From a2734b18c133020520183292c9d2ff0593040a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Brais=20Gab=C3=ADn?= Date: Mon, 25 Apr 2022 23:04:26 +0200 Subject: [PATCH] Remove Unnecesary @Nested (#4740) --- .../detekt/api/ConfigPropertySpec.kt | 607 +++--- .../arturbosch/detekt/api/EntitySpec.kt | 113 +- .../arturbosch/detekt/api/MetricSpec.kt | 25 +- .../detekt/api/PropertiesAwareSpec.kt | 73 +- .../api/internal/RuleSetConfigPropertySpec.kt | 67 +- .../detekt/api/internal/SimpleGlobSpec.kt | 395 ++-- .../gitlab/arturbosch/detekt/cli/MainSpec.kt | 3 +- .../arturbosch/detekt/cli/PathFiltersSpec.kt | 164 +- .../arturbosch/detekt/cli/ReportPathSpec.kt | 175 +- .../detekt/cli/runners/AstPrinterSpec.kt | 66 +- .../detekt/cli/runners/ElementPrinterSpec.kt | 17 +- .../detekt/core/CorrectableRulesFirstSpec.kt | 55 +- .../detekt/core/CustomRuleSetProviderSpec.kt | 25 +- .../detekt/core/FileProcessorLocatorSpec.kt | 35 +- .../detekt/core/KtTreeCompilerSpec.kt | 117 +- .../detekt/core/TopLevelAutoCorrectSpec.kt | 69 +- .../core/baseline/BaselineFacadeSpec.kt | 145 +- .../baseline/BaselineFilteredResultSpec.kt | 59 +- .../core/baseline/BaselineFormatSpec.kt | 122 +- .../baseline/BaselineResultMappingSpec.kt | 163 +- .../core/config/CheckConfigurationSpec.kt | 129 +- .../detekt/core/config/CompositeConfigSpec.kt | 85 +- .../config/DefaultConfigValidationSpec.kt | 21 +- .../detekt/core/config/ValidateConfigSpec.kt | 330 ++-- .../core/reporting/OutputReportsSpec.kt | 148 +- .../reporting/console/ComplexityReportSpec.kt | 35 +- .../console/FileBasedFindingsReportSpec.kt | 70 +- .../reporting/console/FindingsReportSpec.kt | 108 +- .../console/LiteFindingsReportSpec.kt | 60 +- .../console/NotificationReportSpec.kt | 25 +- .../console/ProjectStatisticsReportSpec.kt | 31 +- .../detekt/core/rules/MultiRuleSpec.kt | 93 +- .../detekt/core/rules/RuleSetLocatorSpec.kt | 35 +- .../detekt/core/rules/RuleSetSpec.kt | 72 +- .../core/rules/SingleRuleProviderSpec.kt | 61 +- .../core/settings/EnvironmentFacadeSpec.kt | 23 +- .../formatting/ArgumentListWrappingSpec.kt | 85 +- .../detekt/formatting/AutoCorrectLevelSpec.kt | 75 +- .../detekt/formatting/ChainWrappingSpec.kt | 19 +- .../detekt/formatting/FinalNewlineSpec.kt | 63 +- .../detekt/formatting/ImportOrderingSpec.kt | 162 +- .../detekt/formatting/IndentationSpec.kt | 76 +- .../detekt/formatting/KtLintMultiRuleSpec.kt | 35 +- .../formatting/MaximumLineLengthSpec.kt | 100 +- .../formatting/ParameterListWrappingSpec.kt | 37 +- .../generator/collection/ConfigurationSpec.kt | 87 +- .../collection/MultiRuleCollectorSpec.kt | 71 +- .../generator/collection/RuleCollectorSpec.kt | 1213 ++++++------ .../RuleSetProviderCollectorSpec.kt | 663 ++++--- .../printer/CliOptionsPrinterSpec.kt | 19 +- .../printer/DeprecatedPrinterSpec.kt | 22 +- .../defaultconfig/ConfigPrinterSpec.kt | 86 +- .../arturbosch/detekt/DetektAndroidSpec.kt | 707 ++++--- .../gitlab/arturbosch/detekt/DetektJvmSpec.kt | 121 +- .../arturbosch/detekt/DetektTaskDslSpec.kt | 1141 ++++++----- .../detekt/DetektTaskMultiModuleSpec.kt | 395 ++-- .../detekt/PluginTaskBehaviorSpec.kt | 162 +- .../detekt/report/ReportMergeSpec.kt | 335 ++-- .../gitlab/arturbosch/detekt/DetektJvmSpec.kt | 86 +- .../detekt/internal/ClassLoaderCacheSpec.kt | 103 +- .../detekt/report/XmlReportMergerSpec.kt | 81 +- .../detekt/metrics/CognitiveComplexitySpec.kt | 416 ++-- .../metrics/ComplexityReportGeneratorSpec.kt | 114 +- .../metrics/processors/CLOCVisitorSpec.kt | 18 +- .../processors/ClassCountVisitorSpec.kt | 51 +- .../CognitiveComplexityProcessorSpec.kt | 17 +- .../processors/ComplexityVisitorSpec.kt | 23 +- .../processors/FieldCountVisitorSpec.kt | 18 +- .../processors/KtFileCountVisitorSpec.kt | 20 +- .../metrics/processors/LLOCVisitorSpec.kt | 36 +- .../metrics/processors/LOCVisitorSpec.kt | 18 +- .../processors/MethodCountVisitorSpec.kt | 14 +- .../processors/PackageCountVisitorSpec.kt | 26 +- .../metrics/processors/SLOCVisitorSpec.kt | 18 +- .../parser/KotlinEnvironmentUtilsSpec.kt | 32 +- .../report/html/HtmlOutputReportSpec.kt | 235 ++- .../detekt/report/html/HtmlUtilsSpec.kt | 214 ++- .../report/sarif/SarifOutputReportSpec.kt | 83 +- .../detekt/report/txt/TxtOutputReportSpec.kt | 61 +- .../detekt/report/xml/XmlOutputFormatSpec.kt | 298 ++- .../rules/complexity/ComplexConditionSpec.kt | 25 +- .../rules/complexity/ComplexMethodSpec.kt | 338 ++-- .../rules/complexity/LabeledExpressionSpec.kt | 261 ++- .../detekt/rules/complexity/LongMethodSpec.kt | 231 ++- .../rules/complexity/LongParameterListSpec.kt | 234 ++- .../rules/complexity/MethodOverloadingSpec.kt | 408 ++-- .../rules/complexity/NamedArgumentsSpec.kt | 412 ++-- .../rules/complexity/NestedBlockDepthSpec.kt | 94 +- .../ReplaceSafeCallChainWithRunSpec.kt | 95 +- .../StringLiteralDuplicationSpec.kt | 218 ++- .../rules/complexity/TooManyFunctionsSpec.kt | 402 ++-- .../coroutines/GlobalCoroutineUsageSpec.kt | 105 +- .../RedundantSuspendModifierSpec.kt | 199 +- .../coroutines/SleepInsteadOfDelaySpec.kt | 104 +- .../SuspendFunWithFlowReturnTypeSpec.kt | 455 +++-- .../AbsentOrWrongFileLicenseSpec.kt | 304 ++- .../CommentOverPrivateMethodSpec.kt | 63 +- .../CommentOverPrivatePropertiesSpec.kt | 79 +- .../documentation/DeprecatedBlockTagSpec.kt | 233 ++- .../documentation/EndOfSentenceFormatSpec.kt | 333 ++-- .../rules/documentation/KDocStyleSpec.kt | 19 +- .../OutdatedDocumentationSpec.kt | 798 ++++---- .../UndocumentedPublicClassSpec.kt | 333 ++-- .../UndocumentedPublicFunctionSpec.kt | 276 ++- .../UndocumentedPublicPropertySpec.kt | 510 +++-- .../rules/empty/EmptyBlocksMultiRuleSpec.kt | 71 +- .../detekt/rules/empty/EmptyClassBlockSpec.kt | 105 +- .../detekt/rules/empty/EmptyCodeSpec.kt | 199 +- .../empty/EmptyDefaultConstructorSpec.kt | 161 +- .../detekt/rules/empty/EmptyElseBlockSpec.kt | 180 +- .../rules/empty/EmptyFunctionBlockSpec.kt | 176 +- .../detekt/rules/empty/EmptyIfBlockSpec.kt | 177 +- .../rules/bugs/CastToNullableTypeSpec.kt | 66 +- .../detekt/rules/bugs/DeprecationSpec.kt | 61 +- .../bugs/DontDowncastCollectionTypesSpec.kt | 736 ++++---- .../bugs/DoubleMutabilityForCollectionSpec.kt | 1678 ++++++++--------- .../bugs/DuplicateCaseInWhenExpressionSpec.kt | 57 +- .../ElseCaseInsteadOfExhaustiveWhenSpec.kt | 481 +++-- .../EqualsAlwaysReturnsTrueOrFalseSpec.kt | 65 +- .../rules/bugs/EqualsWithHashCodeExistSpec.kt | 180 +- .../detekt/rules/bugs/ExitOutsideMainSpec.kt | 119 +- .../bugs/ExplicitGarbageCollectionCallSpec.kt | 25 +- .../detekt/rules/bugs/HasPlatformTypeSpec.kt | 111 +- .../rules/bugs/ImplicitDefaultLocaleSpec.kt | 165 +- .../rules/bugs/ImplicitUnitReturnTypeSpec.kt | 85 +- .../IteratorHasNextCallsNextMethodSpec.kt | 23 +- ...orNotThrowingNoSuchElementExceptionSpec.kt | 23 +- .../detekt/rules/bugs/LateinitUsageSpec.kt | 154 +- .../bugs/MissingPackageDeclarationSpec.kt | 33 +- .../bugs/NullCheckOnMutablePropertySpec.kt | 506 +++-- .../rules/bugs/NullableToStringCallSpec.kt | 306 ++- .../rules/bugs/RedundantElseInWhenSpec.kt | 393 ++-- .../UnconditionalJumpStatementInLoopSpec.kt | 591 +++--- .../rules/bugs/UnreachableCatchBlockSpec.kt | 114 +- .../detekt/rules/bugs/UnreachableCodeSpec.kt | 273 ++- .../detekt/rules/bugs/UnsafeCastSpec.kt | 75 +- .../rules/bugs/UnusedUnaryOperatorSpec.kt | 210 +-- .../bugs/WrongEqualsTypeParameterSpec.kt | 129 +- ...ExceptionRaisedInUnexpectedLocationSpec.kt | 67 +- .../InstanceOfCheckForExceptionSpec.kt | 105 +- .../NotImplementedDeclarationSpec.kt | 55 +- .../exceptions/ObjectExtendsThrowableSpec.kt | 205 +- .../rules/exceptions/PrintStackTraceSpec.kt | 76 +- .../exceptions/RethrowCaughtExceptionSpec.kt | 339 ++-- .../rules/exceptions/ReturnFromFinallySpec.kt | 415 ++-- .../exceptions/SwallowedExceptionSpec.kt | 462 +++-- .../ThrowingExceptionFromFinallySpec.kt | 71 +- .../exceptions/ThrowingExceptionInMainSpec.kt | 141 +- ...wingExceptionsWithoutMessageOrCauseSpec.kt | 60 +- .../ThrowingNewInstanceOfSameExceptionSpec.kt | 86 +- .../exceptions/TooGenericExceptionSpec.kt | 21 +- .../TooGenericExceptionThrownSpec.kt | 81 +- .../rules/naming/BooleanPropertyNamingSpec.kt | 1152 ++++++----- .../detekt/rules/naming/ClassNamingSpec.kt | 99 +- .../naming/ConstructorParameterNamingSpec.kt | 95 +- .../detekt/rules/naming/EnumNamingSpec.kt | 99 +- .../rules/naming/ForbiddenClassNameSpec.kt | 119 +- .../detekt/rules/naming/FunctionNamingSpec.kt | 171 +- .../naming/InvalidPackageDeclarationSpec.kt | 196 +- .../rules/naming/LambdaParameterNamingSpec.kt | 212 +-- .../naming/MatchingDeclarationNameSpec.kt | 400 ++-- .../naming/MemberNameEqualsClassNameSpec.kt | 478 +++-- .../NamingConventionCustomPatternSpec.kt | 205 +- .../naming/NamingConventionLengthSpec.kt | 168 +- .../detekt/rules/naming/NamingRulesSpec.kt | 22 +- .../rules/naming/NoNameShadowingSpec.kt | 174 +- .../NonBooleanPropertyWithPrefixIsSpec.kt | 434 +++-- .../detekt/rules/naming/PackageNamingSpec.kt | 57 +- .../detekt/rules/naming/VariableNamingSpec.kt | 127 +- .../rules/performance/ForEachOnRangeSpec.kt | 94 +- .../rules/performance/SpreadOperatorSpec.kt | 389 ++-- .../UnnecessaryTemporaryInstantiationSpec.kt | 23 +- .../rules/style/CanBeNonNullableSpec.kt | 1257 ++++++------ .../detekt/rules/style/ClassOrderingSpec.kt | 425 +++-- .../style/CollapsibleIfStatementsSpec.kt | 181 +- .../style/DataClassContainsFunctionsSpec.kt | 94 +- .../style/DataClassShouldBeImmutableSpec.kt | 133 +- ...turingDeclarationWithTooManyEntriesSpec.kt | 166 +- .../detekt/rules/style/EqualsNullCallSpec.kt | 57 +- .../rules/style/EqualsOnSignatureLineSpec.kt | 260 ++- .../style/ExplicitItLambdaParameterSpec.kt | 115 +- .../rules/style/ExpressionBodySyntaxSpec.kt | 242 ++- .../rules/style/ForbiddenCommentSpec.kt | 354 ++-- .../detekt/rules/style/ForbiddenImportSpec.kt | 206 +- .../rules/style/ForbiddenMethodCallSpec.kt | 740 ++++---- .../style/ForbiddenPublicDataClassSpec.kt | 318 ++-- .../detekt/rules/style/ForbiddenVoidSpec.kt | 283 ++- .../LibraryCodeMustSpecifyReturnTypeSpec.kt | 334 ++-- .../LibraryEntitiesShouldNotBePublicSpec.kt | 197 +- .../LoopWithTooManyJumpStatementsSpec.kt | 36 +- .../detekt/rules/style/MagicNumberSpec.kt | 1551 ++++++++------- .../detekt/rules/style/MaxLineLengthSpec.kt | 386 ++-- .../detekt/rules/style/MayBeConstSpec.kt | 600 +++--- .../detekt/rules/style/ModifierOrderSpec.kt | 248 ++- .../style/MultilineLambdaItParameterSpec.kt | 311 ++- .../style/NestedClassesVisibilitySpec.kt | 197 +- .../rules/style/NewLineAtEndOfFileSpec.kt | 35 +- .../detekt/rules/style/NoTabsSpec.kt | 31 +- .../rules/style/ObjectLiteralToLambdaSpec.kt | 898 +++++---- .../style/OptionalAbstractKeywordSpec.kt | 87 +- .../rules/style/OptionalWhenBracesSpec.kt | 178 +- .../rules/style/RedundantExplicitTypeSpec.kt | 233 ++- .../RedundantVisibilityModifierRuleSpec.kt | 355 ++-- .../detekt/rules/style/ReturnCountSpec.kt | 802 ++++---- .../detekt/rules/style/SafeCastSpec.kt | 101 +- ...SerialVersionUIDInSerializableClassSpec.kt | 209 +- .../SpacingBetweenPackageAndImportsSpec.kt | 184 +- .../detekt/rules/style/ThrowsCountSpec.kt | 458 +++-- .../rules/style/TrailingWhitespaceSpec.kt | 108 +- .../style/UnnecessaryAbstractClassSpec.kt | 426 +++-- .../UnnecessaryAnnotationUseSiteTargetSpec.kt | 115 +- .../rules/style/UnnecessaryApplySpec.kt | 746 ++++---- .../rules/style/UnnecessaryInheritanceSpec.kt | 33 +- .../rules/style/UnnecessaryInnerClassSpec.kt | 485 +++-- .../detekt/rules/style/UnnecessaryLetSpec.kt | 715 ++++--- .../rules/style/UnnecessaryParenthesesSpec.kt | 325 ++-- .../rules/style/UntilInsteadOfRangeToSpec.kt | 121 +- .../detekt/rules/style/UnusedImportsSpec.kt | 1085 ++++++----- .../style/UseAnyOrNoneInsteadOfFindSpec.kt | 166 +- .../UseArrayLiteralsInAnnotationsSpec.kt | 54 +- .../detekt/rules/style/UseCheckNotNullSpec.kt | 62 +- .../detekt/rules/style/UseCheckOrErrorSpec.kt | 290 ++- .../detekt/rules/style/UseDataClassSpec.kt | 654 ++++--- .../rules/style/UseEmptyCounterpartSpec.kt | 133 +- .../rules/style/UseIfInsteadOfWhenSpec.kt | 101 +- .../rules/style/UseRequireNotNullSpec.kt | 62 +- .../detekt/rules/style/UseRequireSpec.kt | 324 ++-- .../rules/style/UselessCallOnNotNullSpec.kt | 470 +++-- .../UtilityClassWithPublicConstructorSpec.kt | 82 +- .../detekt/rules/style/WildcardImportSpec.kt | 144 +- .../rules/style/optional/OptionalUnitSpec.kt | 673 ++++--- .../optional/PreferToOverPairSyntaxSpec.kt | 91 +- .../detekt/rules/RuleProviderConfigSpec.kt | 33 +- .../detekt/rules/RuleProviderSpec.kt | 33 +- .../detekt/rules/SuppressingSpec.kt | 67 +- .../LicenceHeaderLoaderExtensionSpec.kt | 29 +- .../api/DefaultConfigurationProviderSpec.kt | 17 +- .../github/detekt/tooling/api/PluginsSpec.kt | 53 +- 238 files changed, 25745 insertions(+), 26846 deletions(-) diff --git a/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/ConfigPropertySpec.kt b/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/ConfigPropertySpec.kt index 97d724cbd37..1bab275bc11 100644 --- a/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/ConfigPropertySpec.kt +++ b/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/ConfigPropertySpec.kt @@ -10,16 +10,37 @@ import java.util.concurrent.atomic.AtomicInteger class ConfigPropertySpec { @Nested - inner class `Config property delegate` { + inner class `simple property` { @Nested - inner class `simple property` { + inner class `String property` { + private val configValue = "value" + private val defaultValue = "default" + private val subject = object : TestConfigAware("present" to configValue) { + val present: String by config(defaultValue) + val notPresent: String by config(defaultValue) + } + + @Test + fun `uses the value provided in config if present`() { + assertThat(subject.present).isEqualTo(configValue) + } + + @Test + fun `uses the default value if not present`() { + assertThat(subject.notPresent).isEqualTo(defaultValue) + } + } + + @Nested + inner class `Int property` { + private val configValue = 99 + private val defaultValue = -1 + @Nested - inner class `String property` { - private val configValue = "value" - private val defaultValue = "default" + inner class `defined as number` { private val subject = object : TestConfigAware("present" to configValue) { - val present: String by config(defaultValue) - val notPresent: String by config(defaultValue) + val present: Int by config(defaultValue) + val notPresent: Int by config(defaultValue) } @Test @@ -34,394 +55,370 @@ class ConfigPropertySpec { } @Nested - inner class `Int property` { - private val configValue = 99 - private val defaultValue = -1 + inner class `defined as string` { + private val subject = object : TestConfigAware("present" to "$configValue") { + val present: Int by config(defaultValue) + } - @Nested - inner class `defined as number` { - private val subject = object : TestConfigAware("present" to configValue) { - val present: Int by config(defaultValue) - val notPresent: Int by config(defaultValue) - } + @Test + fun `uses the value provided in config if present`() { + assertThat(subject.present).isEqualTo(configValue) + } + } + } - @Test - fun `uses the value provided in config if present`() { - assertThat(subject.present).isEqualTo(configValue) - } + @Nested + inner class `Boolean property` { + private val configValue = false + private val defaultValue = true - @Test - fun `uses the default value if not present`() { - assertThat(subject.notPresent).isEqualTo(defaultValue) - } + @Nested + inner class `defined as Boolean` { + private val subject = object : TestConfigAware("present" to configValue) { + val present: Boolean by config(defaultValue) + val notPresent: Boolean by config(defaultValue) } - @Nested - inner class `defined as string` { - private val subject = object : TestConfigAware("present" to "$configValue") { - val present: Int by config(defaultValue) - } + @Test + fun `uses the value provided in config if present`() { + assertThat(subject.present).isEqualTo(configValue) + } - @Test - fun `uses the value provided in config if present`() { - assertThat(subject.present).isEqualTo(configValue) - } + @Test + fun `uses the default value if not present`() { + assertThat(subject.notPresent).isEqualTo(defaultValue) } } @Nested - inner class `Boolean property` { - private val configValue = false - private val defaultValue = true + inner class `defined as string` { + private val subject = object : TestConfigAware("present" to "$configValue") { + val present: Boolean by config(defaultValue) + } - @Nested - inner class `defined as Boolean` { - private val subject = object : TestConfigAware("present" to configValue) { - val present: Boolean by config(defaultValue) - val notPresent: Boolean by config(defaultValue) - } + @Test + fun `uses the value provided in config if present`() { + assertThat(subject.present).isEqualTo(configValue) + } + } + } - @Test - fun `uses the value provided in config if present`() { - assertThat(subject.present).isEqualTo(configValue) - } + @Nested + inner class `List property` { + private val defaultValue = listOf("x") - @Test - fun `uses the default value if not present`() { - assertThat(subject.notPresent).isEqualTo(defaultValue) - } + @Nested + inner class `defined as list` { + private val subject = object : TestConfigAware("present" to "a,b,c") { + val present: List by config(defaultValue) + val notPresent: List by config(defaultValue) } - @Nested - inner class `defined as string` { - private val subject = object : TestConfigAware("present" to "$configValue") { - val present: Boolean by config(defaultValue) - } + @Test + fun `uses the value provided in config if present`() { + assertThat(subject.present).isEqualTo(listOf("a", "b", "c")) + } - @Test - fun `uses the value provided in config if present`() { - assertThat(subject.present).isEqualTo(configValue) - } + @Test + fun `uses the default value if not present`() { + assertThat(subject.notPresent).isEqualTo(defaultValue) } } @Nested - inner class `List property` { - private val defaultValue = listOf("x") - - @Nested - inner class `defined as list` { - private val subject = object : TestConfigAware("present" to "a,b,c") { - val present: List by config(defaultValue) - val notPresent: List by config(defaultValue) - } - - @Test - fun `uses the value provided in config if present`() { - assertThat(subject.present).isEqualTo(listOf("a", "b", "c")) - } + inner class `defined as comma separated string` { + private val subject = object : TestConfigAware("present" to "a,b,c") { + val present: List by config(defaultValue) + val notPresent: List by config(defaultValue) + } - @Test - fun `uses the default value if not present`() { - assertThat(subject.notPresent).isEqualTo(defaultValue) - } + @Test + fun `uses the value provided in config if present`() { + assertThat(subject.present).isEqualTo(listOf("a", "b", "c")) } - @Nested - inner class `defined as comma separated string` { - private val subject = object : TestConfigAware("present" to "a,b,c") { - val present: List by config(defaultValue) - val notPresent: List by config(defaultValue) - } + @Test + fun `uses the default value if not present`() { + assertThat(subject.notPresent).isEqualTo(defaultValue) + } + } + } + } - @Test - fun `uses the value provided in config if present`() { - assertThat(subject.present).isEqualTo(listOf("a", "b", "c")) - } + @Nested + inner class `invalid type` { + @Nested + inner class `Long property` { + private val defaultValue = 1L + private val subject = object : TestConfigAware() { + val prop: Long by config(defaultValue) + } - @Test - fun `uses the default value if not present`() { - assertThat(subject.notPresent).isEqualTo(defaultValue) - } - } + @Test + fun `throws`() { + assertThatThrownBy { subject.prop } + .isInstanceOf(IllegalStateException::class.java) + .hasMessageContaining("is not supported") } } @Nested - inner class `invalid type` { - @Nested - inner class `Long property` { - private val defaultValue = 1L - private val subject = object : TestConfigAware() { - val prop: Long by config(defaultValue) - } + inner class `Regex property` { + private val defaultValue = Regex("a") + private val subject = object : TestConfigAware() { + val prop: Regex by config(defaultValue) + } - @Test - fun `throws`() { - assertThatThrownBy { subject.prop } - .isInstanceOf(IllegalStateException::class.java) - .hasMessageContaining("is not supported") - } + @Test + fun `throws`() { + assertThatThrownBy { subject.prop } + .isInstanceOf(IllegalStateException::class.java) + .hasMessageContaining("is not supported") } + } - @Nested - inner class `Regex property` { - private val defaultValue = Regex("a") - private val subject = object : TestConfigAware() { - val prop: Regex by config(defaultValue) - } + @Nested + inner class `Set property` { + private val defaultValue = setOf("a") + private val subject = object : TestConfigAware() { + val prop: Set by config(defaultValue) + } - @Test - fun `throws`() { - assertThatThrownBy { subject.prop } - .isInstanceOf(IllegalStateException::class.java) - .hasMessageContaining("is not supported") - } + @Test + fun `throws`() { + assertThatThrownBy { subject.prop } + .isInstanceOf(IllegalStateException::class.java) + .hasMessageContaining("is not supported") } + } - @Nested - inner class `Set property` { - private val defaultValue = setOf("a") - private val subject = object : TestConfigAware() { - val prop: Set by config(defaultValue) - } + @Nested + inner class `List of Int` { + private val defaultValue = listOf(1) + private val subject = object : TestConfigAware() { + val prop: List by config(defaultValue) + } - @Test - fun `throws`() { - assertThatThrownBy { subject.prop } - .isInstanceOf(IllegalStateException::class.java) - .hasMessageContaining("is not supported") - } + @Test + fun `throws`() { + assertThatThrownBy { subject.prop } + .isInstanceOf(IllegalStateException::class.java) + .hasMessageContaining("lists of strings are supported") } + } + } + @Nested + inner class `transform` { + @Nested + inner class `primitive` { @Nested - inner class `List of Int` { - private val defaultValue = listOf(1) - private val subject = object : TestConfigAware() { - val prop: List by config(defaultValue) + inner class `String property is transformed to regex` { + private val defaultValue = ".*" + private val configValue = "[a-z]+" + private val subject = object : TestConfigAware("present" to configValue) { + val present: Regex by config(defaultValue) { it.toRegex() } + val notPresent: Regex by config(defaultValue) { it.toRegex() } } @Test - fun `throws`() { - assertThatThrownBy { subject.prop } - .isInstanceOf(IllegalStateException::class.java) - .hasMessageContaining("lists of strings are supported") + fun `applies the mapping function to the configured value`() { + assertThat(subject.present.matches("abc")).isTrue + assertThat(subject.present.matches("123")).isFalse() } - } - } - @Nested - inner class `transform` { - @Nested - inner class `primitive` { - @Nested - inner class `String property is transformed to regex` { - private val defaultValue = ".*" - private val configValue = "[a-z]+" - private val subject = object : TestConfigAware("present" to configValue) { - val present: Regex by config(defaultValue) { it.toRegex() } - val notPresent: Regex by config(defaultValue) { it.toRegex() } - } - - @Test - fun `applies the mapping function to the configured value`() { - assertThat(subject.present.matches("abc")).isTrue - assertThat(subject.present.matches("123")).isFalse() - } - - @Test - fun `applies the mapping function to the default`() { - assertThat(subject.notPresent.matches("abc")).isTrue - assertThat(subject.notPresent.matches("123")).isTrue - } - } - - @Nested - inner class `Int property is transformed to String` { - private val configValue = 99 - private val defaultValue = -1 - private val subject = object : TestConfigAware("present" to configValue) { - val present: String by config(defaultValue) { it.toString() } - val notPresent: String by config(defaultValue) { it.toString() } - } - - @Test - fun `applies the mapping function to the configured value`() { - assertThat(subject.present).isEqualTo("$configValue") - } - - @Test - fun `applies the mapping function to the default`() { - assertThat(subject.notPresent).isEqualTo("$defaultValue") - } - } - - @Nested - inner class `Boolean property is transformed to String` { - private val configValue = true - private val defaultValue = false - private val subject = object : TestConfigAware("present" to configValue) { - val present: String by config(defaultValue) { it.toString() } - val notPresent: String by config(defaultValue) { it.toString() } - } - - @Test - fun `applies the mapping function to the configured value`() { - assertThat(subject.present).isEqualTo("$configValue") - } - - @Test - fun `applies the mapping function to the default`() { - assertThat(subject.notPresent).isEqualTo("$defaultValue") - } - } - - @Nested - inner class `Boolean property is transformed to String with function reference` { - private val defaultValue = false - private val subject = object : TestConfigAware() { - val prop1: String by config(defaultValue, Boolean::toString) - val prop2: String by config(transformer = Boolean::toString, defaultValue = defaultValue) - } - - @Test - fun `transforms properties`() { - assertThat(subject.prop1).isEqualTo("$defaultValue") - assertThat(subject.prop2).isEqualTo("$defaultValue") - } + @Test + fun `applies the mapping function to the default`() { + assertThat(subject.notPresent.matches("abc")).isTrue + assertThat(subject.notPresent.matches("123")).isTrue } } @Nested - inner class `list of strings` { - private val defaultValue = listOf("99") - private val subject = object : TestConfigAware("present" to "1,2,3") { - val present: Int by config(defaultValue) { it.sumOf(String::toInt) } - val notPresent: Int by config(defaultValue) { it.sumOf(String::toInt) } + inner class `Int property is transformed to String` { + private val configValue = 99 + private val defaultValue = -1 + private val subject = object : TestConfigAware("present" to configValue) { + val present: String by config(defaultValue) { it.toString() } + val notPresent: String by config(defaultValue) { it.toString() } } @Test - fun `applies transformer to list configured`() { - assertThat(subject.present).isEqualTo(6) + fun `applies the mapping function to the configured value`() { + assertThat(subject.present).isEqualTo("$configValue") } @Test - fun `applies transformer to default list`() { - assertThat(subject.notPresent).isEqualTo(99) + fun `applies the mapping function to the default`() { + assertThat(subject.notPresent).isEqualTo("$defaultValue") } } @Nested - inner class `empty list of strings` { - private val subject = object : TestConfigAware() { - val defaultValue: List = emptyList() - val prop1: List by config(defaultValue) { it.map(String::toInt) } - val prop2: List by config(emptyList()) { it.map(String::toInt) } + inner class `Boolean property is transformed to String` { + private val configValue = true + private val defaultValue = false + private val subject = object : TestConfigAware("present" to configValue) { + val present: String by config(defaultValue) { it.toString() } + val notPresent: String by config(defaultValue) { it.toString() } } @Test - fun `can be defined as variable`() { - assertThat(subject.prop1).isEmpty() + fun `applies the mapping function to the configured value`() { + assertThat(subject.present).isEqualTo("$configValue") } @Test - fun `can be defined using listOf`() { - assertThat(subject.prop2).isEmpty() + fun `applies the mapping function to the default`() { + assertThat(subject.notPresent).isEqualTo("$defaultValue") } } @Nested - inner class `memoization` { + inner class `Boolean property is transformed to String with function reference` { + private val defaultValue = false private val subject = object : TestConfigAware() { - val counter = AtomicInteger(0) - val prop: String by config(1) { - counter.getAndIncrement() - it.toString() - } - - fun useProperty(): String { - return "something with $prop" - } + val prop1: String by config(defaultValue, Boolean::toString) + val prop2: String by config(transformer = Boolean::toString, defaultValue = defaultValue) } @Test - fun `transformer is called only once`() { - repeat(5) { - assertThat(subject.useProperty()).isEqualTo("something with 1") - } - assertThat(subject.counter.get()).isEqualTo(1) + fun `transforms properties`() { + assertThat(subject.prop1).isEqualTo("$defaultValue") + assertThat(subject.prop2).isEqualTo("$defaultValue") } } } - @OptIn(UnstableApi::class) @Nested - inner class `configWithFallback` { - @Nested - inner class `primitive` { - private val configValue = 99 - private val defaultValue = 0 - private val fallbackValue = -1 - private val subject = - object : TestConfigAware("present" to "$configValue", "fallback" to fallbackValue) { - private val fallback: Int by config(42) - private val missing: Int by config(42) - val present: Int by configWithFallback(::fallback, defaultValue) - val notPresentWithFallback: Int by configWithFallback(::fallback, defaultValue) - val notPresentFallbackMissing: Int by configWithFallback(::missing, defaultValue) - } + inner class `list of strings` { + private val defaultValue = listOf("99") + private val subject = object : TestConfigAware("present" to "1,2,3") { + val present: Int by config(defaultValue) { it.sumOf(String::toInt) } + val notPresent: Int by config(defaultValue) { it.sumOf(String::toInt) } + } - @Test - fun `uses the value provided in config if present`() { - assertThat(subject.present).isEqualTo(configValue) - } + @Test + fun `applies transformer to list configured`() { + assertThat(subject.present).isEqualTo(6) + } - @Test - fun `uses the value from fallback property if value is missing and fallback exists`() { - assertThat(subject.notPresentWithFallback).isEqualTo(fallbackValue) - } + @Test + fun `applies transformer to default list`() { + assertThat(subject.notPresent).isEqualTo(99) + } + } - @Test - fun `uses the default value if not present`() { - assertThat(subject.notPresentFallbackMissing).isEqualTo(defaultValue) - } + @Nested + inner class `empty list of strings` { + private val subject = object : TestConfigAware() { + val defaultValue: List = emptyList() + val prop1: List by config(defaultValue) { it.map(String::toInt) } + val prop2: List by config(emptyList()) { it.map(String::toInt) } } - @Nested - inner class `with transformation` { - private val configValue = 99 - private val defaultValue = 0 - private val fallbackValue = -1 - private val fallbackOffset = 10 - private val subject = object : TestConfigAware("present" to configValue, "fallback" to fallbackValue) { - private val fallback: String by config(42) { (it + fallbackOffset).toString() } - private val missing: String by config(42) { (it + fallbackOffset).toString() } - val present: String by configWithFallback(::fallback, defaultValue) { v -> - v.toString() - } - val notPresentWithFallback: String by configWithFallback(::fallback, defaultValue) { v -> - v.toString() - } - val notPresentFallbackMissing: String by configWithFallback(::missing, defaultValue) { v -> - v.toString() - } + @Test + fun `can be defined as variable`() { + assertThat(subject.prop1).isEmpty() + } + + @Test + fun `can be defined using listOf`() { + assertThat(subject.prop2).isEmpty() + } + } + + @Nested + inner class `memoization` { + private val subject = object : TestConfigAware() { + val counter = AtomicInteger(0) + val prop: String by config(1) { + counter.getAndIncrement() + it.toString() } - @Test - fun `uses the value provided in config if present`() { - assertThat(subject.present).isEqualTo("$configValue") + fun useProperty(): String { + return "something with $prop" } + } - @Test - fun `transforms the value from fallback property if value is missing and fallback exists`() { - assertThat(subject.notPresentWithFallback).isEqualTo("${fallbackValue + fallbackOffset}") + @Test + fun `transformer is called only once`() { + repeat(5) { + assertThat(subject.useProperty()).isEqualTo("something with 1") } + assertThat(subject.counter.get()).isEqualTo(1) + } + } + } - @Test - fun `uses the default value if not present`() { - assertThat(subject.notPresentFallbackMissing).isEqualTo("$defaultValue") + @OptIn(UnstableApi::class) + @Nested + inner class `configWithFallback` { + @Nested + inner class `primitive` { + private val configValue = 99 + private val defaultValue = 0 + private val fallbackValue = -1 + private val subject = + object : TestConfigAware("present" to "$configValue", "fallback" to fallbackValue) { + private val fallback: Int by config(42) + private val missing: Int by config(42) + val present: Int by configWithFallback(::fallback, defaultValue) + val notPresentWithFallback: Int by configWithFallback(::fallback, defaultValue) + val notPresentFallbackMissing: Int by configWithFallback(::missing, defaultValue) + } + + @Test + fun `uses the value provided in config if present`() { + assertThat(subject.present).isEqualTo(configValue) + } + + @Test + fun `uses the value from fallback property if value is missing and fallback exists`() { + assertThat(subject.notPresentWithFallback).isEqualTo(fallbackValue) + } + + @Test + fun `uses the default value if not present`() { + assertThat(subject.notPresentFallbackMissing).isEqualTo(defaultValue) + } + } + + @Nested + inner class `with transformation` { + private val configValue = 99 + private val defaultValue = 0 + private val fallbackValue = -1 + private val fallbackOffset = 10 + private val subject = object : TestConfigAware("present" to configValue, "fallback" to fallbackValue) { + private val fallback: String by config(42) { (it + fallbackOffset).toString() } + private val missing: String by config(42) { (it + fallbackOffset).toString() } + val present: String by configWithFallback(::fallback, defaultValue) { v -> + v.toString() + } + val notPresentWithFallback: String by configWithFallback(::fallback, defaultValue) { v -> + v.toString() + } + val notPresentFallbackMissing: String by configWithFallback(::missing, defaultValue) { v -> + v.toString() } } + + @Test + fun `uses the value provided in config if present`() { + assertThat(subject.present).isEqualTo("$configValue") + } + + @Test + fun `transforms the value from fallback property if value is missing and fallback exists`() { + assertThat(subject.notPresentWithFallback).isEqualTo("${fallbackValue + fallbackOffset}") + } + + @Test + fun `uses the default value if not present`() { + assertThat(subject.notPresentFallbackMissing).isEqualTo("$defaultValue") + } } } } diff --git a/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/EntitySpec.kt b/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/EntitySpec.kt index 68682ff7766..94834d41285 100644 --- a/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/EntitySpec.kt +++ b/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/EntitySpec.kt @@ -12,84 +12,81 @@ import java.nio.file.Paths class EntitySpec { - @Nested - inner class `entity signatures` { - private val path = Paths.get("/full/path/to/Test.kt") - private val code = compileContentForTest( - """ - package test + private val path = Paths.get("/full/path/to/Test.kt") + private val code = compileContentForTest( + """ + package test - class C : Any() { + class C : Any() { - private fun memberFun(): Int = 5 - } + private fun memberFun(): Int = 5 + } - fun topLevelFun(number: Int) = Unit - """.trimIndent(), - path.toString() - ) + fun topLevelFun(number: Int) = Unit + """.trimIndent(), + path.toString() + ) - @Nested - inner class `Named functions` { + @Nested + inner class `Named functions` { - private val functions = code.collectDescendantsOfType() + private val functions = code.collectDescendantsOfType() - @Test - fun `includes full function header, class name and filename`() { - val memberFunction = functions.first { it.name == "memberFun" } + @Test + fun `includes full function header, class name and filename`() { + val memberFunction = functions.first { it.name == "memberFun" } - assertThat(Entity.atName(memberFunction).signature) - .isEqualTo("Test.kt\$C\$private fun memberFun(): Int") - } + assertThat(Entity.atName(memberFunction).signature) + .isEqualTo("Test.kt\$C\$private fun memberFun(): Int") + } - @Test - fun `includes full function header and filename for a top level function`() { - val topLevelFunction = functions.first { it.name == "topLevelFun" } + @Test + fun `includes full function header and filename for a top level function`() { + val topLevelFunction = functions.first { it.name == "topLevelFun" } - assertThat(Entity.atName(topLevelFunction).signature) - .isEqualTo("Test.kt\$fun topLevelFun(number: Int)") - } + assertThat(Entity.atName(topLevelFunction).signature) + .isEqualTo("Test.kt\$fun topLevelFun(number: Int)") + } - @Test - fun `includes function name in entity compact`() { - val memberFunction = functions.first { it.name == "memberFun" } + @Test + fun `includes function name in entity compact`() { + val memberFunction = functions.first { it.name == "memberFun" } - assertThat(Entity.atName(memberFunction).compact()) - .isEqualTo("[memberFun] at $path:5:17") - } + assertThat(Entity.atName(memberFunction).compact()) + .isEqualTo("[memberFun] at $path:5:17") } + } - @Nested - inner class `Classes` { - private val clazz = requireNotNull(code.findDescendantOfType()) + @Nested + inner class `Classes` { + private val clazz = requireNotNull(code.findDescendantOfType()) - @Test - fun `includes full class signature`() { - assertThat(Entity.atName(clazz).signature).isEqualTo("Test.kt\$C : Any") - } + @Test + fun `includes full class signature`() { + assertThat(Entity.atName(clazz).signature).isEqualTo("Test.kt\$C : Any") + } - @Test - fun `includes class name in entity compact`() { - assertThat(Entity.atName(clazz).compact()).isEqualTo("[C] at $path:3:7") - } + @Test + fun `includes class name in entity compact`() { + assertThat(Entity.atName(clazz).compact()).isEqualTo("[C] at $path:3:7") } + } - @Nested - inner class `Files` { + @Nested + inner class `Files` { - @Test - fun `includes package and file name in entity signature`() { - assertThat(Entity.from(code).signature).isEqualTo("Test.kt\$test.Test.kt") - assertThat(Entity.atPackageOrFirstDecl(code).signature).isEqualTo("Test.kt\$test.Test.kt") - } + @Test + fun `includes package and file name in entity signature`() { + assertThat(Entity.from(code).signature).isEqualTo("Test.kt\$test.Test.kt") + assertThat(Entity.atPackageOrFirstDecl(code).signature).isEqualTo("Test.kt\$test.Test.kt") + } - @Test - fun `includes file name in entity compact`() { - val expectedResult = "[Test.kt] at $path:1:1" + @Test + fun `includes file name in entity compact`() { + val expectedResult = "[Test.kt] at $path:1:1" - assertThat(Entity.from(code).compact()).isEqualTo(expectedResult) - assertThat(Entity.atPackageOrFirstDecl(code).compact()).isEqualTo(expectedResult) - } + assertThat(Entity.from(code).compact()).isEqualTo(expectedResult) + assertThat(Entity.atPackageOrFirstDecl(code).compact()).isEqualTo(expectedResult) } } } diff --git a/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/MetricSpec.kt b/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/MetricSpec.kt index fed84615b2a..3632fb0144a 100644 --- a/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/MetricSpec.kt +++ b/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/MetricSpec.kt @@ -2,26 +2,21 @@ package io.gitlab.arturbosch.detekt.api import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatIllegalStateException -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class MetricSpec { - @Nested - inner class `Metrics` { - - @Test - fun `should convert double values to int`() { - val metric = Metric("LOC", 0.33, 0.10, 100) - assertThat(metric.doubleValue()).isEqualTo(0.33) - assertThat(metric.doubleThreshold()).isEqualTo(0.10) - } + @Test + fun `should convert double values to int`() { + val metric = Metric("LOC", 0.33, 0.10, 100) + assertThat(metric.doubleValue()).isEqualTo(0.33) + assertThat(metric.doubleThreshold()).isEqualTo(0.10) + } - @Test - fun `should throw error if double value is asked for int metric`() { - assertThatIllegalStateException().isThrownBy { - Metric("LOC", 100, 50).doubleValue() - } + @Test + fun `should throw error if double value is asked for int metric`() { + assertThatIllegalStateException().isThrownBy { + Metric("LOC", 100, 50).doubleValue() } } } diff --git a/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/PropertiesAwareSpec.kt b/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/PropertiesAwareSpec.kt index 0f649acbcc2..707fcc1bcbf 100644 --- a/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/PropertiesAwareSpec.kt +++ b/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/PropertiesAwareSpec.kt @@ -2,54 +2,49 @@ package io.gitlab.arturbosch.detekt.api import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatCode -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import kotlin.random.Random @OptIn(UnstableApi::class) class PropertiesAwareSpec { - @Nested - inner class `Implementations can store and retrieve properties` { - - private val hash = Random(1).nextInt() - private val store = object : PropertiesAware { - override val properties: MutableMap = HashMap() - override fun register(key: String, value: Any) { - properties[key] = value - } - }.apply { - register("bool", true) - register("string", "test") - register("number", 5) - register("set", setOf(1, 2, 3)) - register( - "any", - object : Any() { - override fun equals(other: Any?): Boolean = hashCode() == other.hashCode() - override fun hashCode(): Int = hash - } - ) + private val hash = Random(1).nextInt() + private val store = object : PropertiesAware { + override val properties: MutableMap = HashMap() + override fun register(key: String, value: Any) { + properties[key] = value } + }.apply { + register("bool", true) + register("string", "test") + register("number", 5) + register("set", setOf(1, 2, 3)) + register( + "any", + object : Any() { + override fun equals(other: Any?): Boolean = hashCode() == other.hashCode() + override fun hashCode(): Int = hash + } + ) + } - @Test - fun `can retrieve the actual typed values`() { - assertThat(store.getOrNull("bool")).isEqualTo(true) - assertThat(store.getOrNull("string")).isEqualTo("test") - assertThat(store.getOrNull("number")).isEqualTo(5) - assertThat(store.getOrNull>("set")).isEqualTo(setOf(1, 2, 3)) - assertThat(store.getOrNull("any").hashCode()).isEqualTo(hash) - } + @Test + fun `can retrieve the actual typed values`() { + assertThat(store.getOrNull("bool")).isEqualTo(true) + assertThat(store.getOrNull("string")).isEqualTo("test") + assertThat(store.getOrNull("number")).isEqualTo(5) + assertThat(store.getOrNull>("set")).isEqualTo(setOf(1, 2, 3)) + assertThat(store.getOrNull("any").hashCode()).isEqualTo(hash) + } - @Test - fun `returns null on absent values`() { - assertThat(store.getOrNull("absent")).isEqualTo(null) - } + @Test + fun `returns null on absent values`() { + assertThat(store.getOrNull("absent")).isEqualTo(null) + } - @Test - fun `throws an error on wrong type`() { - assertThatCode { store.getOrNull("bool") } - .isInstanceOf(IllegalStateException::class.java) - } + @Test + fun `throws an error on wrong type`() { + assertThatCode { store.getOrNull("bool") } + .isInstanceOf(IllegalStateException::class.java) } } diff --git a/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/internal/RuleSetConfigPropertySpec.kt b/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/internal/RuleSetConfigPropertySpec.kt index 388c0a67e17..2b1c064bbfa 100644 --- a/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/internal/RuleSetConfigPropertySpec.kt +++ b/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/internal/RuleSetConfigPropertySpec.kt @@ -11,48 +11,45 @@ import org.junit.jupiter.api.Test class RuleSetConfigPropertySpec { @Nested - inner class `Rule set config property delegate` { - @Nested - inner class `boolean property` { - @Test - fun `reads the value in config if present`() { - assertThat(TestRuleSetProvider.android.value(TestConfig("android" to "false"))) - .isEqualTo(false) - } + inner class `boolean property` { + @Test + fun `reads the value in config if present`() { + assertThat(TestRuleSetProvider.android.value(TestConfig("android" to "false"))) + .isEqualTo(false) + } - @Test - fun `uses the default value in config if not present`() { - assertThat(TestRuleSetProvider.android.value(TestConfig())) - .isEqualTo(true) - } + @Test + fun `uses the default value in config if not present`() { + assertThat(TestRuleSetProvider.android.value(TestConfig())) + .isEqualTo(true) } + } - @Nested - inner class `int property` { - @Test - fun `reads the value in config if present`() { - assertThat(TestRuleSetProvider.number.value(TestConfig("number" to "37"))).isEqualTo(37) - } + @Nested + inner class `int property` { + @Test + fun `reads the value in config if present`() { + assertThat(TestRuleSetProvider.number.value(TestConfig("number" to "37"))).isEqualTo(37) + } - @Test - fun `uses the default value in config if not present`() { - assertThat(TestRuleSetProvider.number.value(TestConfig())).isEqualTo(42) - } + @Test + fun `uses the default value in config if not present`() { + assertThat(TestRuleSetProvider.number.value(TestConfig())).isEqualTo(42) } + } - @Nested - inner class `string property` { - @Test - fun `reads the value in config if present`() { - assertThat(TestRuleSetProvider.fileName.value(TestConfig("fileName" to "main.kt"))) - .isEqualTo("main.kt") - } + @Nested + inner class `string property` { + @Test + fun `reads the value in config if present`() { + assertThat(TestRuleSetProvider.fileName.value(TestConfig("fileName" to "main.kt"))) + .isEqualTo("main.kt") + } - @Test - fun `uses the default value in config if not present`() { - assertThat(TestRuleSetProvider.fileName.value(TestConfig())) - .isEqualTo("test.kt") - } + @Test + fun `uses the default value in config if not present`() { + assertThat(TestRuleSetProvider.fileName.value(TestConfig())) + .isEqualTo("test.kt") } } } diff --git a/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/internal/SimpleGlobSpec.kt b/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/internal/SimpleGlobSpec.kt index 4186edef29b..fd78c382848 100644 --- a/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/internal/SimpleGlobSpec.kt +++ b/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/internal/SimpleGlobSpec.kt @@ -7,274 +7,271 @@ import org.junit.jupiter.api.Test class SimpleGlobSpec { @Nested - inner class `glob` { - @Nested - inner class `empty pattern` { - private val subject = SimpleGlob.of("") + inner class `empty pattern` { + private val subject = SimpleGlob.of("") - @Test - fun `matches an empty string`() { - val actual = subject.matches("") - assertThat(actual).isTrue() - } + @Test + fun `matches an empty string`() { + val actual = subject.matches("") + assertThat(actual).isTrue() + } - @Test - fun `does not match a blank string`() { - val actual = subject.matches(" ") - assertThat(actual).isFalse() - } + @Test + fun `does not match a blank string`() { + val actual = subject.matches(" ") + assertThat(actual).isFalse() } + } - @Nested - inner class `blank pattern` { - private val subject = SimpleGlob.of(" \t") + @Nested + inner class `blank pattern` { + private val subject = SimpleGlob.of(" \t") - @Test - fun `matches an empty string`() { - val actual = subject.matches(" \t") - assertThat(actual).isTrue() - } + @Test + fun `matches an empty string`() { + val actual = subject.matches(" \t") + assertThat(actual).isTrue() + } - @Test - fun `does not match a different string`() { - val actual = subject.matches(" ") - assertThat(actual).isFalse() - } + @Test + fun `does not match a different string`() { + val actual = subject.matches(" ") + assertThat(actual).isFalse() } + } - @Nested - inner class `Static pattern` { - private val subject = SimpleGlob.of("abc") + @Nested + inner class `Static pattern` { + private val subject = SimpleGlob.of("abc") - @Test - fun `matches the same string`() { - val actual = subject.matches("abc") - assertThat(actual).isTrue() - } + @Test + fun `matches the same string`() { + val actual = subject.matches("abc") + assertThat(actual).isTrue() + } - @Test - fun `does not match a other string`() { - val actual = subject.matches("aaa") - assertThat(actual).isFalse() - } + @Test + fun `does not match a other string`() { + val actual = subject.matches("aaa") + assertThat(actual).isFalse() } + } + @Nested + inner class `Asterisk wildcard` { @Nested - inner class `Asterisk wildcard` { + inner class `single wildcard` { @Nested - inner class `single wildcard` { - @Nested - inner class `pattern with wildcard at the beginning` { - private val subject = SimpleGlob.of("*xyz") - - @Test - fun `matches pattern exactly`() { - val actual = subject.matches("xyz") - assertThat(actual).isTrue() - } - - @Test - fun `matches pattern with anything before`() { - val actual = subject.matches("abcxyz") - assertThat(actual).isTrue() - } - - @Test - fun `does not match with anything after`() { - val actual = subject.matches("xyzabc") - assertThat(actual).isFalse() - } + inner class `pattern with wildcard at the beginning` { + private val subject = SimpleGlob.of("*xyz") + + @Test + fun `matches pattern exactly`() { + val actual = subject.matches("xyz") + assertThat(actual).isTrue() } - @Nested - inner class `Pattern with wildcard at the end` { - private val subject = SimpleGlob.of("xyz*") - - @Test - fun `matches pattern exactly`() { - val actual = subject.matches("xyz") - assertThat(actual).isTrue() - } - - @Test - fun `matches pattern with anything after`() { - val actual = subject.matches("xyzabc") - assertThat(actual).isTrue() - } - - @Test - fun `does not match with anything before`() { - val actual = subject.matches("abcxyz") - assertThat(actual).isFalse() - } + @Test + fun `matches pattern with anything before`() { + val actual = subject.matches("abcxyz") + assertThat(actual).isTrue() } - @Nested - inner class `Pattern with wildcard at the middle` { - private val subject = SimpleGlob.of("x*yz") - - @Test - fun `matches pattern exactly`() { - val actual = subject.matches("xyz") - assertThat(actual).isTrue() - } - - @Test - fun `matches pattern with anything in between`() { - val actual = subject.matches("xaaaayz") - assertThat(actual).isTrue() - } - - @Test - fun `does not match with anything before`() { - val actual = subject.matches("axyz") - assertThat(actual).isFalse() - } - - @Test - fun `does not match with anything after`() { - val actual = subject.matches("xyza") - assertThat(actual).isFalse() - } + @Test + fun `does not match with anything after`() { + val actual = subject.matches("xyzabc") + assertThat(actual).isFalse() } } @Nested - inner class `multiple wildcards` { - private val subject = SimpleGlob.of("x*yz*") + inner class `Pattern with wildcard at the end` { + private val subject = SimpleGlob.of("xyz*") @Test - fun `matches pattern`() { - val actual = subject.matches("x.aaa.yz.bbb") + fun `matches pattern exactly`() { + val actual = subject.matches("xyz") assertThat(actual).isTrue() } + + @Test + fun `matches pattern with anything after`() { + val actual = subject.matches("xyzabc") + assertThat(actual).isTrue() + } + + @Test + fun `does not match with anything before`() { + val actual = subject.matches("abcxyz") + assertThat(actual).isFalse() + } } - } - @Nested - inner class `Questionmark wildcard` { @Nested - inner class `single wildcard` { - @Nested - inner class `pattern with wildcard at the beginning` { - private val subject = SimpleGlob.of("?xyz") - - @Test - fun `matches with any character before`() { - val actual = subject.matches("_xyz") - assertThat(actual).isTrue() - } - - @Test - fun `does not match with anything before`() { - val actual = subject.matches("xyz") - assertThat(actual).isFalse() - } - - @Test - fun `does not match with more than on character before`() { - val actual = subject.matches("aaxyz") - assertThat(actual).isFalse() - } + inner class `Pattern with wildcard at the middle` { + private val subject = SimpleGlob.of("x*yz") + + @Test + fun `matches pattern exactly`() { + val actual = subject.matches("xyz") + assertThat(actual).isTrue() } - @Nested - inner class `pattern with wildcard at the end` { - private val subject = SimpleGlob.of("xyz?") - - @Test - fun `matches with any character after`() { - val actual = subject.matches("xyz_") - assertThat(actual).isTrue() - } - - @Test - fun `does not match with anything after`() { - val actual = subject.matches("xyz") - assertThat(actual).isFalse() - } - - @Test - fun `does not match with more than on character after`() { - val actual = subject.matches("xyz_a") - assertThat(actual).isFalse() - } + @Test + fun `matches pattern with anything in between`() { + val actual = subject.matches("xaaaayz") + assertThat(actual).isTrue() } - @Nested - inner class `pattern with wildcard at the middle` { - private val subject = SimpleGlob.of("x?yz") - - @Test - fun `matches with any single character`() { - val actual = subject.matches("x_yz") - assertThat(actual).isTrue() - } - - @Test - fun `does not match with more than one character`() { - val actual = subject.matches("x_a_yz") - assertThat(actual).isFalse() - } + @Test + fun `does not match with anything before`() { + val actual = subject.matches("axyz") + assertThat(actual).isFalse() + } + + @Test + fun `does not match with anything after`() { + val actual = subject.matches("xyza") + assertThat(actual).isFalse() } } + } + + @Nested + inner class `multiple wildcards` { + private val subject = SimpleGlob.of("x*yz*") + @Test + fun `matches pattern`() { + val actual = subject.matches("x.aaa.yz.bbb") + assertThat(actual).isTrue() + } + } + } + + @Nested + inner class `Questionmark wildcard` { + @Nested + inner class `single wildcard` { @Nested - inner class `multiple wildcards` { - private val subject = SimpleGlob.of("x?y?z") + inner class `pattern with wildcard at the beginning` { + private val subject = SimpleGlob.of("?xyz") @Test - fun `matches pattern`() { - val actual = subject.matches("x.y.z") + fun `matches with any character before`() { + val actual = subject.matches("_xyz") assertThat(actual).isTrue() } + + @Test + fun `does not match with anything before`() { + val actual = subject.matches("xyz") + assertThat(actual).isFalse() + } + + @Test + fun `does not match with more than on character before`() { + val actual = subject.matches("aaxyz") + assertThat(actual).isFalse() + } } - } - @Nested - inner class `characters that have a special meaning in regular expression must be escaped` { @Nested - inner class `Period` { - private val subject = SimpleGlob.of("a.b.c") + inner class `pattern with wildcard at the end` { + private val subject = SimpleGlob.of("xyz?") @Test - fun `matches the same string`() { - val actual = subject.matches("a.b.c") + fun `matches with any character after`() { + val actual = subject.matches("xyz_") assertThat(actual).isTrue() } @Test - fun `does not match a other string`() { - val actual = subject.matches("a_b_c") + fun `does not match with anything after`() { + val actual = subject.matches("xyz") + assertThat(actual).isFalse() + } + + @Test + fun `does not match with more than on character after`() { + val actual = subject.matches("xyz_a") assertThat(actual).isFalse() } } @Nested - inner class `Backslash` { - private val subject = SimpleGlob.of("""ab\d""") + inner class `pattern with wildcard at the middle` { + private val subject = SimpleGlob.of("x?yz") @Test - fun `matches the same string`() { - val actual = subject.matches("""ab\d""") + fun `matches with any single character`() { + val actual = subject.matches("x_yz") assertThat(actual).isTrue() } @Test - fun `does not match a other string`() { - val actual = subject.matches("ab5") + fun `does not match with more than one character`() { + val actual = subject.matches("x_a_yz") assertThat(actual).isFalse() } } } @Nested - inner class `invalid pattern` { + inner class `multiple wildcards` { + private val subject = SimpleGlob.of("x?y?z") + @Test - fun `fails during creation`() { - assertThatThrownBy { SimpleGlob.of("""a[b""") } - .isInstanceOf(IllegalArgumentException::class.java) + fun `matches pattern`() { + val actual = subject.matches("x.y.z") + assertThat(actual).isTrue() } } } + + @Nested + inner class `characters that have a special meaning in regular expression must be escaped` { + @Nested + inner class `Period` { + private val subject = SimpleGlob.of("a.b.c") + + @Test + fun `matches the same string`() { + val actual = subject.matches("a.b.c") + assertThat(actual).isTrue() + } + + @Test + fun `does not match a other string`() { + val actual = subject.matches("a_b_c") + assertThat(actual).isFalse() + } + } + + @Nested + inner class `Backslash` { + private val subject = SimpleGlob.of("""ab\d""") + + @Test + fun `matches the same string`() { + val actual = subject.matches("""ab\d""") + assertThat(actual).isTrue() + } + + @Test + fun `does not match a other string`() { + val actual = subject.matches("ab5") + assertThat(actual).isFalse() + } + } + } + + @Nested + inner class `invalid pattern` { + @Test + fun `fails during creation`() { + assertThatThrownBy { SimpleGlob.of("""a[b""") } + .isInstanceOf(IllegalArgumentException::class.java) + } + } } diff --git a/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/MainSpec.kt b/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/MainSpec.kt index d323138d423..3cd86067fc0 100644 --- a/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/MainSpec.kt +++ b/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/MainSpec.kt @@ -23,7 +23,8 @@ class MainSpec { @Nested inner class `Build runner` { - fun runnerConfigs(): List { + @Suppress("UnusedPrivateMember") + private fun runnerConfigs(): List { return listOf( arguments(arrayOf("--generate-config"), ConfigExporter::class), arguments(arrayOf("--run-rule", "RuleSet:Rule"), Runner::class), diff --git a/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/PathFiltersSpec.kt b/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/PathFiltersSpec.kt index a6477cfcde6..6031e1e12aa 100644 --- a/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/PathFiltersSpec.kt +++ b/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/PathFiltersSpec.kt @@ -9,101 +9,97 @@ import java.nio.file.Paths class PathFiltersSpec { + @Test + fun `should load single filter`() { + val filters = CliArgs { excludes = "**/one/**" }.toSpecFilters() + assertThat(filters?.isIgnored(Paths.get("/one/path"))).isTrue() + assertThat(filters?.isIgnored(Paths.get("/two/path"))).isFalse() + } + + @Nested + inner class `parsing with different nullability combinations of path filters` { + @Test + fun `returns an empty path filter when includes are empty and excludes are empty`() { + val pathFilter = PathFilters.of(emptyList(), emptyList()) + assertThat(pathFilter).isNull() + } + + @Test + fun `parses includes correctly`() { + val pathFilter = PathFilters.of(listOf("**/one/**", "**/two/**"), emptyList()) + assertThat(pathFilter).isNotNull + assertThat(pathFilter?.isIgnored(Paths.get("/one/path"))).isFalse + assertThat(pathFilter?.isIgnored(Paths.get("/two/path"))).isFalse + assertThat(pathFilter?.isIgnored(Paths.get("/three/path"))).isTrue + } + + @Test + fun `parses excludes correctly`() { + val pathFilter = PathFilters.of(emptyList(), listOf("**/one/**", "**/two/**")) + assertThat(pathFilter).isNotNull + assertThat(pathFilter?.isIgnored(Paths.get("/one/path"))).isTrue + assertThat(pathFilter?.isIgnored(Paths.get("/two/path"))).isTrue + assertThat(pathFilter?.isIgnored(Paths.get("/three/path"))).isFalse + } + + @Test + fun `parses both includes and excludes correctly`() { + val pathFilter = PathFilters.of(listOf("**/one/**"), listOf("**/two/**")) + assertThat(pathFilter).isNotNull + assertThat(pathFilter?.isIgnored(Paths.get("/one/path"))).isFalse + assertThat(pathFilter?.isIgnored(Paths.get("/two/path"))).isTrue + assertThat(pathFilter?.isIgnored(Paths.get("/three/path"))).isTrue + } + } + @Nested - inner class `parse different filter settings` { + inner class `parsing with different separators` { @Test - fun `should load single filter`() { - val filters = CliArgs { excludes = "**/one/**" }.toSpecFilters() - assertThat(filters?.isIgnored(Paths.get("/one/path"))).isTrue() - assertThat(filters?.isIgnored(Paths.get("/two/path"))).isFalse() + fun `should load multiple comma-separated filters with no spaces around commas`() { + val filters = CliArgs { excludes = "**/one/**,**/two/**,**/three" }.toSpecFilters() + assertSameFiltersIndependentOfSpacingAndSeparater(filters) } - @Nested - inner class `parsing with different nullability combinations of path filters` { - @Test - fun `returns an empty path filter when includes are empty and excludes are empty`() { - val pathFilter = PathFilters.of(emptyList(), emptyList()) - assertThat(pathFilter).isNull() - } - - @Test - fun `parses includes correctly`() { - val pathFilter = PathFilters.of(listOf("**/one/**", "**/two/**"), emptyList()) - assertThat(pathFilter).isNotNull - assertThat(pathFilter?.isIgnored(Paths.get("/one/path"))).isFalse - assertThat(pathFilter?.isIgnored(Paths.get("/two/path"))).isFalse - assertThat(pathFilter?.isIgnored(Paths.get("/three/path"))).isTrue - } - - @Test - fun `parses excludes correctly`() { - val pathFilter = PathFilters.of(emptyList(), listOf("**/one/**", "**/two/**")) - assertThat(pathFilter).isNotNull - assertThat(pathFilter?.isIgnored(Paths.get("/one/path"))).isTrue - assertThat(pathFilter?.isIgnored(Paths.get("/two/path"))).isTrue - assertThat(pathFilter?.isIgnored(Paths.get("/three/path"))).isFalse - } - - @Test - fun `parses both includes and excludes correctly`() { - val pathFilter = PathFilters.of(listOf("**/one/**"), listOf("**/two/**")) - assertThat(pathFilter).isNotNull - assertThat(pathFilter?.isIgnored(Paths.get("/one/path"))).isFalse - assertThat(pathFilter?.isIgnored(Paths.get("/two/path"))).isTrue - assertThat(pathFilter?.isIgnored(Paths.get("/three/path"))).isTrue - } + @Test + fun `should load multiple semicolon-separated filters with no spaces around semicolons`() { + val filters = CliArgs { excludes = "**/one/**;**/two/**;**/three" }.toSpecFilters() + assertSameFiltersIndependentOfSpacingAndSeparater(filters) } - @Nested - inner class `parsing with different separators` { - - @Test - fun `should load multiple comma-separated filters with no spaces around commas`() { - val filters = CliArgs { excludes = "**/one/**,**/two/**,**/three" }.toSpecFilters() - assertSameFiltersIndependentOfSpacingAndSeparater(filters) - } - - @Test - fun `should load multiple semicolon-separated filters with no spaces around semicolons`() { - val filters = CliArgs { excludes = "**/one/**;**/two/**;**/three" }.toSpecFilters() - assertSameFiltersIndependentOfSpacingAndSeparater(filters) - } - - @Test - fun `should load multiple comma-separated filters with spaces around commas`() { - val filters = CliArgs { excludes = "**/one/** ,**/two/**, **/three" }.toSpecFilters() - assertSameFiltersIndependentOfSpacingAndSeparater(filters) - } - - @Test - fun `should load multiple semicolon-separated filters with spaces around semicolons`() { - val filters = CliArgs { excludes = "**/one/** ;**/two/**; **/three" }.toSpecFilters() - assertSameFiltersIndependentOfSpacingAndSeparater(filters) - } - - @Test - fun `should load multiple mixed-separated filters with no spaces around separators`() { - val filters = CliArgs { excludes = "**/one/**,**/two/**;**/three" }.toSpecFilters() - assertSameFiltersIndependentOfSpacingAndSeparater(filters) - } - - @Test - fun `should load multiple mixed-separated filters with spaces around separators`() { - val filters = CliArgs { excludes = "**/one/** ,**/two/**; **/three" }.toSpecFilters() - assertSameFiltersIndependentOfSpacingAndSeparater(filters) - } + @Test + fun `should load multiple comma-separated filters with spaces around commas`() { + val filters = CliArgs { excludes = "**/one/** ,**/two/**, **/three" }.toSpecFilters() + assertSameFiltersIndependentOfSpacingAndSeparater(filters) } @Test - fun `should ignore empty and blank filters`() { - val filters = CliArgs { excludes = " ,,**/three" }.toSpecFilters() - assertThat(filters?.isIgnored(Paths.get("/three"))).isTrue() - assertThat(filters?.isIgnored(Paths.get("/root/three"))).isTrue() - assertThat(filters?.isIgnored(Paths.get("/one/path"))).isFalse() - assertThat(filters?.isIgnored(Paths.get("/two/path"))).isFalse() - assertThat(filters?.isIgnored(Paths.get("/three/path"))).isFalse() + fun `should load multiple semicolon-separated filters with spaces around semicolons`() { + val filters = CliArgs { excludes = "**/one/** ;**/two/**; **/three" }.toSpecFilters() + assertSameFiltersIndependentOfSpacingAndSeparater(filters) } + + @Test + fun `should load multiple mixed-separated filters with no spaces around separators`() { + val filters = CliArgs { excludes = "**/one/**,**/two/**;**/three" }.toSpecFilters() + assertSameFiltersIndependentOfSpacingAndSeparater(filters) + } + + @Test + fun `should load multiple mixed-separated filters with spaces around separators`() { + val filters = CliArgs { excludes = "**/one/** ,**/two/**; **/three" }.toSpecFilters() + assertSameFiltersIndependentOfSpacingAndSeparater(filters) + } + } + + @Test + fun `should ignore empty and blank filters`() { + val filters = CliArgs { excludes = " ,,**/three" }.toSpecFilters() + assertThat(filters?.isIgnored(Paths.get("/three"))).isTrue() + assertThat(filters?.isIgnored(Paths.get("/root/three"))).isTrue() + assertThat(filters?.isIgnored(Paths.get("/one/path"))).isFalse() + assertThat(filters?.isIgnored(Paths.get("/two/path"))).isFalse() + assertThat(filters?.isIgnored(Paths.get("/three/path"))).isFalse() } } diff --git a/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/ReportPathSpec.kt b/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/ReportPathSpec.kt index b0357ad61e5..1eb6848c7de 100644 --- a/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/ReportPathSpec.kt +++ b/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/ReportPathSpec.kt @@ -12,109 +12,106 @@ import java.nio.file.Paths class ReportPathSpec { + @EnabledOnOs(OS.WINDOWS) @Nested - inner class `report paths` { - @EnabledOnOs(OS.WINDOWS) - @Nested - inner class `a Windows path` { - @Test - fun `parses a valid absolute path correctly`() { - val reportPath = ReportPath.from("test:C:\\tmp\\valid\\report") - - assertThat(reportPath.path).isEqualTo(Paths.get("C:\\tmp\\valid\\report")) - } - - @Test - fun `parses a valid relative path correctly`() { - val reportPath = ReportPath.from("test:valid\\report") - - assertThat(reportPath.path).isEqualTo(Paths.get("valid\\report")) - } - - @Test - fun `fails when the path is empty`() { - assertThatIllegalArgumentException() - .isThrownBy { ReportPath.from("test:") } - } - - @Test - fun `fails when the path is malformed`() { - assertThatIllegalArgumentException() - .isThrownBy { ReportPath.from("test:a*a") } - } + inner class `a Windows path` { + @Test + fun `parses a valid absolute path correctly`() { + val reportPath = ReportPath.from("test:C:\\tmp\\valid\\report") + + assertThat(reportPath.path).isEqualTo(Paths.get("C:\\tmp\\valid\\report")) } - @DisabledOnOs(OS.WINDOWS) - @Nested - inner class `a POSIX path` { - @Test - fun `parses a valid absolute path correctly`() { - val reportPath = ReportPath.from("test:/tmp/valid/report") - - assertThat(reportPath.path).isEqualTo(Paths.get("/tmp/valid/report")) - } - - @Test - fun `parses a valid relative path correctly`() { - val reportPath = ReportPath.from("test:valid/report") - - assertThat(reportPath.path).isEqualTo(Paths.get("valid/report")) - } - - @Test - fun `fails when the path is empty`() { - assertThatIllegalArgumentException() - .isThrownBy { ReportPath.from("test:") } - } - - @Test - fun `fails when the path is malformed`() { - assertThatIllegalArgumentException() - .isThrownBy { ReportPath.from("test:a${0.toChar()}a") } - } + @Test + fun `parses a valid relative path correctly`() { + val reportPath = ReportPath.from("test:valid\\report") + + assertThat(reportPath.path).isEqualTo(Paths.get("valid\\report")) } - @Nested - inner class `_kind_ processing` { - @Test - fun `parses and maps the txt kind correctly`() { - val reportPath = ReportPath.from("txt:/tmp/valid/report") + @Test + fun `fails when the path is empty`() { + assertThatIllegalArgumentException() + .isThrownBy { ReportPath.from("test:") } + } - assertThat(reportPath.kind).isEqualTo("txt") - } + @Test + fun `fails when the path is malformed`() { + assertThatIllegalArgumentException() + .isThrownBy { ReportPath.from("test:a*a") } + } + } - @Test - fun `parses and maps the xml kind correctly`() { - val reportPath = ReportPath.from("xml:/tmp/valid/report") + @DisabledOnOs(OS.WINDOWS) + @Nested + inner class `a POSIX path` { + @Test + fun `parses a valid absolute path correctly`() { + val reportPath = ReportPath.from("test:/tmp/valid/report") - assertThat(reportPath.kind).isEqualTo("xml") - } + assertThat(reportPath.path).isEqualTo(Paths.get("/tmp/valid/report")) + } - @Test - fun `parses and maps the html kind correctly`() { - val reportPath = ReportPath.from("html:/tmp/valid/report") + @Test + fun `parses a valid relative path correctly`() { + val reportPath = ReportPath.from("test:valid/report") - assertThat(reportPath.kind).isEqualTo("html") - } + assertThat(reportPath.path).isEqualTo(Paths.get("valid/report")) + } + + @Test + fun `fails when the path is empty`() { + assertThatIllegalArgumentException() + .isThrownBy { ReportPath.from("test:") } + } - @Test - fun `parses a non-default kind correctly`() { - val reportPath = ReportPath.from("test:/tmp/valid/report") + @Test + fun `fails when the path is malformed`() { + assertThatIllegalArgumentException() + .isThrownBy { ReportPath.from("test:a${0.toChar()}a") } + } + } - assertThat(reportPath.kind).isEqualTo("test") - } + @Nested + inner class `_kind_ processing` { + @Test + fun `parses and maps the txt kind correctly`() { + val reportPath = ReportPath.from("txt:/tmp/valid/report") - @Test - fun `fails when the kind is empty`() { - assertThatIllegalArgumentException() - .isThrownBy { ReportPath.from(":/tmp/anything") } - } + assertThat(reportPath.kind).isEqualTo("txt") + } + + @Test + fun `parses and maps the xml kind correctly`() { + val reportPath = ReportPath.from("xml:/tmp/valid/report") + + assertThat(reportPath.kind).isEqualTo("xml") + } + + @Test + fun `parses and maps the html kind correctly`() { + val reportPath = ReportPath.from("html:/tmp/valid/report") + + assertThat(reportPath.kind).isEqualTo("html") + } + + @Test + fun `parses a non-default kind correctly`() { + val reportPath = ReportPath.from("test:/tmp/valid/report") + + assertThat(reportPath.kind).isEqualTo("test") + } + + @Test + fun `fails when the kind is empty`() { + assertThatIllegalArgumentException() + .isThrownBy { ReportPath.from(":/tmp/anything") } + } - @Test - fun `fails when part size is illegal`() { - assertThatIllegalStateException() - .isThrownBy { ReportPath.from("") } - } + @Test + fun `fails when part size is illegal`() { + assertThatIllegalStateException() + .isThrownBy { ReportPath.from("") } } } } diff --git a/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/runners/AstPrinterSpec.kt b/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/runners/AstPrinterSpec.kt index 6c696c73f06..748ea3a3ab1 100644 --- a/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/runners/AstPrinterSpec.kt +++ b/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/runners/AstPrinterSpec.kt @@ -12,49 +12,45 @@ import java.io.PrintStream class AstPrinterSpec { - @Nested - inner class `element printer` { - - val path = resourceAsPath("cases").toString() + val path = resourceAsPath("cases").toString() - @Nested - inner class `successful AST printing` { + @Nested + inner class `successful AST printing` { - @Test - fun `should print the AST as string`() { - val output = ByteArrayOutputStream() - val args = CliArgs() - args.input = resourceAsPath("cases/Poko.kt").toString() - val printer = AstPrinter(args, PrintStream(output)) + @Test + fun `should print the AST as string`() { + val output = ByteArrayOutputStream() + val args = CliArgs() + args.input = resourceAsPath("cases/Poko.kt").toString() + val printer = AstPrinter(args, PrintStream(output)) - printer.execute() + printer.execute() - assertThat(output.toString()).isNotEmpty() - } + assertThat(output.toString()).isNotEmpty() } + } - @Test - fun `throws an exception when declaring multiple input files`() { - val multiplePaths = "$path,$path" - val args = CliArgs() - args.input = multiplePaths - val printer = AstPrinter(args, NullPrintStream()) + @Test + fun `throws an exception when declaring multiple input files`() { + val multiplePaths = "$path,$path" + val args = CliArgs() + args.input = multiplePaths + val printer = AstPrinter(args, NullPrintStream()) - assertThatIllegalArgumentException() - .isThrownBy { printer.execute() } - .withMessage("More than one input path specified. Printing AST is only supported for single files.") - } + assertThatIllegalArgumentException() + .isThrownBy { printer.execute() } + .withMessage("More than one input path specified. Printing AST is only supported for single files.") + } - @Test - fun `throws an exception when trying to print the AST of a directory`() { - val args = CliArgs() - args.input = path - val printer = AstPrinter(args, NullPrintStream()) + @Test + fun `throws an exception when trying to print the AST of a directory`() { + val args = CliArgs() + args.input = path + val printer = AstPrinter(args, NullPrintStream()) - assertThatIllegalArgumentException() - .isThrownBy { printer.execute() } - .withMessageStartingWith("Input path ") - .withMessageEndingWith(" must be a kotlin file and not a directory.") - } + assertThatIllegalArgumentException() + .isThrownBy { printer.execute() } + .withMessageStartingWith("Input path ") + .withMessageEndingWith(" must be a kotlin file and not a directory.") } } diff --git a/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/runners/ElementPrinterSpec.kt b/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/runners/ElementPrinterSpec.kt index a795f1cabc3..319684a5067 100644 --- a/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/runners/ElementPrinterSpec.kt +++ b/detekt-cli/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/runners/ElementPrinterSpec.kt @@ -3,23 +3,18 @@ package io.gitlab.arturbosch.detekt.cli.runners import io.github.detekt.test.utils.compileForTest import io.github.detekt.test.utils.resourceAsPath import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ElementPrinterSpec { - @Nested - inner class `element printer` { + @Test + fun `should print the ast as string`() { + val case = resourceAsPath("cases/Poko.kt") + val ktFile = compileForTest(case) - @Test - fun `should print the ast as string`() { - val case = resourceAsPath("cases/Poko.kt") - val ktFile = compileForTest(case) + val dump = ElementPrinter.dump(ktFile) - val dump = ElementPrinter.dump(ktFile) - - assertThat(dump.trimIndent()).isEqualTo(expected) - } + assertThat(dump.trimIndent()).isEqualTo(expected) } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/CorrectableRulesFirstSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/CorrectableRulesFirstSpec.kt index af73fe3512e..d75c7851578 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/CorrectableRulesFirstSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/CorrectableRulesFirstSpec.kt @@ -11,47 +11,42 @@ import io.gitlab.arturbosch.detekt.api.Severity import io.gitlab.arturbosch.detekt.test.yamlConfig import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.psi.KtClass -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class CorrectableRulesFirstSpec { - @Nested - inner class `correctable rules are run first` { + @Test + fun `runs rule with id 'NonCorrectable' last`() { + var actualLastRuleId = "" - @Test - fun `runs rule with id 'NonCorrectable' last`() { - var actualLastRuleId = "" - - class First(config: Config) : Rule(config) { - override val issue: Issue = justAnIssue.copy(id = "NonCorrectable") - override fun visitClass(klass: KtClass) { - actualLastRuleId = issue.id - } + class First(config: Config) : Rule(config) { + override val issue: Issue = justAnIssue.copy(id = "NonCorrectable") + override fun visitClass(klass: KtClass) { + actualLastRuleId = issue.id } + } - class Last(config: Config) : Rule(config) { - override val issue: Issue = justAnIssue.copy(id = "Correctable") - override fun visitClass(klass: KtClass) { - actualLastRuleId = issue.id - } + class Last(config: Config) : Rule(config) { + override val issue: Issue = justAnIssue.copy(id = "Correctable") + override fun visitClass(klass: KtClass) { + actualLastRuleId = issue.id } + } - val testFile = path.resolve("Test.kt") - val settings = createProcessingSettings(testFile, yamlConfig("configs/one-correctable-rule.yml")) - val detector = Analyzer( - settings, - listOf(object : RuleSetProvider { - override val ruleSetId: String = "Test" - override fun instance(config: Config) = RuleSet(ruleSetId, listOf(Last(config), First(config))) - }), - emptyList() - ) + val testFile = path.resolve("Test.kt") + val settings = createProcessingSettings(testFile, yamlConfig("configs/one-correctable-rule.yml")) + val detector = Analyzer( + settings, + listOf(object : RuleSetProvider { + override val ruleSetId: String = "Test" + override fun instance(config: Config) = RuleSet(ruleSetId, listOf(Last(config), First(config))) + }), + emptyList() + ) - settings.use { detector.run(listOf(compileForTest(testFile))) } + settings.use { detector.run(listOf(compileForTest(testFile))) } - assertThat(actualLastRuleId).isEqualTo("NonCorrectable") - } + assertThat(actualLastRuleId).isEqualTo("NonCorrectable") } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/CustomRuleSetProviderSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/CustomRuleSetProviderSpec.kt index 5c9936a8583..1b5d714fc85 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/CustomRuleSetProviderSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/CustomRuleSetProviderSpec.kt @@ -4,7 +4,6 @@ import io.github.detekt.test.utils.resourceAsPath import io.gitlab.arturbosch.detekt.core.rules.RuleSetLocator import io.gitlab.arturbosch.detekt.core.tooling.withSettings import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test /** @@ -20,22 +19,18 @@ import org.junit.jupiter.api.Test */ class CustomRuleSetProviderSpec { - @Nested - inner class `custom rule sets should be loadable through jars` { - - @Test - fun `should load the sample provider`() { - val sampleRuleSet = resourceAsPath("sample-rule-set.jar") - val spec = createNullLoggingSpec { - extensions { - disableDefaultRuleSets = true - fromPaths { listOf(sampleRuleSet) } - } + @Test + fun `custom rule sets should be loadable through jars should load the sample provider`() { + val sampleRuleSet = resourceAsPath("sample-rule-set.jar") + val spec = createNullLoggingSpec { + extensions { + disableDefaultRuleSets = true + fromPaths { listOf(sampleRuleSet) } } + } - val providers = spec.withSettings { RuleSetLocator(this).load() } + val providers = spec.withSettings { RuleSetLocator(this).load() } - assertThat(providers).filteredOn { it.ruleSetId == "sample" }.hasSize(1) - } + assertThat(providers).filteredOn { it.ruleSetId == "sample" }.hasSize(1) } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/FileProcessorLocatorSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/FileProcessorLocatorSpec.kt index 00fc47f996e..8f869a0c288 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/FileProcessorLocatorSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/FileProcessorLocatorSpec.kt @@ -5,7 +5,6 @@ import io.gitlab.arturbosch.detekt.api.FileProcessListener import io.gitlab.arturbosch.detekt.test.yamlConfig import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.fail -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import org.reflections.Reflections import java.lang.reflect.Modifier @@ -15,28 +14,24 @@ import java.lang.reflect.Modifier */ class FileProcessorLocatorSpec { - @Nested - inner class `file processor locator` { + private val path = resourceAsPath("") - val path = resourceAsPath("") + @Test + fun `contains all processors`() { + val processors = createProcessingSettings(path).use { FileProcessorLocator(it).load() } + val processorClasses = getProcessorClasses() - @Test - fun `contains all processors`() { - val processors = createProcessingSettings(path).use { FileProcessorLocator(it).load() } - val processorClasses = getProcessorClasses() - - assertThat(processorClasses).isNotEmpty - processorClasses - .filter { clazz -> processors.none { clazz == it.javaClass } } - .forEach { fail("$it processor is not loaded by the FileProcessorLocator") } - } + assertThat(processorClasses).isNotEmpty + processorClasses + .filter { clazz -> processors.none { clazz == it.javaClass } } + .forEach { fail("$it processor is not loaded by the FileProcessorLocator") } + } - @Test - fun `has disabled processors`() { - val config = yamlConfig("configs/disabled-processors.yml") - val processors = createProcessingSettings(path, config).use { FileProcessorLocator(it).load() } - assertThat(processors).isEmpty() - } + @Test + fun `has disabled processors`() { + val config = yamlConfig("configs/disabled-processors.yml") + val processors = createProcessingSettings(path, config).use { FileProcessorLocator(it).load() } + assertThat(processors).isEmpty() } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/KtTreeCompilerSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/KtTreeCompilerSpec.kt index df155519d2c..8b4fe63721d 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/KtTreeCompilerSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/KtTreeCompilerSpec.kt @@ -5,80 +5,75 @@ import io.gitlab.arturbosch.detekt.core.tooling.withSettings import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatIllegalArgumentException import org.jetbrains.kotlin.psi.KtFile -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import java.nio.file.Paths class KtTreeCompilerSpec { - @Nested - inner class `tree compiler functionality` { - - @Test - fun `should compile all files`() { - val (ktFiles, _) = fixture { compile(path) } - assertThat(ktFiles.size) - .describedAs("It should compile at least three files, but did ${ktFiles.size}") - .isGreaterThanOrEqualTo(3) - } + @Test + fun `should compile all files`() { + val (ktFiles, _) = fixture { compile(path) } + assertThat(ktFiles.size) + .describedAs("It should compile at least three files, but did ${ktFiles.size}") + .isGreaterThanOrEqualTo(3) + } - @Test - fun `should filter the file 'Default_kt'`() { - val (ktFiles, output) = fixture("**/Default.kt", loggingDebug = true) { compile(path) } - val ktFile = ktFiles.find { it.name == "Default.kt" } - assertThat(ktFile).describedAs("It should have no Default.kt file").isNull() + @Test + fun `should filter the file 'Default_kt'`() { + val (ktFiles, output) = fixture("**/Default.kt", loggingDebug = true) { compile(path) } + val ktFile = ktFiles.find { it.name == "Default.kt" } + assertThat(ktFile).describedAs("It should have no Default.kt file").isNull() - assertThat(output).contains("Ignoring file ") - } + assertThat(output).contains("Ignoring file ") + } - @Test - fun `should work with two or more filters`() { - val (ktFiles, _) = fixture( - "**/Default.kt", - "**/*Test*", - "**/*Complex*", - "**/*KotlinScript*" - ) { compile(path) } - assertThat(ktFiles).isEmpty() - } + @Test + fun `should work with two or more filters`() { + val (ktFiles, _) = fixture( + "**/Default.kt", + "**/*Test*", + "**/*Complex*", + "**/*KotlinScript*" + ) { compile(path) } + assertThat(ktFiles).isEmpty() + } - @Test - fun `should also compile regular files`() { - val (ktFiles, _) = fixture { compile(path.resolve("Default.kt")) } - assertThat(ktFiles.size).isEqualTo(1) - } + @Test + fun `should also compile regular files`() { + val (ktFiles, _) = fixture { compile(path.resolve("Default.kt")) } + assertThat(ktFiles.size).isEqualTo(1) + } - @Test - fun `throws an exception if given file does not exist`() { - val invalidPath = "NOTHERE" - assertThatIllegalArgumentException() - .isThrownBy { fixture { compile(Paths.get(invalidPath)) } } - .withMessage("Given path $invalidPath does not exist!") - } + @Test + fun `throws an exception if given file does not exist`() { + val invalidPath = "NOTHERE" + assertThatIllegalArgumentException() + .isThrownBy { fixture { compile(Paths.get(invalidPath)) } } + .withMessage("Given path $invalidPath does not exist!") + } - @Test - fun `does not compile a folder with a css file`() { - val cssPath = resourceAsPath("css") - val (ktFiles, output) = fixture { compile(cssPath) } - assertThat(ktFiles).isEmpty() - assertThat(output).isEmpty() - } + @Test + fun `does not compile a folder with a css file`() { + val cssPath = resourceAsPath("css") + val (ktFiles, output) = fixture { compile(cssPath) } + assertThat(ktFiles).isEmpty() + assertThat(output).isEmpty() + } - @Test - fun `does not compile a css file`() { - val cssPath = resourceAsPath("css").resolve("test.css") - val (ktFiles, output) = fixture { compile(cssPath) } - assertThat(ktFiles).isEmpty() - assertThat(output).isEmpty() - } + @Test + fun `does not compile a css file`() { + val cssPath = resourceAsPath("css").resolve("test.css") + val (ktFiles, output) = fixture { compile(cssPath) } + assertThat(ktFiles).isEmpty() + assertThat(output).isEmpty() + } - @Test - fun `does not compile a css file but show log if debug is enabled`() { - val cssPath = resourceAsPath("css").resolve("test.css") - val (ktFiles, output) = fixture(loggingDebug = true) { compile(cssPath) } - assertThat(ktFiles).isEmpty() - assertThat(output).contains("Ignoring a file detekt cannot handle: ") - } + @Test + fun `does not compile a css file but show log if debug is enabled`() { + val cssPath = resourceAsPath("css").resolve("test.css") + val (ktFiles, output) = fixture(loggingDebug = true) { compile(cssPath) } + assertThat(ktFiles).isEmpty() + assertThat(output).contains("Ignoring a file detekt cannot handle: ") } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/TopLevelAutoCorrectSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/TopLevelAutoCorrectSpec.kt index 1f5c8e47db9..ad11ff5ee6c 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/TopLevelAutoCorrectSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/TopLevelAutoCorrectSpec.kt @@ -22,53 +22,48 @@ import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.psi.KtAnnotation import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.BindingContext -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class TopLevelAutoCorrectSpec { - @Nested - inner class `autoCorrect_ false on top level` { - - @Test - fun `should format the test file but not print the modified content to disc`() { - val fileContentBeforeAutoCorrect = readResourceContent("cases/Test.kt") - val fileUnderTest = resourceAsPath("cases/Test.kt") - val spec = ProcessingSpec { - project { - inputPaths = listOf(fileUnderTest) - } - config { - resources = listOf(resourceUrl("configs/rule-and-ruleset-autocorrect-true.yaml")) - } - rules { - autoCorrect = false // fixture - } - logging { - outputChannel = NullPrintStream() - errorChannel = NullPrintStream() - } + @Test + fun `should format the test file but not print the modified content to disc`() { + val fileContentBeforeAutoCorrect = readResourceContent("cases/Test.kt") + val fileUnderTest = resourceAsPath("cases/Test.kt") + val spec = ProcessingSpec { + project { + inputPaths = listOf(fileUnderTest) } - - val contentChangedListener = object : FileProcessListener { - override fun onFinish(files: List, result: Detektion, bindingContext: BindingContext) { - assertThat(files).hasSize(1) - assertThat(files[0].text).isNotEqualToIgnoringWhitespace(fileContentBeforeAutoCorrect) - } + config { + resources = listOf(resourceUrl("configs/rule-and-ruleset-autocorrect-true.yaml")) + } + rules { + autoCorrect = false // fixture + } + logging { + outputChannel = NullPrintStream() + errorChannel = NullPrintStream() } + } - AnalysisFacade(spec).runAnalysis { - DefaultLifecycle( - mockk(), - it, - inputPathsToKtFiles, - processorsProvider = { listOf(contentChangedListener) }, - ruleSetsProvider = { listOf(TopLevelAutoCorrectProvider()) } - ) + val contentChangedListener = object : FileProcessListener { + override fun onFinish(files: List, result: Detektion, bindingContext: BindingContext) { + assertThat(files).hasSize(1) + assertThat(files[0].text).isNotEqualToIgnoringWhitespace(fileContentBeforeAutoCorrect) } + } - assertThat(readResourceContent("cases/Test.kt")).isEqualTo(fileContentBeforeAutoCorrect) + AnalysisFacade(spec).runAnalysis { + DefaultLifecycle( + mockk(), + it, + inputPathsToKtFiles, + processorsProvider = { listOf(contentChangedListener) }, + ruleSetsProvider = { listOf(TopLevelAutoCorrectProvider()) } + ) } + + assertThat(readResourceContent("cases/Test.kt")).isEqualTo(fileContentBeforeAutoCorrect) } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/baseline/BaselineFacadeSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/baseline/BaselineFacadeSpec.kt index b97ad27f2aa..04ba4ace1f2 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/baseline/BaselineFacadeSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/baseline/BaselineFacadeSpec.kt @@ -6,85 +6,80 @@ import io.gitlab.arturbosch.detekt.test.TestDetektion import io.gitlab.arturbosch.detekt.test.createFinding import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import java.nio.file.Files class BaselineFacadeSpec { - @Nested - inner class `a baseline facade` { - - private val baselineFile = createTempDirectoryForTest("baseline_format").resolve("baseline.xml") - private val validBaseline = resourceAsPath("/baseline_feature/valid-baseline.xml") - - @AfterEach - fun tearDown() { - Files.deleteIfExists(baselineFile) - } - - @Test - fun `returns a BaselineFilteredResult when the baseline exists`() { - val detektion = BaselineFacade().transformResult(validBaseline, TestDetektion()) - - assertThat(detektion).isInstanceOf(BaselineFilteredResult::class.java) - } - - @Test - fun `returns the same detektion when the baseline doesn't exist`() { - val initialDetektion = TestDetektion() - val detektion = BaselineFacade().transformResult(baselineFile, initialDetektion) - - assertThat(detektion).isEqualTo(initialDetektion) - } - - @Test - fun `doesn't create a baseline file without findings`() { - BaselineFacade().createOrUpdate(baselineFile, emptyList()) - - assertThat(baselineFile).doesNotExist() - } - - @Test - fun `creates on top of an existing a baseline file without findings`() { - Files.copy(validBaseline, baselineFile) - - BaselineFacade().createOrUpdate(baselineFile, emptyList()) - - assertThat(baselineFile).hasContent( - """ - - - - LongParameterList:Signature - LongMethod:Signature - - - - """.trimIndent() - ) - } - - @Test - fun `creates on top of an existing a baseline file with findings`() { - Files.copy(validBaseline, baselineFile) - - BaselineFacade().createOrUpdate(baselineFile, listOf(createFinding())) - - assertThat(baselineFile).hasContent( - """ - - - - LongParameterList:Signature - LongMethod:Signature - - - TestSmell:TestEntitySignature - - - """.trimIndent() - ) - } + private val baselineFile = createTempDirectoryForTest("baseline_format").resolve("baseline.xml") + private val validBaseline = resourceAsPath("/baseline_feature/valid-baseline.xml") + + @AfterEach + fun tearDown() { + Files.deleteIfExists(baselineFile) + } + + @Test + fun `returns a BaselineFilteredResult when the baseline exists`() { + val detektion = BaselineFacade().transformResult(validBaseline, TestDetektion()) + + assertThat(detektion).isInstanceOf(BaselineFilteredResult::class.java) + } + + @Test + fun `returns the same detektion when the baseline doesn't exist`() { + val initialDetektion = TestDetektion() + val detektion = BaselineFacade().transformResult(baselineFile, initialDetektion) + + assertThat(detektion).isEqualTo(initialDetektion) + } + + @Test + fun `doesn't create a baseline file without findings`() { + BaselineFacade().createOrUpdate(baselineFile, emptyList()) + + assertThat(baselineFile).doesNotExist() + } + + @Test + fun `creates on top of an existing a baseline file without findings`() { + Files.copy(validBaseline, baselineFile) + + BaselineFacade().createOrUpdate(baselineFile, emptyList()) + + assertThat(baselineFile).hasContent( + """ + + + + LongParameterList:Signature + LongMethod:Signature + + + + """.trimIndent() + ) + } + + @Test + fun `creates on top of an existing a baseline file with findings`() { + Files.copy(validBaseline, baselineFile) + + BaselineFacade().createOrUpdate(baselineFile, listOf(createFinding())) + + assertThat(baselineFile).hasContent( + """ + + + + LongParameterList:Signature + LongMethod:Signature + + + TestSmell:TestEntitySignature + + + """.trimIndent() + ) } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/baseline/BaselineFilteredResultSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/baseline/BaselineFilteredResultSpec.kt index 9f998cdbd1c..43e2ef43d76 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/baseline/BaselineFilteredResultSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/baseline/BaselineFilteredResultSpec.kt @@ -5,44 +5,39 @@ import io.gitlab.arturbosch.detekt.test.TestDetektion import io.mockk.every import io.mockk.mockk import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class BaselineFilteredResultSpec { - @Nested - inner class `baseline based result transformation` { + private val baselineFile = resourceAsPath("/baseline_feature/valid-baseline.xml") - private val baselineFile = resourceAsPath("/baseline_feature/valid-baseline.xml") + private val result = TestDetektion( + mockk { + every { id }.returns("LongParameterList") + every { signature }.returns("Signature") + }, + mockk { + every { id }.returns("LongMethod") + every { signature }.returns("Signature") + }, + mockk { + every { id }.returns("FeatureEnvy") + every { signature }.returns("Signature") + }, + ) - private val result = TestDetektion( - mockk { - every { id }.returns("LongParameterList") - every { signature }.returns("Signature") - }, - mockk { - every { id }.returns("LongMethod") - every { signature }.returns("Signature") - }, - mockk { - every { id }.returns("FeatureEnvy") - every { signature }.returns("Signature") - }, - ) - - @Test - fun `does return the same finding on empty baseline`() { - val actual = BaselineFilteredResult(result, Baseline(emptySet(), emptySet())) - assertThat(actual.findings).hasSize(3) - } + @Test + fun `does return the same finding on empty baseline`() { + val actual = BaselineFilteredResult(result, Baseline(emptySet(), emptySet())) + assertThat(actual.findings).hasSize(3) + } - @Test - fun `filters with an existing baseline file`() { - val baseline = Baseline.load(baselineFile) - val actual = BaselineFilteredResult(result, baseline) - // Note: Detektion works with Map - // but the TestDetektion maps the RuleId as RuleSetId - actual.findings.forEach { (_, value) -> assertThat(value).isEmpty() } - } + @Test + fun `filters with an existing baseline file`() { + val baseline = Baseline.load(baselineFile) + val actual = BaselineFilteredResult(result, baseline) + // Note: Detektion works with Map + // but the TestDetektion maps the RuleId as RuleSetId + actual.findings.forEach { (_, value) -> assertThat(value).isEmpty() } } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/baseline/BaselineFormatSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/baseline/BaselineFormatSpec.kt index 0c18c7944bc..bb00b0bd808 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/baseline/BaselineFormatSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/baseline/BaselineFormatSpec.kt @@ -12,78 +12,74 @@ import java.nio.file.Files class BaselineFormatSpec { @Nested - inner class `baseline format` { - - @Nested - inner class `read a baseline file` { - - @Test - fun `loads the baseline file`() { - val path = resourceAsPath("/baseline_feature/valid-baseline.xml") - val (manuallySuppressedIssues, currentIssues) = BaselineFormat().read(path) - - assertThat(manuallySuppressedIssues).hasSize(2) - assertThat(manuallySuppressedIssues).anySatisfy { it.startsWith("LongParameterList") } - assertThat(manuallySuppressedIssues).anySatisfy { it.startsWith("LongMethod") } - assertThat(currentIssues).hasSize(1) - assertThat(currentIssues).anySatisfy { it.startsWith("FeatureEnvy") } - } - - @Test - fun `throws on an invalid baseline file extension`() { - val path = resourceAsPath("/baseline_feature/invalid-txt-baseline.txt") - assertThatThrownBy { BaselineFormat().read(path) } - .isInstanceOf(BaselineFormat.InvalidState::class.java) - } - - @Test - fun `throws on an invalid baseline ID declaration`() { - val path = resourceAsPath("/baseline_feature/missing-temporary-suppressed-baseline.xml") - assertThatIllegalStateException() - .isThrownBy { BaselineFormat().read(path) } - .withMessage("The content of the ID element must not be empty") - } - - @Test - fun `supports deprecated baseline values`() { - val path = resourceAsPath("/baseline_feature/deprecated-baseline.xml") - val (manuallySuppressedIssues, currentIssues) = BaselineFormat().read(path) - - assertThat(manuallySuppressedIssues).hasSize(2) - assertThat(manuallySuppressedIssues).anySatisfy { it.startsWith("LongParameterList") } - assertThat(manuallySuppressedIssues).anySatisfy { it.startsWith("LongMethod") } - assertThat(currentIssues).hasSize(1) - assertThat(currentIssues).anySatisfy { it.startsWith("FeatureEnvy") } - } + inner class `read a baseline file` { + + @Test + fun `loads the baseline file`() { + val path = resourceAsPath("/baseline_feature/valid-baseline.xml") + val (manuallySuppressedIssues, currentIssues) = BaselineFormat().read(path) + + assertThat(manuallySuppressedIssues).hasSize(2) + assertThat(manuallySuppressedIssues).anySatisfy { it.startsWith("LongParameterList") } + assertThat(manuallySuppressedIssues).anySatisfy { it.startsWith("LongMethod") } + assertThat(currentIssues).hasSize(1) + assertThat(currentIssues).anySatisfy { it.startsWith("FeatureEnvy") } } - @Nested - inner class `writes a baseline file` { + @Test + fun `throws on an invalid baseline file extension`() { + val path = resourceAsPath("/baseline_feature/invalid-txt-baseline.txt") + assertThatThrownBy { BaselineFormat().read(path) } + .isInstanceOf(BaselineFormat.InvalidState::class.java) + } + + @Test + fun `throws on an invalid baseline ID declaration`() { + val path = resourceAsPath("/baseline_feature/missing-temporary-suppressed-baseline.xml") + assertThatIllegalStateException() + .isThrownBy { BaselineFormat().read(path) } + .withMessage("The content of the ID element must not be empty") + } + + @Test + fun `supports deprecated baseline values`() { + val path = resourceAsPath("/baseline_feature/deprecated-baseline.xml") + val (manuallySuppressedIssues, currentIssues) = BaselineFormat().read(path) + + assertThat(manuallySuppressedIssues).hasSize(2) + assertThat(manuallySuppressedIssues).anySatisfy { it.startsWith("LongParameterList") } + assertThat(manuallySuppressedIssues).anySatisfy { it.startsWith("LongMethod") } + assertThat(currentIssues).hasSize(1) + assertThat(currentIssues).anySatisfy { it.startsWith("FeatureEnvy") } + } + } - private val savedBaseline = Baseline(setOf("4", "2", "2"), setOf("1", "2", "3")) + @Nested + inner class `writes a baseline file` { - @Test - fun `has a new line at the end of the written baseline file`() { - val tempFile = createTempFileForTest("baseline1", ".xml") + private val savedBaseline = Baseline(setOf("4", "2", "2"), setOf("1", "2", "3")) - val format = BaselineFormat() - format.write(savedBaseline, tempFile) - val bytes = Files.readAllBytes(tempFile) - val content = String(bytes, Charsets.UTF_8) + @Test + fun `has a new line at the end of the written baseline file`() { + val tempFile = createTempFileForTest("baseline1", ".xml") - assertThat(content).endsWith(">\n") - } + val format = BaselineFormat() + format.write(savedBaseline, tempFile) + val bytes = Files.readAllBytes(tempFile) + val content = String(bytes, Charsets.UTF_8) + + assertThat(content).endsWith(">\n") + } - @Test - fun `asserts that the saved and loaded baseline files are equal`() { - val tempFile = createTempFileForTest("baseline-saved", ".xml") + @Test + fun `asserts that the saved and loaded baseline files are equal`() { + val tempFile = createTempFileForTest("baseline-saved", ".xml") - val format = BaselineFormat() - format.write(savedBaseline, tempFile) - val loadedBaseline = format.read(tempFile) + val format = BaselineFormat() + format.write(savedBaseline, tempFile) + val loadedBaseline = format.read(tempFile) - assertThat(loadedBaseline).isEqualTo(savedBaseline) - } + assertThat(loadedBaseline).isEqualTo(savedBaseline) } } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/baseline/BaselineResultMappingSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/baseline/BaselineResultMappingSpec.kt index 0fd76c4cab1..6d5698045d0 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/baseline/BaselineResultMappingSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/baseline/BaselineResultMappingSpec.kt @@ -13,7 +13,6 @@ import io.mockk.mockk import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import java.io.PrintStream import java.net.URI @@ -23,106 +22,102 @@ import java.nio.file.Path @OptIn(UnstableApi::class) class BaselineResultMappingSpec { - @Nested - inner class `a baseline result mapping` { - - private val dir = createTempDirectoryForTest("baseline_format") - private val baselineFile = dir.resolve("baseline.xml") - private val existingBaselineFile = resourceAsPath("/baseline_feature/valid-baseline.xml") - private lateinit var findings: Map> - private lateinit var finding: Finding - - @BeforeEach - fun setupMocks() { - finding = mockk() - every { finding.id }.returns("SomeIssueId") - every { finding.signature }.returns("SomeSignature") - findings = mapOf("RuleSet" to listOf(finding)) - } - - @AfterEach - fun tearDown() { - Files.deleteIfExists(baselineFile) - } - - @Test - fun `should not create a new baseline file when no findings occurred`() { - val mapping = resultMapping( - baselineFile = baselineFile, - createBaseline = true, - ) + private val dir = createTempDirectoryForTest("baseline_format") + private val baselineFile = dir.resolve("baseline.xml") + private val existingBaselineFile = resourceAsPath("/baseline_feature/valid-baseline.xml") + private lateinit var findings: Map> + private lateinit var finding: Finding + + @BeforeEach + fun setupMocks() { + finding = mockk() + every { finding.id }.returns("SomeIssueId") + every { finding.signature }.returns("SomeSignature") + findings = mapOf("RuleSet" to listOf(finding)) + } - mapping.transformFindings(emptyMap()) + @AfterEach + fun tearDown() { + Files.deleteIfExists(baselineFile) + } - assertThat(baselineFile.exists()).isFalse() - } + @Test + fun `should not create a new baseline file when no findings occurred`() { + val mapping = resultMapping( + baselineFile = baselineFile, + createBaseline = true, + ) - @Test - fun `should not update an existing baseline file if option configured as false`() { - val existing = Baseline.load(existingBaselineFile) - val mapping = resultMapping( - baselineFile = existingBaselineFile, - createBaseline = false, - ) + mapping.transformFindings(emptyMap()) - mapping.transformFindings(findings) + assertThat(baselineFile.exists()).isFalse() + } - val changed = Baseline.load(existingBaselineFile) - assertThat(existing).isEqualTo(changed) - } + @Test + fun `should not update an existing baseline file if option configured as false`() { + val existing = Baseline.load(existingBaselineFile) + val mapping = resultMapping( + baselineFile = existingBaselineFile, + createBaseline = false, + ) - @Test - fun `should not update an existing baseline file if option is not configured`() { - val existing = Baseline.load(existingBaselineFile) - val mapping = resultMapping( - baselineFile = existingBaselineFile, - createBaseline = null, - ) + mapping.transformFindings(findings) - mapping.transformFindings(findings) + val changed = Baseline.load(existingBaselineFile) + assertThat(existing).isEqualTo(changed) + } - val changed = Baseline.load(existingBaselineFile) - assertThat(existing).isEqualTo(changed) - } + @Test + fun `should not update an existing baseline file if option is not configured`() { + val existing = Baseline.load(existingBaselineFile) + val mapping = resultMapping( + baselineFile = existingBaselineFile, + createBaseline = null, + ) - @Test - fun `should not create a new baseline file if no file is configured`() { - val mapping = resultMapping( - baselineFile = null, - createBaseline = false, - ) + mapping.transformFindings(findings) - mapping.transformFindings(findings) + val changed = Baseline.load(existingBaselineFile) + assertThat(existing).isEqualTo(changed) + } - assertThat(baselineFile.exists()).isFalse() - } + @Test + fun `should not create a new baseline file if no file is configured`() { + val mapping = resultMapping( + baselineFile = null, + createBaseline = false, + ) - @Test - fun `should create a new baseline file if a file is configured`() { - val mapping = resultMapping( - baselineFile = baselineFile, - createBaseline = true, - ) + mapping.transformFindings(findings) - mapping.transformFindings(findings) + assertThat(baselineFile.exists()).isFalse() + } - assertThat(baselineFile.exists()).isTrue() - } + @Test + fun `should create a new baseline file if a file is configured`() { + val mapping = resultMapping( + baselineFile = baselineFile, + createBaseline = true, + ) - @Test - fun `should update an existing baseline file if a file is configured`() { - Files.copy(existingBaselineFile, baselineFile) - val existing = Baseline.load(baselineFile) - val mapping = resultMapping( - baselineFile = baselineFile, - createBaseline = true, - ) + mapping.transformFindings(findings) + + assertThat(baselineFile.exists()).isTrue() + } + + @Test + fun `should update an existing baseline file if a file is configured`() { + Files.copy(existingBaselineFile, baselineFile) + val existing = Baseline.load(baselineFile) + val mapping = resultMapping( + baselineFile = baselineFile, + createBaseline = true, + ) - mapping.transformFindings(findings) + mapping.transformFindings(findings) - val changed = Baseline.load(baselineFile) - assertThat(existing).isNotEqualTo(changed) - } + val changed = Baseline.load(baselineFile) + assertThat(existing).isNotEqualTo(changed) } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/config/CheckConfigurationSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/config/CheckConfigurationSpec.kt index 0f2897213ee..b5830937bcd 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/config/CheckConfigurationSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/config/CheckConfigurationSpec.kt @@ -13,85 +13,80 @@ import io.gitlab.arturbosch.detekt.core.createProcessingSettings import io.gitlab.arturbosch.detekt.core.tooling.getDefaultConfiguration import io.gitlab.arturbosch.detekt.test.yamlConfigFromContent import org.assertj.core.api.Assertions.assertThatCode -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class SupportConfigValidationSpec { - @Nested - inner class `support config validation` { + private val testDir = createTempDirectoryForTest("detekt-sample") + private val spec = createNullLoggingSpec {} - private val testDir = createTempDirectoryForTest("detekt-sample") - private val spec = createNullLoggingSpec {} + @Test + fun `fails when unknown properties are found`() { + val config = yamlConfigFromContent( + """ + # Properties of custom rule sets get excluded by default. + sample-rule-set: + TooManyFunctions: + active: true - @Test - fun `fails when unknown properties are found`() { - val config = yamlConfigFromContent( - """ - # Properties of custom rule sets get excluded by default. - sample-rule-set: - TooManyFunctions: - active: true - - # This properties are unknown to detekt and must be excluded. - my_additional_properties: - magic_number: 7 - magic_string: 'Hello World' - """ - ) - createProcessingSettings(testDir, config).use { - assertThatCode { checkConfiguration(it, spec.getDefaultConfiguration()) } - .isInstanceOf(InvalidConfig::class.java) - .hasMessageContaining("Run failed with 1 invalid config property.") - .hasMessageContaining("my_additional_properties") - } + # This properties are unknown to detekt and must be excluded. + my_additional_properties: + magic_number: 7 + magic_string: 'Hello World' + """ + ) + createProcessingSettings(testDir, config).use { + assertThatCode { checkConfiguration(it, spec.getDefaultConfiguration()) } + .isInstanceOf(InvalidConfig::class.java) + .hasMessageContaining("Run failed with 1 invalid config property.") + .hasMessageContaining("my_additional_properties") } + } - @Test - fun `fails due to custom config validator want active to be booleans`() { - val config = yamlConfigFromContent( - """ - # Properties of custom rule sets get excluded by default. - sample-rule-set: - TooManyFunctions: - # This property is tested via the SampleConfigValidator - active: 1 # should be true - """ - ) - createProcessingSettings(testDir, config).use { - assertThatCode { checkConfiguration(it, spec.getDefaultConfiguration()) } - .isInstanceOf(InvalidConfig::class.java) - .hasMessageContaining("Run failed with 1 invalid config property.") - } + @Test + fun `fails due to custom config validator want active to be booleans`() { + val config = yamlConfigFromContent( + """ + # Properties of custom rule sets get excluded by default. + sample-rule-set: + TooManyFunctions: + # This property is tested via the SampleConfigValidator + active: 1 # should be true + """ + ) + createProcessingSettings(testDir, config).use { + assertThatCode { checkConfiguration(it, spec.getDefaultConfiguration()) } + .isInstanceOf(InvalidConfig::class.java) + .hasMessageContaining("Run failed with 1 invalid config property.") } + } - @Test - fun `passes with excluded new properties`() { - val config = yamlConfigFromContent( - """ - config: - validation: true - # Additional properties can be useful when writing custom extensions. - # However only properties defined in the default config are known to detekt. - # All unknown properties are treated as errors if not excluded. - excludes: 'my_additional_properties' + @Test + fun `passes with excluded new properties`() { + val config = yamlConfigFromContent( + """ + config: + validation: true + # Additional properties can be useful when writing custom extensions. + # However only properties defined in the default config are known to detekt. + # All unknown properties are treated as errors if not excluded. + excludes: 'my_additional_properties' - # Properties of custom rule sets get excluded by default. - # If you want to validate them further, consider implementing a ConfigValidator. - sample-rule-set: - TooManyFunctions: - active: true + # Properties of custom rule sets get excluded by default. + # If you want to validate them further, consider implementing a ConfigValidator. + sample-rule-set: + TooManyFunctions: + active: true - # This properties are unknown to detekt and must be excluded. - my_additional_properties: - magic_number: 7 - magic_string: 'Hello World' - """ - ) - createProcessingSettings(testDir, config).use { - assertThatCode { checkConfiguration(it, spec.getDefaultConfiguration()) } - .doesNotThrowAnyException() - } + # This properties are unknown to detekt and must be excluded. + my_additional_properties: + magic_number: 7 + magic_string: 'Hello World' + """ + ) + createProcessingSettings(testDir, config).use { + assertThatCode { checkConfiguration(it, spec.getDefaultConfiguration()) } + .doesNotThrowAnyException() } } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/config/CompositeConfigSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/config/CompositeConfigSpec.kt index dd94389a834..45baa3fc554 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/config/CompositeConfigSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/config/CompositeConfigSpec.kt @@ -3,54 +3,49 @@ package io.gitlab.arturbosch.detekt.core.config import io.gitlab.arturbosch.detekt.test.yamlConfig import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatThrownBy -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class CompositeConfigSpec { - @Nested - inner class `both configs should be considered` { - - private val second = yamlConfig("composite-test.yml") - private val first = yamlConfig("detekt.yml") - private val compositeConfig = CompositeConfig(second, first) - - @Test - fun `should have style sub config with active false which is overridden in second config regardless of default value`() { - val styleConfig = compositeConfig.subConfig("style").subConfig("WildcardImport") - assertThat(styleConfig.valueOrDefault("active", true)).isEqualTo(false) - assertThat(styleConfig.valueOrDefault("active", false)).isEqualTo(false) - } - - @Test - fun `should have code smell sub config with LongMethod threshold 20 from _first_ config`() { - val codeSmellConfig = compositeConfig.subConfig("code-smell").subConfig("LongMethod") - assertThat(codeSmellConfig.valueOrDefault("threshold", -1)).isEqualTo(20) - } - - @Test - fun `should use the default as both part configurations do not have the value`() { - assertThat(compositeConfig.valueOrDefault("TEST", 42)).isEqualTo(42) - } - - @Test - fun `should return a string based on default value`() { - val config = compositeConfig.subConfig("style").subConfig("MagicNumber") - val value = config.valueOrDefault("ignoreNumbers", emptyList()) - assertThat(value).isEqualTo(listOf("-1", "0", "1", "2", "100", "1000")) - } - - @Test - fun `should fail with a meaningful exception when boolean property is invalid`() { - val config = compositeConfig.subConfig("style").subConfig("LargeClass") - - val expectedErrorMessage = "Value \"truuu\" set for config parameter \"style > LargeClass > active\" " + - "is not of required type Boolean" - - assertThatThrownBy { - config.valueOrDefault("active", true) - }.isInstanceOf(IllegalStateException::class.java) - .hasMessageContaining(expectedErrorMessage) - } + private val second = yamlConfig("composite-test.yml") + private val first = yamlConfig("detekt.yml") + private val compositeConfig = CompositeConfig(second, first) + + @Test + fun `should have style sub config with active false which is overridden in second config regardless of default value`() { + val styleConfig = compositeConfig.subConfig("style").subConfig("WildcardImport") + assertThat(styleConfig.valueOrDefault("active", true)).isEqualTo(false) + assertThat(styleConfig.valueOrDefault("active", false)).isEqualTo(false) + } + + @Test + fun `should have code smell sub config with LongMethod threshold 20 from _first_ config`() { + val codeSmellConfig = compositeConfig.subConfig("code-smell").subConfig("LongMethod") + assertThat(codeSmellConfig.valueOrDefault("threshold", -1)).isEqualTo(20) + } + + @Test + fun `should use the default as both part configurations do not have the value`() { + assertThat(compositeConfig.valueOrDefault("TEST", 42)).isEqualTo(42) + } + + @Test + fun `should return a string based on default value`() { + val config = compositeConfig.subConfig("style").subConfig("MagicNumber") + val value = config.valueOrDefault("ignoreNumbers", emptyList()) + assertThat(value).isEqualTo(listOf("-1", "0", "1", "2", "100", "1000")) + } + + @Test + fun `should fail with a meaningful exception when boolean property is invalid`() { + val config = compositeConfig.subConfig("style").subConfig("LargeClass") + + val expectedErrorMessage = "Value \"truuu\" set for config parameter \"style > LargeClass > active\" " + + "is not of required type Boolean" + + assertThatThrownBy { + config.valueOrDefault("active", true) + }.isInstanceOf(IllegalStateException::class.java) + .hasMessageContaining(expectedErrorMessage) } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/config/DefaultConfigValidationSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/config/DefaultConfigValidationSpec.kt index fc08fb2280e..c18e954802f 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/config/DefaultConfigValidationSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/config/DefaultConfigValidationSpec.kt @@ -2,24 +2,19 @@ package io.gitlab.arturbosch.detekt.core.config import io.gitlab.arturbosch.detekt.test.yamlConfig import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class DefaultConfigValidationSpec { - @Nested - inner class `default configuration is valid` { + private val baseline = yamlConfig("default-detekt-config.yml") - private val baseline = yamlConfig("default-detekt-config.yml") - - @Test - fun `is valid comparing itself`() { - assertThat(validateConfig(baseline, baseline)).isEmpty() - } + @Test + fun `is valid comparing itself`() { + assertThat(validateConfig(baseline, baseline)).isEmpty() + } - @Test - fun `does not flag common known config sub sections`() { - assertThat(validateConfig(yamlConfig("common_known_sections.yml"), baseline)).isEmpty() - } + @Test + fun `does not flag common known config sub sections`() { + assertThat(validateConfig(yamlConfig("common_known_sections.yml"), baseline)).isEmpty() } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/config/ValidateConfigSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/config/ValidateConfigSpec.kt index cdb427143b9..81b41bb41d1 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/config/ValidateConfigSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/config/ValidateConfigSpec.kt @@ -16,42 +16,121 @@ import org.junit.jupiter.params.provider.ValueSource class ValidateConfigSpec { - @Nested - inner class `validate configuration file` { + private val baseline = yamlConfig("config_validation/baseline.yml") + + @Test + fun `passes for same config test`() { + val result = validateConfig(baseline, baseline) + assertThat(result).isEmpty() + } + + @Test + fun `passes for properties which may appear on rules and rule sets but may be not present in default config`() { + val result = validateConfig( + yamlConfig("config_validation/default-excluded-properties.yml"), + baseline + ) + assertThat(result).isEmpty() + } + + @Test + fun `reports different rule set name`() { + val result = validateConfig( + yamlConfig("config_validation/other-ruleset-name.yml"), + baseline + ) + assertThat(result).contains(propertyDoesNotExists("code-smell")) + } + + @Test + fun `reports different nested property names`() { + val result = validateConfig( + yamlConfig("config_validation/other-nested-property-names.yml"), + baseline + ) + assertThat(result).contains( + propertyDoesNotExists("complexity>LongLongMethod"), + propertyDoesNotExists("complexity>LongParameterList>enabled"), + propertyDoesNotExists("complexity>LargeClass>howMany"), + propertyDoesNotExists("complexity>InnerMap>InnerKey"), + propertyDoesNotExists("complexity>InnerMap>Inner2>nestedActive") + ) + } + + @Test + fun `reports nested configuration expected`() { + val result = validateConfig( + yamlConfig("config_validation/no-nested-config.yml"), + baseline + ) + assertThat(result).contains( + nestedConfigurationExpected("complexity"), + nestedConfigurationExpected("style>WildcardImport") + ) + } + + @Test + fun `reports unexpected nested configs`() { + // note that the baseline config is now the first argument + val result = validateConfig(baseline, yamlConfig("config_validation/no-value.yml")) + assertThat(result).contains( + unexpectedNestedConfiguration("style"), + unexpectedNestedConfiguration("comments") + ) + } + + @Test + fun `returns an error for an invalid config type`() { + val invalidConfig = TestConfig() + assertThatIllegalStateException().isThrownBy { + validateConfig(invalidConfig, baseline) + }.withMessageStartingWith("Unsupported config type for validation") + } + + @Test + fun `returns an error for an invalid baseline`() { + val invalidBaseline = TestConfig() + assertThatIllegalArgumentException().isThrownBy { + validateConfig(Config.empty, invalidBaseline) + }.withMessageStartingWith("Only supported baseline config is the YamlConfig.") + } + + @Test + fun `returns an error for an empty baseline`() { + val invalidBaseline = Config.empty + assertThatIllegalArgumentException().isThrownBy { + validateConfig(Config.empty, invalidBaseline) + }.withMessageStartingWith("Cannot validate configuration based on an empty baseline config.") + } - private val baseline = yamlConfig("config_validation/baseline.yml") + @Nested + inner class `validate composite configurations` { @Test - fun `passes for same config test`() { - val result = validateConfig(baseline, baseline) + fun `passes for same left, right and baseline config`() { + val result = validateConfig(CompositeConfig(baseline, baseline), baseline) assertThat(result).isEmpty() } @Test - fun `passes for properties which may appear on rules and rule sets but may be not present in default config`() { - val result = validateConfig( - yamlConfig("config_validation/default-excluded-properties.yml"), - baseline - ) + fun `passes for empty configs`() { + val result = validateConfig(CompositeConfig(Config.empty, Config.empty), baseline) assertThat(result).isEmpty() } @Test - fun `reports different rule set name`() { + fun `finds accumulated errors`() { val result = validateConfig( - yamlConfig("config_validation/other-ruleset-name.yml"), + CompositeConfig( + yamlConfig("config_validation/other-nested-property-names.yml"), + yamlConfig("config_validation/no-nested-config.yml") + ), baseline ) - assertThat(result).contains(propertyDoesNotExists("code-smell")) - } - @Test - fun `reports different nested property names`() { - val result = validateConfig( - yamlConfig("config_validation/other-nested-property-names.yml"), - baseline - ) assertThat(result).contains( + nestedConfigurationExpected("complexity"), + nestedConfigurationExpected("style>WildcardImport"), propertyDoesNotExists("complexity>LongLongMethod"), propertyDoesNotExists("complexity>LongParameterList>enabled"), propertyDoesNotExists("complexity>LargeClass>howMany"), @@ -59,173 +138,90 @@ class ValidateConfigSpec { propertyDoesNotExists("complexity>InnerMap>Inner2>nestedActive") ) } + } + + @Nested + inner class `configure additional exclude paths` { + + private fun patterns(str: String) = CommaSeparatedPattern(str).mapToRegex() @Test - fun `reports nested configuration expected`() { + fun `does not report any complexity properties`() { val result = validateConfig( - yamlConfig("config_validation/no-nested-config.yml"), - baseline - ) - assertThat(result).contains( - nestedConfigurationExpected("complexity"), - nestedConfigurationExpected("style>WildcardImport") + yamlConfig("config_validation/other-nested-property-names.yml"), + baseline, + patterns("complexity") ) + assertThat(result).isEmpty() } @Test - fun `reports unexpected nested configs`() { - // note that the baseline config is now the first argument - val result = validateConfig(baseline, yamlConfig("config_validation/no-value.yml")) - assertThat(result).contains( - unexpectedNestedConfiguration("style"), - unexpectedNestedConfiguration("comments") + fun `does not report 'complexity_LargeClass_howMany'`() { + val result = validateConfig( + yamlConfig("config_validation/other-nested-property-names.yml"), + baseline, + patterns(".*>.*>howMany") ) - } - @Test - fun `returns an error for an invalid config type`() { - val invalidConfig = TestConfig() - assertThatIllegalStateException().isThrownBy { - validateConfig(invalidConfig, baseline) - }.withMessageStartingWith("Unsupported config type for validation") - } + assertThat(result).contains( + propertyDoesNotExists("complexity>LongLongMethod"), + propertyDoesNotExists("complexity>LongParameterList>enabled"), + propertyDoesNotExists("complexity>InnerMap>InnerKey"), + propertyDoesNotExists("complexity>InnerMap>Inner2>nestedActive") + ) - @Test - fun `returns an error for an invalid baseline`() { - val invalidBaseline = TestConfig() - assertThatIllegalArgumentException().isThrownBy { - validateConfig(Config.empty, invalidBaseline) - }.withMessageStartingWith("Only supported baseline config is the YamlConfig.") + assertThat(result).doesNotContain( + propertyDoesNotExists("complexity>LargeClass>howMany") + ) } @Test - fun `returns an error for an empty baseline`() { - val invalidBaseline = Config.empty - assertThatIllegalArgumentException().isThrownBy { - validateConfig(Config.empty, invalidBaseline) - }.withMessageStartingWith("Cannot validate configuration based on an empty baseline config.") - } - - @Nested - inner class `validate composite configurations` { - - @Test - fun `passes for same left, right and baseline config`() { - val result = validateConfig(CompositeConfig(baseline, baseline), baseline) - assertThat(result).isEmpty() - } - - @Test - fun `passes for empty configs`() { - val result = validateConfig(CompositeConfig(Config.empty, Config.empty), baseline) - assertThat(result).isEmpty() - } - - @Test - fun `finds accumulated errors`() { - val result = validateConfig( - CompositeConfig( - yamlConfig("config_validation/other-nested-property-names.yml"), - yamlConfig("config_validation/no-nested-config.yml") - ), - baseline - ) - - assertThat(result).contains( - nestedConfigurationExpected("complexity"), - nestedConfigurationExpected("style>WildcardImport"), - propertyDoesNotExists("complexity>LongLongMethod"), - propertyDoesNotExists("complexity>LongParameterList>enabled"), - propertyDoesNotExists("complexity>LargeClass>howMany"), - propertyDoesNotExists("complexity>InnerMap>InnerKey"), - propertyDoesNotExists("complexity>InnerMap>Inner2>nestedActive") - ) - } - } - - @Nested - inner class `configure additional exclude paths` { - - fun patterns(str: String) = CommaSeparatedPattern(str).mapToRegex() - - @Test - fun `does not report any complexity properties`() { - val result = validateConfig( - yamlConfig("config_validation/other-nested-property-names.yml"), - baseline, - patterns("complexity") - ) - assertThat(result).isEmpty() - } - - @Test - fun `does not report 'complexity_LargeClass_howMany'`() { - val result = validateConfig( - yamlConfig("config_validation/other-nested-property-names.yml"), - baseline, - patterns(".*>.*>howMany") - ) - - assertThat(result).contains( - propertyDoesNotExists("complexity>LongLongMethod"), - propertyDoesNotExists("complexity>LongParameterList>enabled"), - propertyDoesNotExists("complexity>InnerMap>InnerKey"), - propertyDoesNotExists("complexity>InnerMap>Inner2>nestedActive") - ) - - assertThat(result).doesNotContain( - propertyDoesNotExists("complexity>LargeClass>howMany") - ) - } - - @Test - @DisplayName("does not report .*>InnerMap") - fun `does not report innerMap`() { - val result = validateConfig( - yamlConfig("config_validation/other-nested-property-names.yml"), - baseline, - patterns(".*>InnerMap") - ) + @DisplayName("does not report .*>InnerMap") + fun `does not report innerMap`() { + val result = validateConfig( + yamlConfig("config_validation/other-nested-property-names.yml"), + baseline, + patterns(".*>InnerMap") + ) - assertThat(result).contains( - propertyDoesNotExists("complexity>LargeClass>howMany"), - propertyDoesNotExists("complexity>LongLongMethod"), - propertyDoesNotExists("complexity>LongParameterList>enabled") - ) + assertThat(result).contains( + propertyDoesNotExists("complexity>LargeClass>howMany"), + propertyDoesNotExists("complexity>LongLongMethod"), + propertyDoesNotExists("complexity>LongParameterList>enabled") + ) - assertThat(result).doesNotContain( - propertyDoesNotExists("complexity>InnerMap>InnerKey"), - propertyDoesNotExists("complexity>InnerMap>Inner2>nestedActive") - ) - } + assertThat(result).doesNotContain( + propertyDoesNotExists("complexity>InnerMap>InnerKey"), + propertyDoesNotExists("complexity>InnerMap>Inner2>nestedActive") + ) } + } - @Nested - inner class `deprecated configuration option` { - - @ParameterizedTest - @ValueSource(booleans = [true, false]) - fun `reports a deprecated property as a warning`(warningsAsErrors: Boolean) { - val config = yamlConfigFromContent( - """ - config: - warningsAsErrors: $warningsAsErrors - naming: - FunctionParameterNaming: - ignoreOverriddenFunctions: '' - """.trimIndent() - ) + @Nested + inner class `deprecated configuration option` { + + @ParameterizedTest + @ValueSource(booleans = [true, false]) + fun `reports a deprecated property as a warning`(warningsAsErrors: Boolean) { + val config = yamlConfigFromContent( + """ + config: + warningsAsErrors: $warningsAsErrors + naming: + FunctionParameterNaming: + ignoreOverriddenFunctions: '' + """.trimIndent() + ) - val result = validateConfig(config, config) + val result = validateConfig(config, config) - assertThat(result).contains( - propertyIsDeprecated( - "naming>FunctionParameterNaming>ignoreOverriddenFunctions", - "Use `ignoreOverridden` instead", - reportAsError = warningsAsErrors - ) + assertThat(result).contains( + propertyIsDeprecated( + "naming>FunctionParameterNaming>ignoreOverriddenFunctions", + "Use `ignoreOverridden` instead", + reportAsError = warningsAsErrors ) - } + ) } } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/OutputReportsSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/OutputReportsSpec.kt index aa2ddef139d..4f8aace147f 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/OutputReportsSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/OutputReportsSpec.kt @@ -20,102 +20,98 @@ import java.util.function.Predicate class OutputReportsSpec { @Nested - inner class `reports` { + inner class `arguments for spec` { + + private val reportUnderTest = TestOutputReport::class.java.simpleName + private val reports = ReportsSpecBuilder().apply { + report { "xml" to Paths.get("/tmp/path1") } + report { "txt" to Paths.get("/tmp/path2") } + report { reportUnderTest to Paths.get("/tmp/path3") } + report { "html" to Paths.get("D:_Gradle\\xxx\\xxx\\build\\reports\\detekt\\detekt.html") } + }.build().reports.toList() + + @Test + fun `should parse multiple report entries`() { + assertThat(reports).hasSize(4) + } - @Nested - inner class `arguments for spec` { + @Test + fun `it should properly parse XML report entry`() { + val xmlReport = reports[0] + assertThat(xmlReport.type).isEqualTo(defaultReportMapping(XmlOutputReport::class.java.simpleName)) + assertThat(xmlReport.path).isEqualTo(Paths.get("/tmp/path1")) + } - private val reportUnderTest = TestOutputReport::class.java.simpleName - private val reports = ReportsSpecBuilder().apply { - report { "xml" to Paths.get("/tmp/path1") } - report { "txt" to Paths.get("/tmp/path2") } - report { reportUnderTest to Paths.get("/tmp/path3") } - report { "html" to Paths.get("D:_Gradle\\xxx\\xxx\\build\\reports\\detekt\\detekt.html") } - }.build().reports.toList() + @Test + fun `it should properly parse TXT report entry`() { + val txtRepot = reports[1] + assertThat(txtRepot.type).isEqualTo(defaultReportMapping(TxtOutputReport::class.java.simpleName)) + assertThat(txtRepot.path).isEqualTo(Paths.get("/tmp/path2")) + } - @Test - fun `should parse multiple report entries`() { - assertThat(reports).hasSize(4) - } + @Test + fun `it should properly parse custom report entry`() { + val customReport = reports[2] + assertThat(customReport.type).isEqualTo(reportUnderTest) + assertThat(defaultReportMapping(customReport.type)).isEqualTo(reportUnderTest) + assertThat(customReport.path).isEqualTo(Paths.get("/tmp/path3")) + } - @Test - fun `it should properly parse XML report entry`() { - val xmlReport = reports[0] - assertThat(xmlReport.type).isEqualTo(defaultReportMapping(XmlOutputReport::class.java.simpleName)) - assertThat(xmlReport.path).isEqualTo(Paths.get("/tmp/path1")) - } + @Test + fun `it should properly parse HTML report entry`() { + val htmlReport = reports[3] + assertThat(htmlReport.type).isEqualTo(defaultReportMapping(HtmlOutputReport::class.java.simpleName)) + assertThat(htmlReport.path).isEqualTo( + Paths.get("D:_Gradle\\xxx\\xxx\\build\\reports\\detekt\\detekt.html") + ) + } - @Test - fun `it should properly parse TXT report entry`() { - val txtRepot = reports[1] - assertThat(txtRepot.type).isEqualTo(defaultReportMapping(TxtOutputReport::class.java.simpleName)) - assertThat(txtRepot.path).isEqualTo(Paths.get("/tmp/path2")) - } + @Nested + inner class `default report ids` { - @Test - fun `it should properly parse custom report entry`() { - val customReport = reports[2] - assertThat(customReport.type).isEqualTo(reportUnderTest) - assertThat(defaultReportMapping(customReport.type)).isEqualTo(reportUnderTest) - assertThat(customReport.path).isEqualTo(Paths.get("/tmp/path3")) - } + private val extensions = createProcessingSettings().use { OutputReportLocator(it).load() } + private val extensionsIds = extensions.mapTo(HashSet()) { defaultReportMapping(it.id) } @Test - fun `it should properly parse HTML report entry`() { - val htmlReport = reports[3] - assertThat(htmlReport.type).isEqualTo(defaultReportMapping(HtmlOutputReport::class.java.simpleName)) - assertThat(htmlReport.path).isEqualTo( - Paths.get("D:_Gradle\\xxx\\xxx\\build\\reports\\detekt\\detekt.html") - ) + fun `should be able to convert to output reports`() { + assertThat(reports).allMatch { it.type in extensionsIds } } - @Nested - inner class `default report ids` { - - private val extensions = createProcessingSettings().use { OutputReportLocator(it).load() } - private val extensionsIds = extensions.mapTo(HashSet()) { defaultReportMapping(it.id) } - - @Test - fun `should be able to convert to output reports`() { - assertThat(reports).allMatch { it.type in extensionsIds } - } - - @Test - fun `should recognize custom output format`() { - assertThat(reports).haveExactly( - 1, - Condition( - Predicate { it.type == reportUnderTest }, - "Corresponds exactly to the test output report." - ) + @Test + fun `should recognize custom output format`() { + assertThat(reports).haveExactly( + 1, + Condition( + Predicate { it.type == reportUnderTest }, + "Corresponds exactly to the test output report." ) + ) - assertThat(extensions).haveExactly( - 1, - Condition( - Predicate { it is TestOutputReport && it.ending == "yml" }, - "Is exactly the test output report." - ) + assertThat(extensions).haveExactly( + 1, + Condition( + Predicate { it is TestOutputReport && it.ending == "yml" }, + "Is exactly the test output report." ) - } + ) } } + } - @Nested - inner class `empty reports` { + @Nested + inner class `empty reports` { - @Test - fun `yields empty extension list`() { - val spec = createNullLoggingSpec { - config { - configPaths = listOf(resourceAsPath("/reporting/disabled-reports.yml")) - } + @Test + fun `yields empty extension list`() { + val spec = createNullLoggingSpec { + config { + configPaths = listOf(resourceAsPath("/reporting/disabled-reports.yml")) } + } - val extensions = spec.withSettings { ConsoleReportLocator(this).load() } + val extensions = spec.withSettings { ConsoleReportLocator(this).load() } - assertThat(extensions).isEmpty() - } + assertThat(extensions).isEmpty() } } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/ComplexityReportSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/ComplexityReportSpec.kt index 3cffd49a9c3..d2301970b2d 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/ComplexityReportSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/ComplexityReportSpec.kt @@ -11,33 +11,24 @@ import io.gitlab.arturbosch.detekt.api.Detektion import io.gitlab.arturbosch.detekt.core.DetektResult import io.gitlab.arturbosch.detekt.test.createFinding import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ComplexityReportSpec { - @Nested - inner class `complexity report` { - - @Nested - inner class `several complexity metrics` { - - @Test - fun `successfully generates a complexity report`() { - val report = ComplexityReport() - val expectedContent = readResourceContent("/reporting/complexity-report.txt") - val detektion = createDetektion() - addData(detektion) - assertThat(report.render(detektion)).isEqualTo(expectedContent) - } + @Test + fun `successfully generates a complexity report`() { + val report = ComplexityReport() + val expectedContent = readResourceContent("/reporting/complexity-report.txt") + val detektion = createDetektion() + addData(detektion) + assertThat(report.render(detektion)).isEqualTo(expectedContent) + } - @Test - fun `returns null for missing complexity metrics in report`() { - val report = ComplexityReport() - val detektion = createDetektion() - assertThat(report.render(detektion)).isNull() - } - } + @Test + fun `returns null for missing complexity metrics in report`() { + val report = ComplexityReport() + val detektion = createDetektion() + assertThat(report.render(detektion)).isNull() } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/FileBasedFindingsReportSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/FileBasedFindingsReportSpec.kt index 5be003491e3..099120ecdf4 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/FileBasedFindingsReportSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/FileBasedFindingsReportSpec.kt @@ -16,52 +16,48 @@ class FileBasedFindingsReportSpec { private val subject = createFileBasedFindingsReport() @Nested - inner class `findings report` { - - @Nested - inner class `reports the debt per file and rule set with the overall debt` { - - @Test - fun `has the reference content`() { - val expectedContent = readResourceContent("/reporting/grouped-findings-report.txt") - val detektion = object : TestDetektion() { - override val findings: Map> = mapOf( - "Ruleset1" to listOf( - createFinding(fileName = "File1.kt"), - createFinding(fileName = "File2.kt") - ), - "EmptyRuleset" to emptyList(), - "Ruleset2" to listOf(createFinding(fileName = "File1.kt")) - ) - } - - val output = subject.render(detektion)?.decolorized() - - assertThat(output).isEqualTo(expectedContent) - } - } - - @Test - fun `reports no findings`() { - val detektion = TestDetektion() - assertThat(subject.render(detektion)).isNull() - } + inner class `reports the debt per file and rule set with the overall debt` { @Test - fun `reports no findings when no rule set contains smells`() { + fun `has the reference content`() { + val expectedContent = readResourceContent("/reporting/grouped-findings-report.txt") val detektion = object : TestDetektion() { override val findings: Map> = mapOf( - "EmptySmells" to emptyList() + "Ruleset1" to listOf( + createFinding(fileName = "File1.kt"), + createFinding(fileName = "File2.kt") + ), + "EmptyRuleset" to emptyList(), + "Ruleset2" to listOf(createFinding(fileName = "File1.kt")) ) } - assertThat(subject.render(detektion)).isNull() + + val output = subject.render(detektion)?.decolorized() + + assertThat(output).isEqualTo(expectedContent) } + } - @Test - fun `should not add auto corrected issues to report`() { - val report = FileBasedFindingsReport() - AutoCorrectableIssueAssert.isReportNull(report) + @Test + fun `reports no findings`() { + val detektion = TestDetektion() + assertThat(subject.render(detektion)).isNull() + } + + @Test + fun `reports no findings when no rule set contains smells`() { + val detektion = object : TestDetektion() { + override val findings: Map> = mapOf( + "EmptySmells" to emptyList() + ) } + assertThat(subject.render(detektion)).isNull() + } + + @Test + fun `should not add auto corrected issues to report`() { + val report = FileBasedFindingsReport() + AutoCorrectableIssueAssert.isReportNull(report) } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/FindingsReportSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/FindingsReportSpec.kt index 0c0c5d56853..1b0093bb318 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/FindingsReportSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/FindingsReportSpec.kt @@ -19,75 +19,71 @@ class FindingsReportSpec { private val subject = createFindingsReport() @Nested - inner class `findings report` { - - @Nested - inner class `reports the debt per rule set and the overall debt` { - private val expectedContent = readResourceContent("/reporting/findings-report.txt") - val detektion = object : TestDetektion() { - override val findings: Map> = mapOf( - "Ruleset1" to listOf(createFinding(), createFinding()), - "EmptyRuleset" to emptyList(), - "Ruleset2" to listOf(createFinding()) - ) - } - - var output: String? = null - - @BeforeEach - fun setUp() { - output = subject.render(detektion)?.decolorized() - } + inner class `reports the debt per rule set and the overall debt` { + private val expectedContent = readResourceContent("/reporting/findings-report.txt") + val detektion = object : TestDetektion() { + override val findings: Map> = mapOf( + "Ruleset1" to listOf(createFinding(), createFinding()), + "EmptyRuleset" to emptyList(), + "Ruleset2" to listOf(createFinding()) + ) + } - @Test - fun `has the reference content`() { - assertThat(output).isEqualTo(expectedContent) - } + var output: String? = null - @Test - fun `does contain the rule set id of rule sets with findings`() { - assertThat(output).contains("TestSmell") - } + @BeforeEach + fun setUp() { + output = subject.render(detektion)?.decolorized() } @Test - fun `reports no findings`() { - val detektion = TestDetektion() - assertThat(subject.render(detektion)).isNull() + fun `has the reference content`() { + assertThat(output).isEqualTo(expectedContent) } @Test - fun `reports no findings with rule set containing no smells`() { - val detektion = object : TestDetektion() { - override val findings: Map> = mapOf( - "Ruleset" to emptyList() - ) - } - assertThat(subject.render(detektion)).isNull() + fun `does contain the rule set id of rule sets with findings`() { + assertThat(output).contains("TestSmell") } + } - @Test - fun `should not add auto corrected issues to report`() { - val report = FindingsReport() - AutoCorrectableIssueAssert.isReportNull(report) + @Test + fun `reports no findings`() { + val detektion = TestDetektion() + assertThat(subject.render(detektion)).isNull() + } + + @Test + fun `reports no findings with rule set containing no smells`() { + val detektion = object : TestDetektion() { + override val findings: Map> = mapOf( + "Ruleset" to emptyList() + ) } + assertThat(subject.render(detektion)).isNull() + } - @Test - fun `truncates long message`() { - val expectedContent = readResourceContent("/reporting/long-messages-report.txt") - val longMessage = "This is just a long message that should be truncated after a given " + - "threshold is reached." - val multilineMessage = "A multiline\n\r\tmessage.\t " - val detektion = object : TestDetektion() { - override val findings: Map> = mapOf( - "Ruleset" to listOf( - createFinding(createIssue("LongRule"), createEntity("File.kt"), longMessage), - createFinding(createIssue("MultilineRule"), createEntity("File.kt"), multilineMessage), - ), - ) - } - assertThat(subject.render(detektion)?.decolorized()).isEqualTo(expectedContent) + @Test + fun `should not add auto corrected issues to report`() { + val report = FindingsReport() + AutoCorrectableIssueAssert.isReportNull(report) + } + + @Test + fun `truncates long message`() { + val expectedContent = readResourceContent("/reporting/long-messages-report.txt") + val longMessage = "This is just a long message that should be truncated after a given " + + "threshold is reached." + val multilineMessage = "A multiline\n\r\tmessage.\t " + val detektion = object : TestDetektion() { + override val findings: Map> = mapOf( + "Ruleset" to listOf( + createFinding(createIssue("LongRule"), createEntity("File.kt"), longMessage), + createFinding(createIssue("MultilineRule"), createEntity("File.kt"), multilineMessage), + ), + ) } + assertThat(subject.render(detektion)?.decolorized()).isEqualTo(expectedContent) } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/LiteFindingsReportSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/LiteFindingsReportSpec.kt index 3b8fbc067de..17f03db3854 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/LiteFindingsReportSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/LiteFindingsReportSpec.kt @@ -7,49 +7,45 @@ import io.gitlab.arturbosch.detekt.core.reporting.AutoCorrectableIssueAssert import io.gitlab.arturbosch.detekt.test.TestDetektion import io.gitlab.arturbosch.detekt.test.createFinding import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class LiteFindingsReportSpec { private val subject = createFindingsReport() - @Nested - inner class `findings report` { - @Test - fun `reports non-empty findings`() { - assertThat( - subject - .render( - TestDetektion( - createFinding("SpacingBetweenPackageAndImports"), - createFinding("UnnecessarySafeCall") - ) + @Test + fun `reports non-empty findings`() { + assertThat( + subject + .render( + TestDetektion( + createFinding("SpacingBetweenPackageAndImports"), + createFinding("UnnecessarySafeCall") ) - ).isEqualTo(readResourceContent("/reporting/lite-findings-report.txt")) - } + ) + ).isEqualTo(readResourceContent("/reporting/lite-findings-report.txt")) + } - @Test - fun `reports no findings`() { - val detektion = TestDetektion() - assertThat(subject.render(detektion)).isNull() - } + @Test + fun `reports no findings`() { + val detektion = TestDetektion() + assertThat(subject.render(detektion)).isNull() + } - @Test - fun `reports no findings with rule set containing no smells`() { - val detektion = object : TestDetektion() { - override val findings: Map> = mapOf( - "Ruleset" to emptyList() - ) - } - assertThat(subject.render(detektion)).isNull() + @Test + fun `reports no findings with rule set containing no smells`() { + val detektion = object : TestDetektion() { + override val findings: Map> = mapOf( + "Ruleset" to emptyList() + ) } + assertThat(subject.render(detektion)).isNull() + } - @Test - fun `should not add auto corrected issues to report`() { - val report = LiteFindingsReport() - AutoCorrectableIssueAssert.isReportNull(report) - } + @Test + fun `should not add auto corrected issues to report`() { + val report = LiteFindingsReport() + AutoCorrectableIssueAssert.isReportNull(report) } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/NotificationReportSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/NotificationReportSpec.kt index 9edef8c1ef3..b99ec6c0ea2 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/NotificationReportSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/NotificationReportSpec.kt @@ -4,28 +4,23 @@ import io.gitlab.arturbosch.detekt.api.internal.SimpleNotification import io.gitlab.arturbosch.detekt.core.NL import io.gitlab.arturbosch.detekt.test.TestDetektion import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class NotificationReportSpec { private val subject = NotificationReport() - @Nested - inner class `notification report` { - - @Test - fun `reports two notifications`() { - val detektion = object : TestDetektion() { - override val notifications = listOf(SimpleNotification("test"), SimpleNotification("test")) - } - assertThat(subject.render(detektion)).isEqualTo("test${NL}test") + @Test + fun `reports two notifications`() { + val detektion = object : TestDetektion() { + override val notifications = listOf(SimpleNotification("test"), SimpleNotification("test")) } + assertThat(subject.render(detektion)).isEqualTo("test${NL}test") + } - @Test - fun `reports no findings`() { - val detektion = TestDetektion() - assertThat(subject.render(detektion)).isNull() - } + @Test + fun `reports no findings`() { + val detektion = TestDetektion() + assertThat(subject.render(detektion)).isNull() } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/ProjectStatisticsReportSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/ProjectStatisticsReportSpec.kt index 31085900509..725c20033b4 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/ProjectStatisticsReportSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/reporting/console/ProjectStatisticsReportSpec.kt @@ -3,31 +3,26 @@ package io.gitlab.arturbosch.detekt.core.reporting.console import io.gitlab.arturbosch.detekt.api.ProjectMetric import io.gitlab.arturbosch.detekt.test.TestDetektion import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ProjectStatisticsReportSpec { private val subject = ProjectStatisticsReport() - @Nested - inner class `project statistics` { - - @Test - fun `reports the project statistics`() { - val expected = "Project Statistics:\n\t- M2: 2\n\t- M1: 1\n" - val detektion = object : TestDetektion() { - override val metrics: Collection = listOf( - ProjectMetric("M1", 1, priority = 1), - ProjectMetric("M2", 2, priority = 2) - ) - } - assertThat(subject.render(detektion)).isEqualTo(expected) + @Test + fun `reports the project statistics`() { + val expected = "Project Statistics:\n\t- M2: 2\n\t- M1: 1\n" + val detektion = object : TestDetektion() { + override val metrics: Collection = listOf( + ProjectMetric("M1", 1, priority = 1), + ProjectMetric("M2", 2, priority = 2) + ) } + assertThat(subject.render(detektion)).isEqualTo(expected) + } - @Test - fun `does not report anything for zero metrics`() { - assertThat(subject.render(TestDetektion())).isNull() - } + @Test + fun `does not report anything for zero metrics`() { + assertThat(subject.render(TestDetektion())).isNull() } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/rules/MultiRuleSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/rules/MultiRuleSpec.kt index 609e405d617..978cd9245ea 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/rules/MultiRuleSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/rules/MultiRuleSpec.kt @@ -16,61 +16,52 @@ import io.gitlab.arturbosch.detekt.test.loadRuleSet import io.gitlab.arturbosch.detekt.test.yamlConfig import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.psi.KtFile -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class MultiRuleSpec { - @Nested - inner class `a multi rule` { - - private val file = compileForTest(resourceAsPath("/cases/Default.kt")) - - @Nested - inner class `runs once on a KtFile for every rules and respects configured path filters` { - - @Test - fun `should not run any rules if rule set defines the filter`() { - val config = yamlConfig("/pathFilters/multi-rule-with-excludes-on-ruleset.yml") - assertThat(config.subConfig("TestMultiRule").shouldAnalyzeFile(file)).isFalse() - } - - @Test - fun `should not run any rules if rule set defines the filter with string`() { - val config = yamlConfig("/pathFilters/multi-rule-with-excludes-on-ruleset-string.yml") - assertThat(config.subConfig("TestMultiRule").shouldAnalyzeFile(file)).isFalse() - } - - @Test - fun `should only run one rule as the other is filtered`() { - val config = yamlConfig("/pathFilters/multi-rule-with-one-exclude.yml") - assertThat(loadRuleSet(config).visitFile(file)).hasSize(1) - } - - @Test - fun `should only run one rule as the other is filtered with string`() { - val config = yamlConfig("/pathFilters/multi-rule-with-one-exclude-string.yml") - assertThat(loadRuleSet(config).visitFile(file)).hasSize(1) - } - - @Test - fun `should run both when no filter is applied`() { - val config = yamlConfig("/pathFilters/multi-rule-without-excludes.yml") - assertThat(loadRuleSet(config).visitFile(file)).hasSize(2) - } - - @Test - fun `should run none when both rules are filtered`() { - val config = yamlConfig("/pathFilters/multi-rule-with-excludes.yml") - assertThat(loadRuleSet(config).visitFile(file)).isEmpty() - } - - @Test - fun `should run none when both rules are filtered with string`() { - val config = yamlConfig("/pathFilters/multi-rule-with-excludes-string.yml") - assertThat(loadRuleSet(config).visitFile(file)).isEmpty() - } - } + private val file = compileForTest(resourceAsPath("/cases/Default.kt")) + + @Test + fun `should not run any rules if rule set defines the filter`() { + val config = yamlConfig("/pathFilters/multi-rule-with-excludes-on-ruleset.yml") + assertThat(config.subConfig("TestMultiRule").shouldAnalyzeFile(file)).isFalse() + } + + @Test + fun `should not run any rules if rule set defines the filter with string`() { + val config = yamlConfig("/pathFilters/multi-rule-with-excludes-on-ruleset-string.yml") + assertThat(config.subConfig("TestMultiRule").shouldAnalyzeFile(file)).isFalse() + } + + @Test + fun `should only run one rule as the other is filtered`() { + val config = yamlConfig("/pathFilters/multi-rule-with-one-exclude.yml") + assertThat(loadRuleSet(config).visitFile(file)).hasSize(1) + } + + @Test + fun `should only run one rule as the other is filtered with string`() { + val config = yamlConfig("/pathFilters/multi-rule-with-one-exclude-string.yml") + assertThat(loadRuleSet(config).visitFile(file)).hasSize(1) + } + + @Test + fun `should run both when no filter is applied`() { + val config = yamlConfig("/pathFilters/multi-rule-without-excludes.yml") + assertThat(loadRuleSet(config).visitFile(file)).hasSize(2) + } + + @Test + fun `should run none when both rules are filtered`() { + val config = yamlConfig("/pathFilters/multi-rule-with-excludes.yml") + assertThat(loadRuleSet(config).visitFile(file)).isEmpty() + } + + @Test + fun `should run none when both rules are filtered with string`() { + val config = yamlConfig("/pathFilters/multi-rule-with-excludes-string.yml") + assertThat(loadRuleSet(config).visitFile(file)).isEmpty() } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/rules/RuleSetLocatorSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/rules/RuleSetLocatorSpec.kt index 4d6922e33d5..3b2cb2f8033 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/rules/RuleSetLocatorSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/rules/RuleSetLocatorSpec.kt @@ -5,36 +5,31 @@ import io.gitlab.arturbosch.detekt.core.createNullLoggingSpec import io.gitlab.arturbosch.detekt.core.tooling.withSettings import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.fail -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import org.reflections.Reflections import java.lang.reflect.Modifier class RuleSetLocatorSpec { - @Nested - inner class `locating RuleSetProvider's` { + @Test + fun `contains all RuleSetProviders`() { + val providers = createNullLoggingSpec().withSettings { RuleSetLocator(this).load() } + val providerClasses = getProviderClasses() - @Test - fun `contains all RuleSetProviders`() { - val providers = createNullLoggingSpec().withSettings { RuleSetLocator(this).load() } - val providerClasses = getProviderClasses() - - assertThat(providerClasses).isNotEmpty - providerClasses - .filter { clazz -> providers.none { it.javaClass == clazz } } - .forEach { fail("$it rule set is not loaded by the RuleSetLocator") } - } + assertThat(providerClasses).isNotEmpty + providerClasses + .filter { clazz -> providers.none { it.javaClass == clazz } } + .forEach { fail("$it rule set is not loaded by the RuleSetLocator") } + } - @Test - fun `does not load any default rule set provider when opt out`() { - val providers = createNullLoggingSpec { extensions { disableDefaultRuleSets = true } } - .withSettings { RuleSetLocator(this).load() } + @Test + fun `does not load any default rule set provider when opt out`() { + val providers = createNullLoggingSpec { extensions { disableDefaultRuleSets = true } } + .withSettings { RuleSetLocator(this).load() } - val defaultProviders = getProviderClasses().toSet() + val defaultProviders = getProviderClasses().toSet() - assertThat(providers).noneMatch { it.javaClass in defaultProviders } - } + assertThat(providers).noneMatch { it.javaClass in defaultProviders } } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/rules/RuleSetSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/rules/RuleSetSpec.kt index 3db56ad7598..8e877632c47 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/rules/RuleSetSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/rules/RuleSetSpec.kt @@ -13,49 +13,45 @@ import org.junit.jupiter.api.Test class RuleSetSpec { @Nested - inner class `rule sets` { + inner class `should rule set be used` { - @Nested - inner class `should rule set be used` { + @Test + fun `is explicitly deactivated`() { + val config = yamlConfig("configs/deactivated_ruleset.yml") + assertThat(config.subConfig("comments").isActive()).isFalse() + } + + @Test + fun `is active with an empty config`() { + assertThat(Config.empty.isActive()).isTrue() + } + } - @Test - fun `is explicitly deactivated`() { - val config = yamlConfig("configs/deactivated_ruleset.yml") - assertThat(config.subConfig("comments").isActive()).isFalse() - } + @Nested + inner class `should rule analyze a file` { + + private val file = compileForTest(resourceAsPath("/cases/Default.kt")) + + @Test + fun `analyzes file with an empty config`() { + val config = Config.empty + assertThat(config.subConfig("comments").shouldAnalyzeFile(file)).isTrue() + } - @Test - fun `is active with an empty config`() { - assertThat(Config.empty.isActive()).isTrue() - } + @Test + @DisplayName("should not analyze file with **/*.kt excludes") + fun ignoreExcludedKt() { + val config = TestConfig(Config.EXCLUDES_KEY to "**/*.kt") + assertThat(config.subConfig("comments").shouldAnalyzeFile(file)).isFalse() } - @Nested - inner class `should rule analyze a file` { - - private val file = compileForTest(resourceAsPath("/cases/Default.kt")) - - @Test - fun `analyzes file with an empty config`() { - val config = Config.empty - assertThat(config.subConfig("comments").shouldAnalyzeFile(file)).isTrue() - } - - @Test - @DisplayName("should not analyze file with **/*.kt excludes") - fun ignoreExcludedKt() { - val config = TestConfig(Config.EXCLUDES_KEY to "**/*.kt") - assertThat(config.subConfig("comments").shouldAnalyzeFile(file)).isFalse() - } - - @Test - fun `should analyze file as it's path is first excluded but then included`() { - val config = TestConfig( - Config.EXCLUDES_KEY to "**/*.kt", - Config.INCLUDES_KEY to "**/*.kt" - ) - assertThat(config.subConfig("comments").shouldAnalyzeFile(file)).isTrue() - } + @Test + fun `should analyze file as it's path is first excluded but then included`() { + val config = TestConfig( + Config.EXCLUDES_KEY to "**/*.kt", + Config.INCLUDES_KEY to "**/*.kt" + ) + assertThat(config.subConfig("comments").shouldAnalyzeFile(file)).isTrue() } } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/rules/SingleRuleProviderSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/rules/SingleRuleProviderSpec.kt index e81d259d6ae..c47f2a33fd3 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/rules/SingleRuleProviderSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/rules/SingleRuleProviderSpec.kt @@ -9,50 +9,41 @@ import io.gitlab.arturbosch.detekt.api.RuleSetProvider import io.gitlab.arturbosch.detekt.api.Severity import io.gitlab.arturbosch.detekt.test.yamlConfigFromContent import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource class SingleRuleProviderSpec { - @Nested - inner class `SingleRuleProvider` { - - private val provider = SingleRuleProvider( - "MagicNumber", - object : RuleSetProvider { - override val ruleSetId: String = "style" - override fun instance(config: Config): RuleSet { - val rule = object : Rule(config) { - override val issue = Issue( - "MagicNumber", - Severity.CodeSmell, - "", - Debt.FIVE_MINS - ) - } - return RuleSet(ruleSetId, listOf(rule)) + private val provider = SingleRuleProvider( + "MagicNumber", + object : RuleSetProvider { + override val ruleSetId: String = "style" + override fun instance(config: Config): RuleSet { + val rule = object : Rule(config) { + override val issue = Issue( + "MagicNumber", + Severity.CodeSmell, + "", + Debt.FIVE_MINS + ) } + return RuleSet(ruleSetId, listOf(rule)) } + } + ) + + @ParameterizedTest + @ValueSource(booleans = [true, false]) + fun `the right sub config is passed to the rule configures rule with active=$value`(value: Boolean) { + val config = yamlConfigFromContent( + """ + style: + MagicNumber: + active: $value + """.trimIndent() ) - @Nested - inner class `the right sub config is passed to the rule` { - - @ParameterizedTest - @ValueSource(booleans = [true, false]) - fun `configures rule with active=$value`(value: Boolean) { - val config = yamlConfigFromContent( - """ - style: - MagicNumber: - active: $value - """.trimIndent() - ) - - assertThat(produceRule(provider, config).active).isEqualTo(value) - } - } + assertThat(produceRule(provider, config).active).isEqualTo(value) } } diff --git a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/settings/EnvironmentFacadeSpec.kt b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/settings/EnvironmentFacadeSpec.kt index 42d067ee024..faadcadadf5 100644 --- a/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/settings/EnvironmentFacadeSpec.kt +++ b/detekt-core/src/test/kotlin/io/gitlab/arturbosch/detekt/core/settings/EnvironmentFacadeSpec.kt @@ -4,25 +4,20 @@ import io.gitlab.arturbosch.detekt.core.createNullLoggingSpec import io.gitlab.arturbosch.detekt.core.createProcessingSettings import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.konan.file.File -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class EnvironmentFacadeSpec { - @Nested - inner class `classpath entries should be separated by platform-specific separator` { - - val classpath = when (File.pathSeparator) { - ":" -> "/path/to/file1:/path/to/file2:/path/to/file3" - ";" -> """C:\path\to\file1;C:\path\to\file2;C:\path\to\file3""" - else -> "" - } + private val classpath = when (File.pathSeparator) { + ":" -> "/path/to/file1:/path/to/file2:/path/to/file3" + ";" -> """C:\path\to\file1;C:\path\to\file2;C:\path\to\file3""" + else -> "" + } - @Test - fun `supports ${File_pathSeparator}`() { - testSettings(classpath).use { - assertThat(it.classpath).hasSize(3) - } + @Test + fun `classpath entries should be separated by platform-specific separator supports ${File_pathSeparator}`() { + testSettings(classpath).use { + assertThat(it.classpath).hasSize(3) } } } diff --git a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/ArgumentListWrappingSpec.kt b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/ArgumentListWrappingSpec.kt index 4f1a3008f82..8fca235ae0d 100644 --- a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/ArgumentListWrappingSpec.kt +++ b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/ArgumentListWrappingSpec.kt @@ -4,57 +4,52 @@ import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.formatting.wrappers.ArgumentListWrapping import io.gitlab.arturbosch.detekt.test.TestConfig import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ArgumentListWrappingSpec { - @Nested - inner class `ArgumentListWrapping rule` { - - @Test - fun `reports wrong argument wrapping`() { - val code = """ - val x = f( - 1, - 2, 3 - ) - """.trimIndent() - assertThat(ArgumentListWrapping(Config.empty).lint(code)).hasSize(1) - } + @Test + fun `reports wrong argument wrapping`() { + val code = """ + val x = f( + 1, + 2, 3 + ) + """.trimIndent() + assertThat(ArgumentListWrapping(Config.empty).lint(code)).hasSize(1) + } - @Test - fun `does not report correct argument list wrapping`() { - val code = """ - val x = f( - 1, - 2, - 3 - ) - """.trimIndent() - assertThat(ArgumentListWrapping(Config.empty).lint(code)).isEmpty() - } + @Test + fun `does not report correct argument list wrapping`() { + val code = """ + val x = f( + 1, + 2, + 3 + ) + """.trimIndent() + assertThat(ArgumentListWrapping(Config.empty).lint(code)).isEmpty() + } - @Test - fun `does not report when overriding an indentation level config of 1`() { - val code = """ - val x = f( - 1, - 2, - 3 - ) - """.trimIndent() - val config = TestConfig("indentSize" to "1") - assertThat(ArgumentListWrapping(config).lint(code)).isEmpty() - } + @Test + fun `does not report when overriding an indentation level config of 1`() { + val code = """ + val x = f( + 1, + 2, + 3 + ) + """.trimIndent() + val config = TestConfig("indentSize" to "1") + assertThat(ArgumentListWrapping(config).lint(code)).isEmpty() + } - @Test - fun `reports when max line length is exceeded`() { - val code = """ - val x = f(1111, 2222, 3333) - """.trimIndent() - val config = TestConfig("maxLineLength" to "10") - assertThat(ArgumentListWrapping(config).lint(code)).hasSize(4) - } + @Test + fun `reports when max line length is exceeded`() { + val code = """ + val x = f(1111, 2222, 3333) + """.trimIndent() + val config = TestConfig("maxLineLength" to "10") + assertThat(ArgumentListWrapping(config).lint(code)).hasSize(4) } } diff --git a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/AutoCorrectLevelSpec.kt b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/AutoCorrectLevelSpec.kt index de5e5c00cb8..21cb64584c8 100644 --- a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/AutoCorrectLevelSpec.kt +++ b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/AutoCorrectLevelSpec.kt @@ -6,69 +6,48 @@ import io.gitlab.arturbosch.detekt.test.loadRuleSet import io.gitlab.arturbosch.detekt.test.yamlConfig import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.psi.KtFile -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class AutoCorrectLevelSpec { - @Nested - inner class `test different autoCorrect levels in configuration` { + @Test + fun `autoCorrect_ true on all levels should reformat the test file`() { + val config = yamlConfig("/autocorrect/autocorrect-all-true.yml") - @Nested - inner class `autoCorrect_ true on all levels` { + val (file, findings) = runRule(config) - @Test - fun `should reformat the test file`() { - val config = yamlConfig("/autocorrect/autocorrect-all-true.yml") - - val (file, findings) = runRule(config) - - assertThat(wasLinted(findings)).isTrue() - assertThat(wasFormatted(file)).isTrue() - } - } - - @Nested - inner class `autoCorrect_ false on ruleSet level` { - - @Test - fun `should not reformat the test file`() { - val config = yamlConfig("/autocorrect/autocorrect-ruleset-false.yml") - - val (file, findings) = runRule(config) + assertThat(wasLinted(findings)).isTrue() + assertThat(wasFormatted(file)).isTrue() + } - assertThat(wasLinted(findings)).isTrue() - assertThat(wasFormatted(file)).isFalse() - } - } + @Test + fun `autoCorrect_ false on ruleSet level should not reformat the test file`() { + val config = yamlConfig("/autocorrect/autocorrect-ruleset-false.yml") - @Nested - inner class `autoCorrect_ false on rule level` { + val (file, findings) = runRule(config) - @Test - fun `should not reformat the test file`() { - val config = yamlConfig("/autocorrect/autocorrect-rule-false.yml") + assertThat(wasLinted(findings)).isTrue() + assertThat(wasFormatted(file)).isFalse() + } - val (file, findings) = runRule(config) + @Test + fun `autoCorrect_ false on rule level should not reformat the test file`() { + val config = yamlConfig("/autocorrect/autocorrect-rule-false.yml") - assertThat(wasLinted(findings)).isTrue() - assertThat(wasFormatted(file)).isFalse() - } - } + val (file, findings) = runRule(config) - @Nested - inner class `autoCorrect_ true but rule active false` { + assertThat(wasLinted(findings)).isTrue() + assertThat(wasFormatted(file)).isFalse() + } - @Test - fun `should not reformat the test file`() { - val config = yamlConfig("/autocorrect/autocorrect-true-rule-active-false.yml") + @Test + fun `autoCorrect_ true but rule active false should not reformat the test file`() { + val config = yamlConfig("/autocorrect/autocorrect-true-rule-active-false.yml") - val (file, findings) = runRule(config) + val (file, findings) = runRule(config) - assertThat(wasLinted(findings)).isFalse() - assertThat(wasFormatted(file)).isFalse() - } - } + assertThat(wasLinted(findings)).isFalse() + assertThat(wasFormatted(file)).isFalse() } } diff --git a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/ChainWrappingSpec.kt b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/ChainWrappingSpec.kt index 720b10c76e6..1fd88a0edc9 100644 --- a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/ChainWrappingSpec.kt +++ b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/ChainWrappingSpec.kt @@ -3,23 +3,18 @@ package io.gitlab.arturbosch.detekt.formatting import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.formatting.wrappers.ChainWrapping import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ChainWrappingSpec { - @Nested - inner class `tests integration of formatting` { + @Test + fun `should work like KtLint`() { + val subject = loadFile("configTests/chain-wrapping-before.kt") + val expected = loadFileContent("configTests/chain-wrapping-after.kt") - @Test - fun `should work like KtLint`() { - val subject = loadFile("configTests/chain-wrapping-before.kt") - val expected = loadFileContent("configTests/chain-wrapping-after.kt") + val findings = ChainWrapping(Config.empty).lint(subject.text) - val findings = ChainWrapping(Config.empty).lint(subject.text) - - assertThat(findings).isNotEmpty - assertThat(subject.text).isEqualTo(expected) - } + assertThat(findings).isNotEmpty + assertThat(subject.text).isEqualTo(expected) } } diff --git a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/FinalNewlineSpec.kt b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/FinalNewlineSpec.kt index e1cec39b922..c7c0be1b991 100644 --- a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/FinalNewlineSpec.kt +++ b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/FinalNewlineSpec.kt @@ -4,54 +4,49 @@ import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.formatting.wrappers.FinalNewline import io.gitlab.arturbosch.detekt.test.TestConfig import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class FinalNewlineSpec { - @Nested - inner class `FinalNewline rule` { + @Test + fun `should report missing new line by default`() { + val findings = FinalNewline(Config.empty) + .lint("fun main() = Unit") - @Test - fun `should report missing new line by default`() { - val findings = FinalNewline(Config.empty) - .lint("fun main() = Unit") + assertThat(findings).hasSize(1) + } + + @Test + fun `should not report as new line is present`() { + val findings = FinalNewline(Config.empty).lint( + """ + fun main() = Unit - assertThat(findings).hasSize(1) - } + """ + ) + + assertThat(findings).isEmpty() + } - @Test - fun `should not report as new line is present`() { - val findings = FinalNewline(Config.empty).lint( + @Test + fun `should report new line when configured`() { + val findings = FinalNewline(TestConfig(INSERT_FINAL_NEWLINE_KEY to "false")) + .lint( """ - fun main() = Unit + fun main() = Unit """ ) - assertThat(findings).isEmpty() - } - - @Test - fun `should report new line when configured`() { - val findings = FinalNewline(TestConfig(INSERT_FINAL_NEWLINE_KEY to "false")) - .lint( - """ - fun main() = Unit - - """ - ) - - assertThat(findings).hasSize(1) - } + assertThat(findings).hasSize(1) + } - @Test - fun `should not report when no new line is configured and not present`() { - val findings = FinalNewline(TestConfig(INSERT_FINAL_NEWLINE_KEY to "false")) - .lint("fun main() = Unit") + @Test + fun `should not report when no new line is configured and not present`() { + val findings = FinalNewline(TestConfig(INSERT_FINAL_NEWLINE_KEY to "false")) + .lint("fun main() = Unit") - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() } } diff --git a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/ImportOrderingSpec.kt b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/ImportOrderingSpec.kt index 974f44ac7c4..3ae5c1b57f4 100644 --- a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/ImportOrderingSpec.kt +++ b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/ImportOrderingSpec.kt @@ -16,113 +16,109 @@ import org.junit.jupiter.api.Test */ class ImportOrderingSpec { + @Test + fun `defaults to the idea layout`() { + val findings = ImportOrdering(Config.empty).lint( + """ + import android.app.Activity + import android.view.View + import android.view.ViewGroup + import kotlinx.coroutines.CoroutineDispatcher + import ru.example.a + import java.util.List + import javax.net.ssl.SSLHandshakeException + import kotlin.concurrent.Thread + import kotlin.io.Closeable + import android.content.Context as Ctx + import androidx.fragment.app.Fragment as F + """.trimIndent() + ) + + assertThat(findings).isEmpty() + } + @Nested - inner class `different import ordering layouts` { + inner class `can be configured to use the ascii one` { + + val negativeCase = """ + import a.A + import a.AB + import b.C + """.trimIndent() + + val positiveCase = """ + import a.A + import java.util.ArrayList + import a.AB + """.trimIndent() @Test - fun `defaults to the idea layout`() { - val findings = ImportOrdering(Config.empty).lint( - """ - import android.app.Activity - import android.view.View - import android.view.ViewGroup - import kotlinx.coroutines.CoroutineDispatcher - import ru.example.a - import java.util.List - import javax.net.ssl.SSLHandshakeException - import kotlin.concurrent.Thread - import kotlin.io.Closeable - import android.content.Context as Ctx - import androidx.fragment.app.Fragment as F - """.trimIndent() - ) + fun `passes for alphabetical order`() { + val findings = ImportOrdering(TestConfig("layout" to ImportOrdering.ASCII_PATTERN)) + .lint(negativeCase) assertThat(findings).isEmpty() } - @Nested - inner class `can be configured to use the ascii one` { + @Test + fun `fails for non alphabetical order`() { + val findings = ImportOrdering(TestConfig("layout" to ImportOrdering.ASCII_PATTERN)) + .lint(positiveCase) - val negativeCase = """ - import a.A - import a.AB - import b.C - """.trimIndent() + assertThat(findings).hasSize(1) + } - val positiveCase = """ - import a.A - import java.util.ArrayList - import a.AB - """.trimIndent() + @Nested + inner class `defaults to ascii if 'android'' property is set to true` { @Test fun `passes for alphabetical order`() { - val findings = ImportOrdering(TestConfig("layout" to ImportOrdering.ASCII_PATTERN)) - .lint(negativeCase) - - assertThat(findings).isEmpty() + assertThat(ImportOrdering(TestConfig("android" to "true")).lint(negativeCase)).isEmpty() } @Test fun `fails for non alphabetical order`() { - val findings = ImportOrdering(TestConfig("layout" to ImportOrdering.ASCII_PATTERN)) - .lint(positiveCase) - - assertThat(findings).hasSize(1) + assertThat(ImportOrdering(TestConfig("android" to "true")).lint(positiveCase)).hasSize(1) } + } + } - @Nested - inner class `defaults to ascii if 'android'' property is set to true` { + @Nested + inner class `supports custom patterns` { - @Test - fun `passes for alphabetical order`() { - assertThat(ImportOrdering(TestConfig("android" to "true")).lint(negativeCase)).isEmpty() - } + @Test + fun `misses a empty line between aliases and other imports`() { + val findings = ImportOrdering(TestConfig("layout" to "*,|,^*")).lint( + """ + import android.app.Activity + import android.view.View + import android.view.ViewGroup + import java.util.List + import kotlin.concurrent.Thread + import android.content.Context as Ctx + import androidx.fragment.app.Fragment as F + """.trimIndent() + ) - @Test - fun `fails for non alphabetical order`() { - assertThat(ImportOrdering(TestConfig("android" to "true")).lint(positiveCase)).hasSize(1) - } - } + assertThat(findings).hasSize(1) } - @Nested - inner class `supports custom patterns` { + @Test + fun `passes for empty line between aliases and other imports`() { + val findings = ImportOrdering(TestConfig("layout" to "*,|,^*")).lint( + """ + import android.app.Activity + import android.view.View + import android.view.ViewGroup + import java.util.List + import kotlin.concurrent.Thread - @Test - fun `misses a empty line between aliases and other imports`() { - val findings = ImportOrdering(TestConfig("layout" to "*,|,^*")).lint( - """ - import android.app.Activity - import android.view.View - import android.view.ViewGroup - import java.util.List - import kotlin.concurrent.Thread - import android.content.Context as Ctx - import androidx.fragment.app.Fragment as F - """.trimIndent() - ) - - assertThat(findings).hasSize(1) - } + import android.content.Context as Ctx + import androidx.fragment.app.Fragment as F + """.trimIndent() + ) - @Test - fun `passes for empty line between aliases and other imports`() { - val findings = ImportOrdering(TestConfig("layout" to "*,|,^*")).lint( - """ - import android.app.Activity - import android.view.View - import android.view.ViewGroup - import java.util.List - import kotlin.concurrent.Thread - - import android.content.Context as Ctx - import androidx.fragment.app.Fragment as F - """.trimIndent() - ) - - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() } } } diff --git a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/IndentationSpec.kt b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/IndentationSpec.kt index 4188266581c..4132f564fc0 100644 --- a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/IndentationSpec.kt +++ b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/IndentationSpec.kt @@ -19,61 +19,57 @@ class IndentationSpec { } @Nested - inner class `Indentation rule` { + inner class `indentation level equals 1` { - @Nested - inner class `indentation level equals 1` { - - val code = "fun main() {\n println()\n}" - - @Nested - inner class `indentation level config of default` { + val code = "fun main() {\n println()\n}" - @Test - fun `reports wrong indentation level`() { - assertThat(subject.lint(code)).hasSize(1) - } + @Nested + inner class `indentation level config of default` { - @Test - fun `places finding location to the indentation`() { - subject.lint(code).assert() - .hasSourceLocation(2, 1) - .hasTextLocations(13 to 14) - } + @Test + fun `reports wrong indentation level`() { + assertThat(subject.lint(code)).hasSize(1) } @Test - fun `does not report when using an indentation level config of 1`() { - val config = TestConfig("indentSize" to "1") - assertThat(Indentation(config).lint(code)).isEmpty() + fun `places finding location to the indentation`() { + subject.lint(code).assert() + .hasSourceLocation(2, 1) + .hasTextLocations(13 to 14) } } @Test - fun `does not report correct indentation level`() { - val code = "fun main() {\n println()\n}" - assertThat(subject.lint(code)).isEmpty() + fun `does not report when using an indentation level config of 1`() { + val config = TestConfig("indentSize" to "1") + assertThat(Indentation(config).lint(code)).isEmpty() } + } - @Nested - inner class `parameter list indent size equals 1` { + @Test + fun `does not report correct indentation level`() { + val code = "fun main() {\n println()\n}" + assertThat(subject.lint(code)).isEmpty() + } - val code = """ - fun f( - a: Int - ) {} - """.trimIndent() + @Nested + inner class `parameter list indent size equals 1` { - @Test - fun `reports wrong indent size`() { - assertThat(subject.lint(code)).hasSize(1) - } + val code = """ + fun f( + a: Int + ) {} + """.trimIndent() - @Test - fun `does not report when using an indentation level config of 1`() { - val config = TestConfig("indentSize" to "1") - assertThat(Indentation(config).lint(code)).isEmpty() - } + @Test + fun `reports wrong indent size`() { + assertThat(subject.lint(code)).hasSize(1) + } + + @Test + fun `does not report when using an indentation level config of 1`() { + val config = TestConfig("indentSize" to "1") + assertThat(Indentation(config).lint(code)).isEmpty() } } } diff --git a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/KtLintMultiRuleSpec.kt b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/KtLintMultiRuleSpec.kt index 2417a6b167c..9b225f91173 100644 --- a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/KtLintMultiRuleSpec.kt +++ b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/KtLintMultiRuleSpec.kt @@ -3,29 +3,24 @@ package io.gitlab.arturbosch.detekt.formatting import io.github.detekt.test.utils.compileContentForTest import io.gitlab.arturbosch.detekt.api.Config import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class KtLintMultiRuleSpec { - @Nested - inner class `KtLintMultiRule rule` { - - @Test - fun `sorts rules correctly`() { - val ktlintRule = KtLintMultiRule(Config.empty) - ktlintRule.visitFile(compileContentForTest("")) - val sortedRules = ktlintRule.getSortedRules() - assertThat(sortedRules).isNotEmpty - assertThat(sortedRules.indexOfFirst { it.runOnRootNodeOnly }) - .isGreaterThan(-1) - .isLessThan(sortedRules.indexOfFirst { !it.runOnRootNodeOnly }) - assertThat(sortedRules.indexOfFirst { !it.runOnRootNodeOnly }) - .isGreaterThan(-1) - .isLessThan(sortedRules.indexOfFirst { it.runOnRootNodeOnly && it.runAsLateAsPossible }) - assertThat(sortedRules.indexOfFirst { it.runOnRootNodeOnly && it.runAsLateAsPossible }) - .isGreaterThan(-1) - .isLessThan(sortedRules.indexOfFirst { it.runAsLateAsPossible && !it.runOnRootNodeOnly }) - } + @Test + fun `sorts rules correctly`() { + val ktlintRule = KtLintMultiRule(Config.empty) + ktlintRule.visitFile(compileContentForTest("")) + val sortedRules = ktlintRule.getSortedRules() + assertThat(sortedRules).isNotEmpty + assertThat(sortedRules.indexOfFirst { it.runOnRootNodeOnly }) + .isGreaterThan(-1) + .isLessThan(sortedRules.indexOfFirst { !it.runOnRootNodeOnly }) + assertThat(sortedRules.indexOfFirst { !it.runOnRootNodeOnly }) + .isGreaterThan(-1) + .isLessThan(sortedRules.indexOfFirst { it.runOnRootNodeOnly && it.runAsLateAsPossible }) + assertThat(sortedRules.indexOfFirst { it.runOnRootNodeOnly && it.runAsLateAsPossible }) + .isGreaterThan(-1) + .isLessThan(sortedRules.indexOfFirst { it.runAsLateAsPossible && !it.runOnRootNodeOnly }) } } diff --git a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/MaximumLineLengthSpec.kt b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/MaximumLineLengthSpec.kt index 9929e72e2ad..8a740ad8477 100644 --- a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/MaximumLineLengthSpec.kt +++ b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/MaximumLineLengthSpec.kt @@ -18,71 +18,67 @@ class MaximumLineLengthSpec { } @Nested - inner class `MaximumLineLength rule` { + inner class `a single function` { - @Nested - inner class `a single function` { + val code = """ + package home.test + fun f() { /* 123456789012345678901234567890 */ } + """.trimIndent() - val code = """ - package home.test - fun f() { /* 123456789012345678901234567890 */ } - """.trimIndent() - - @Test - fun `reports line which exceeds the threshold`() { - assertThat(subject.lint(code)).hasSize(1) - } - - @Test - fun `reports issues with the filename and package as signature`() { - val finding = subject.lint( - code, - Paths.get("home", "test", "Test.kt").toString() - ).first() + @Test + fun `reports line which exceeds the threshold`() { + assertThat(subject.lint(code)).hasSize(1) + } - assertThat(finding.entity.signature).isEqualTo("home.test.Test.kt:2") - } + @Test + fun `reports issues with the filename and package as signature`() { + val finding = subject.lint( + code, + Paths.get("home", "test", "Test.kt").toString() + ).first() - @Test - fun `does not report line which does not exceed the threshold`() { - val config = TestConfig(MAX_LINE_LENGTH to code.length) - assertThat(MaximumLineLength(config).lint(code)).isEmpty() - } + assertThat(finding.entity.signature).isEqualTo("home.test.Test.kt:2") } @Test fun `does not report line which does not exceed the threshold`() { - val code = "val a = 1" - assertThat(subject.lint(code)).isEmpty() + val config = TestConfig(MAX_LINE_LENGTH to code.length) + assertThat(MaximumLineLength(config).lint(code)).isEmpty() } + } - @Test - fun `reports correct line numbers`() { - val findings = subject.lint(longLines) + @Test + fun `does not report line which does not exceed the threshold`() { + val code = "val a = 1" + assertThat(subject.lint(code)).isEmpty() + } - // Note that KtLint's MaximumLineLength rule, in contrast to detekt's MaxLineLength rule, does not report - // exceeded lines in block comments. - assertThat(findings).hasSize(2) + @Test + fun `reports correct line numbers`() { + val findings = subject.lint(longLines) - assertThat(findings[0].entity.location.source.line).isEqualTo(8) - assertThat(findings[1].entity.location.source.line).isEqualTo(14) - } + // Note that KtLint's MaximumLineLength rule, in contrast to detekt's MaxLineLength rule, does not report + // exceeded lines in block comments. + assertThat(findings).hasSize(2) - @Test - fun `does not report back ticked line which exceeds the threshold`() { - val code = """ - package home.test - fun `this is a test method that has more than 30 characters inside the back ticks`() { - } - """.trimIndent() - val findings = MaximumLineLength( - TestConfig( - MAX_LINE_LENGTH to "30", - "ignoreBackTickedIdentifier" to "true" - ) - ).lint(code) - assertThat(findings).isEmpty() - } + assertThat(findings[0].entity.location.source.line).isEqualTo(8) + assertThat(findings[1].entity.location.source.line).isEqualTo(14) + } + + @Test + fun `does not report back ticked line which exceeds the threshold`() { + val code = """ + package home.test + fun `this is a test method that has more than 30 characters inside the back ticks`() { + } + """.trimIndent() + val findings = MaximumLineLength( + TestConfig( + MAX_LINE_LENGTH to "30", + "ignoreBackTickedIdentifier" to "true" + ) + ).lint(code) + assertThat(findings).isEmpty() } } diff --git a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/ParameterListWrappingSpec.kt b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/ParameterListWrappingSpec.kt index efb2f1b33e8..359711daf7e 100644 --- a/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/ParameterListWrappingSpec.kt +++ b/detekt-formatting/src/test/kotlin/io/gitlab/arturbosch/detekt/formatting/ParameterListWrappingSpec.kt @@ -5,7 +5,6 @@ import io.gitlab.arturbosch.detekt.formatting.wrappers.ParameterListWrapping import io.gitlab.arturbosch.detekt.test.TestConfig import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ParameterListWrappingSpec { @@ -17,26 +16,22 @@ class ParameterListWrappingSpec { subject = ParameterListWrapping(Config.empty) } - @Nested - inner class `ParameterListWrapping rule` { - - @Test - fun `does not report correct ParameterListWrapping level`() { - val code = """ - fun f( - a: Int - ) {} - """.trimIndent() - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `does not report correct ParameterListWrapping level`() { + val code = """ + fun f( + a: Int + ) {} + """.trimIndent() + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `reports when max line length is exceeded`() { - val code = """ - fun f(a: Int, b: Int, c: Int) {} - """.trimIndent() - val config = TestConfig("maxLineLength" to "10") - assertThat(ParameterListWrapping(config).lint(code)).hasSize(4) - } + @Test + fun `reports when max line length is exceeded`() { + val code = """ + fun f(a: Int, b: Int, c: Int) {} + """.trimIndent() + val config = TestConfig("maxLineLength" to "10") + assertThat(ParameterListWrapping(config).lint(code)).hasSize(4) } } diff --git a/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/collection/ConfigurationSpec.kt b/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/collection/ConfigurationSpec.kt index 592a0c4254b..1060f14b327 100644 --- a/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/collection/ConfigurationSpec.kt +++ b/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/collection/ConfigurationSpec.kt @@ -17,65 +17,62 @@ private val defaultConfiguration = Configuration( class ConfigurationSpec { @Nested - inner class `default value to list conversion` { - @Nested - inner class `empty default value` { - private val subject = defaultConfiguration.copy(defaultValue = of("")) + inner class `empty default value` { + private val subject = defaultConfiguration.copy(defaultValue = of("")) - @Test - fun `identifies default as not a list`() { - assertThat(subject.isDefaultValueNonEmptyList()).isFalse() - } + @Test + fun `identifies default as not a list`() { + assertThat(subject.isDefaultValueNonEmptyList()).isFalse() + } - @Test - fun `fails when attempting conversion`() { - assertThatIllegalStateException().isThrownBy { subject.getDefaultValueAsList() } - } + @Test + fun `fails when attempting conversion`() { + assertThatIllegalStateException().isThrownBy { subject.getDefaultValueAsList() } } + } - @Nested - inner class `non list default value` { - private val subject = defaultConfiguration.copy(defaultValue = of("abc")) + @Nested + inner class `non list default value` { + private val subject = defaultConfiguration.copy(defaultValue = of("abc")) - @Test - fun `identifies default as not a list`() { - assertThat(subject.isDefaultValueNonEmptyList()).isFalse() - } + @Test + fun `identifies default as not a list`() { + assertThat(subject.isDefaultValueNonEmptyList()).isFalse() + } - @Test - fun `fails when attempting conversion`() { - assertThatIllegalStateException().isThrownBy { subject.getDefaultValueAsList() } - } + @Test + fun `fails when attempting conversion`() { + assertThatIllegalStateException().isThrownBy { subject.getDefaultValueAsList() } } + } - @Nested - inner class `empty list default value` { - private val subject = defaultConfiguration.copy(defaultValue = of(emptyList())) + @Nested + inner class `empty list default value` { + private val subject = defaultConfiguration.copy(defaultValue = of(emptyList())) - @Test - fun `identifies default as not a non empty list`() { - assertThat(subject.isDefaultValueNonEmptyList()).isFalse() - } + @Test + fun `identifies default as not a non empty list`() { + assertThat(subject.isDefaultValueNonEmptyList()).isFalse() + } - @Test - fun `fails when attempting conversion`() { - assertThatIllegalStateException().isThrownBy { subject.getDefaultValueAsList() } - } + @Test + fun `fails when attempting conversion`() { + assertThatIllegalStateException().isThrownBy { subject.getDefaultValueAsList() } } + } - @Nested - inner class `bracket list default value` { - private val subject = defaultConfiguration.copy(defaultValue = of(listOf("a", "b"))) + @Nested + inner class `bracket list default value` { + private val subject = defaultConfiguration.copy(defaultValue = of(listOf("a", "b"))) - @Test - fun `identifies default as a non empty list`() { - assertThat(subject.isDefaultValueNonEmptyList()).isTrue() - } + @Test + fun `identifies default as a non empty list`() { + assertThat(subject.isDefaultValueNonEmptyList()).isTrue() + } - @Test - fun `converts to a list`() { - assertThat(subject.getDefaultValueAsList()).isEqualTo(listOf("a", "b")) - } + @Test + fun `converts to a list`() { + assertThat(subject.getDefaultValueAsList()).isEqualTo(listOf("a", "b")) } } } diff --git a/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/collection/MultiRuleCollectorSpec.kt b/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/collection/MultiRuleCollectorSpec.kt index 708d5af64e5..c2ddccbfdf4 100644 --- a/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/collection/MultiRuleCollectorSpec.kt +++ b/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/collection/MultiRuleCollectorSpec.kt @@ -5,7 +5,6 @@ import io.gitlab.arturbosch.detekt.generator.util.run import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatExceptionOfType import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class MultiRuleCollectorSpec { @@ -17,47 +16,43 @@ class MultiRuleCollectorSpec { subject = MultiRuleCollector() } - @Nested - inner class `a MultiRuleCollector` { + @Test + fun `collects no MultiRule when no class is extended`() { + val code = "class MyRule" + assertThat(subject.run(code)).isEmpty() + } - @Test - fun `collects no MultiRule when no class is extended`() { - val code = "class MyRule" - assertThat(subject.run(code)).isEmpty() - } + @Test + fun `collects no rules when no MultiRule class is extended`() { + val code = "class MyRule : Other" + assertThat(subject.run(code)).isEmpty() + } - @Test - fun `collects no rules when no MultiRule class is extended`() { - val code = "class MyRule : Other" - assertThat(subject.run(code)).isEmpty() + @Test + fun `throws when no rules are added`() { + val code = "class MyRule : MultiRule" + assertThatExceptionOfType(InvalidDocumentationException::class.java).isThrownBy { + subject.run(code) } + } - @Test - fun `throws when no rules are added`() { - val code = "class MyRule : MultiRule" - assertThatExceptionOfType(InvalidDocumentationException::class.java).isThrownBy { - subject.run(code) + @Test + fun `collects all rules in fields and in the rule property`() { + val code = """ + class MyRule : MultiRule { + val p1 = Rule3() + val p2 = Rule4() + + override val rules: List = listOf( + Rule1(), + Rule2(), + p1, + p2 + ) } - } - - @Test - fun `collects all rules in fields and in the rule property`() { - val code = """ - class MyRule : MultiRule { - val p1 = Rule3() - val p2 = Rule4() - - override val rules: List = listOf( - Rule1(), - Rule2(), - p1, - p2 - ) - } - """ - val items = subject.run(code) - assertThat(items[0].rules).hasSize(4) - assertThat(items[0].rules).contains("Rule1", "Rule2", "Rule3", "Rule4") - } + """ + val items = subject.run(code) + assertThat(items[0].rules).hasSize(4) + assertThat(items[0].rules).contains("Rule1", "Rule2", "Rule3", "Rule4") } } diff --git a/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/collection/RuleCollectorSpec.kt b/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/collection/RuleCollectorSpec.kt index 7786d85335c..7e200f5c35b 100644 --- a/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/collection/RuleCollectorSpec.kt +++ b/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/collection/RuleCollectorSpec.kt @@ -22,774 +22,767 @@ class RuleCollectorSpec { subject = RuleCollector() } + @Test + fun `collects no rules when no class is extended`() { + val code = "class SomeRandomClass" + val items = subject.run(code) + assertThat(items).isEmpty() + } + + @Test + fun `collects no rules when no rule class is extended`() { + val code = "class SomeRandomClass : SomeOtherClass" + val items = subject.run(code) + assertThat(items).isEmpty() + } + + @Test + fun `throws when a class extends Rule but has no valid documentation`() { + val rules = listOf("Rule", "FormattingRule", "ThresholdRule", "EmptyRule") + for (rule in rules) { + val code = "class SomeRandomClass : $rule" + assertThatExceptionOfType(InvalidDocumentationException::class.java).isThrownBy { subject.run(code) } + } + } + + @Test + fun `collects the rule name`() { + val name = "SomeRandomClass" + val code = """ + /** + * description + */ + class $name : Rule + """ + val items = subject.run(code) + assertThat(items[0].name).isEqualTo(name) + } + + @Test + fun `collects the rule description`() { + val description = "description" + val code = """ + /** + * $description + */ + class SomeRandomClass : Rule + """ + val items = subject.run(code) + assertThat(items[0].description).isEqualTo(description) + } + + @Test + fun `has a multi paragraph description`() { + val description = "description" + val code = """ + /** + * $description + * + * more... + */ + class SomeRandomClass : Rule + """ + val items = subject.run(code) + assertThat(items[0].description).startsWith(description) + assertThat(items[0].description).contains("more...") + } + + @Test + fun `is not active by default`() { + val code = """ + /** + * description + */ + class SomeRandomClass : Rule + """ + val items = subject.run(code) + assertThat(items[0].defaultActivationStatus.active).isFalse() + } + + @Test + fun `is active by default with valid version`() { + val code = """ + /** + * description + */ + @ActiveByDefault("1.12.123") + class SomeRandomClass : Rule + """ + val items = subject.run(code) + val defaultActivationStatus = items[0].defaultActivationStatus as Active + assertThat(defaultActivationStatus.since).isEqualTo("1.12.123") + } + + @Test + fun `is active by default with named since`() { + val code = """ + /** + * description + */ + @ActiveByDefault(since = "1.2.3") + class SomeRandomClass : Rule + """ + val items = subject.run(code) + val defaultActivationStatus = items[0].defaultActivationStatus as Active + assertThat(defaultActivationStatus.since).isEqualTo("1.2.3") + } + + @Test + fun `is active by default with invalid version`() { + val code = """ + /** + * description + */ + @ActiveByDefault("1.2.x") + class SomeRandomClass : Rule + """ + assertThatExceptionOfType(InvalidDocumentationException::class.java).isThrownBy { subject.run(code) } + } + + @Test + fun `is auto-correctable`() { + val code = """ + /** + * description + * + */ + @AutoCorrectable(since = "1.0.0") + class SomeRandomClass : Rule + """ + val items = subject.run(code) + assertThat(items[0].autoCorrect).isTrue() + } + + @Test + fun `collects the issue property`() { + val code = """ + /** + * description + */ + class SomeRandomClass : Rule { + override val defaultRuleIdAliases = setOf("RULE", "RULE2") + override val issue = Issue(javaClass.simpleName, Severity.Style, "", Debt.TEN_MINS) + } + """ + val items = subject.run(code) + assertThat(items[0].severity).isEqualTo("Style") + assertThat(items[0].debt).isEqualTo("10min") + assertThat(items[0].aliases).isEqualTo("RULE, RULE2") + } + @Nested - inner class `a RuleCollector` { + inner class `collects configuration options using annotation` { + @Test + fun `contains no configuration options by default`() { + val code = """ + /** + * description + */ + class SomeRandomClass : Rule + """ + val items = subject.run(code) + assertThat(items[0].configuration).isEmpty() + } @Test - fun `collects no rules when no class is extended`() { - val code = "class SomeRandomClass" + fun `contains one configuration option with correct formatting`() { + val code = """ + /** + * description + */ + class SomeRandomClass() : Rule { + @Configuration("description") + private val config: String by config("[A-Z$]") + } + """ val items = subject.run(code) - assertThat(items).isEmpty() + assertThat(items[0].configuration).hasSize(1) + val expectedConfiguration = Configuration( + name = "config", + description = "description", + defaultValue = of("[A-Z$]"), + defaultAndroidValue = null, + deprecated = null + ) + assertThat(items[0].configuration[0]).isEqualTo(expectedConfiguration) } @Test - fun `collects no rules when no rule class is extended`() { - val code = "class SomeRandomClass : SomeOtherClass" + fun `contains one configuration option of type Int`() { + val code = """ + /** + * description + */ + class SomeRandomClass() : Rule { + @Configuration("description") + private val config: Int by config(1_999_000) + } + """ val items = subject.run(code) - assertThat(items).isEmpty() + assertThat(items[0].configuration).hasSize(1) + assertThat(items[0].configuration[0].defaultValue).isEqualTo(of(1_999_000)) } @Test - fun `throws when a class extends Rule but has no valid documentation`() { - val rules = listOf("Rule", "FormattingRule", "ThresholdRule", "EmptyRule") - for (rule in rules) { - val code = "class SomeRandomClass : $rule" - assertThatExceptionOfType(InvalidDocumentationException::class.java).isThrownBy { subject.run(code) } - } + fun `extracts default value when it is a multi line string`() { + val code = """ + /** + * description + */ + class SomeRandomClass() : Rule { + @Configuration("description") + private val config: String by config(""${"\""}abcd""${"\""}) + } + """ + val items = subject.run(code) + assertThat(items[0].configuration[0].defaultValue).isEqualTo(of("abcd")) } @Test - fun `collects the rule name`() { - val name = "SomeRandomClass" + fun `extracts default value when defined with named parameter`() { val code = """ /** * description */ - class $name : Rule + class SomeRandomClass() : Rule { + @Configuration("description") + private val config: Int by config(defaultValue = 99) + } """ val items = subject.run(code) - assertThat(items[0].name).isEqualTo(name) + assertThat(items[0].configuration[0].defaultValue).isEqualTo(of(99)) } @Test - fun `collects the rule description`() { - val description = "description" + fun `extracts default value for list of strings`() { val code = """ /** - * $description + * description */ - class SomeRandomClass : Rule + class SomeRandomClass() : Rule { + @Configuration("description") + private val config: List by config( + listOf( + "a", + "b" + ) + ) + } """ val items = subject.run(code) - assertThat(items[0].description).isEqualTo(description) + val expected = of(listOf("a", "b")) + assertThat(items[0].configuration[0].defaultValue).isEqualTo(expected) } @Test - fun `has a multi paragraph description`() { - val description = "description" + fun `contains multiple configuration options`() { val code = """ /** - * $description - * - * more... + * description */ - class SomeRandomClass : Rule + class SomeRandomClass() : Rule { + @Configuration("description") + private val config: String by config("") + + @Configuration("description") + private val config2: String by config("") + } """ val items = subject.run(code) - assertThat(items[0].description).startsWith(description) - assertThat(items[0].description).contains("more...") + assertThat(items[0].configuration).hasSize(2) } @Test - fun `is not active by default`() { + fun `has description that is concatenated`() { val code = """ /** * description */ - class SomeRandomClass : Rule + class SomeRandomClass() : Rule { + @Configuration( + "This is a " + + "multi line " + + "description") + private val config: String by config("a") + } """ val items = subject.run(code) - assertThat(items[0].defaultActivationStatus.active).isFalse() + assertThat(items[0].configuration[0].description).isEqualTo("This is a multi line description") + assertThat(items[0].configuration[0].defaultValue).isEqualTo(of("a")) } @Test - fun `is active by default with valid version`() { + fun `extracts default value when it is an Int constant`() { val code = """ /** * description */ - @ActiveByDefault("1.12.123") - class SomeRandomClass : Rule + class SomeRandomClass() : Rule { + @Configuration("description") + private val config: Int by config(DEFAULT_CONFIG_VALUE) + + companion object { + private const val DEFAULT_CONFIG_VALUE = 99 + } + } """ val items = subject.run(code) - val defaultActivationStatus = items[0].defaultActivationStatus as Active - assertThat(defaultActivationStatus.since).isEqualTo("1.12.123") + assertThat(items[0].configuration[0].defaultValue).isEqualTo(of(99)) } @Test - fun `is active by default with named since`() { + fun `extracts default value when it is an Int constant as named parameter`() { val code = """ /** * description */ - @ActiveByDefault(since = "1.2.3") - class SomeRandomClass : Rule + class SomeRandomClass() : Rule { + @Configuration("description") + private val config: Int by config(defaultValue = DEFAULT_CONFIG_VALUE) + + companion object { + private const val DEFAULT_CONFIG_VALUE = 99 + } + } """ val items = subject.run(code) - val defaultActivationStatus = items[0].defaultActivationStatus as Active - assertThat(defaultActivationStatus.since).isEqualTo("1.2.3") + assertThat(items[0].configuration[0].defaultValue).isEqualTo(of(99)) } @Test - fun `is active by default with invalid version`() { + fun `extracts default value when it is a String constant`() { val code = """ /** * description */ - @ActiveByDefault("1.2.x") - class SomeRandomClass : Rule + class SomeRandomClass() : Rule { + @Configuration("description") + private val config: String by config(DEFAULT_CONFIG_VALUE) + + companion object { + private const val DEFAULT_CONFIG_VALUE = "a" + } + } """ - assertThatExceptionOfType(InvalidDocumentationException::class.java).isThrownBy { subject.run(code) } + val items = subject.run(code) + assertThat(items[0].configuration[0].defaultValue).isEqualTo(of("a")) } @Test - fun `is auto-correctable`() { + fun `extracts default value for list of strings from constant`() { val code = """ /** * description - * */ - @AutoCorrectable(since = "1.0.0") - class SomeRandomClass : Rule + class SomeRandomClass() : Rule { + @Configuration("description") + private val config1: List by config(DEFAULT_CONFIG_VALUE) + + @Configuration("description") + private val config2: List by config(listOf(DEFAULT_CONFIG_VALUE_A, "b")) + + companion object { + private val DEFAULT_CONFIG_VALUE = listOf("a", "b") + private val DEFAULT_CONFIG_VALUE_A = "a" + } + } """ val items = subject.run(code) - assertThat(items[0].autoCorrect).isTrue() + val expected = of(listOf("a", "b")) + assertThat(items[0].configuration[0].defaultValue).isEqualTo(expected) + assertThat(items[0].configuration[1].defaultValue).isEqualTo(expected) } @Test - fun `collects the issue property`() { + fun `extracts emptyList default value`() { val code = """ /** * description */ - class SomeRandomClass : Rule { - override val defaultRuleIdAliases = setOf("RULE", "RULE2") - override val issue = Issue(javaClass.simpleName, Severity.Style, "", Debt.TEN_MINS) - } + class SomeRandomClass() : Rule { + @Configuration("description") + private val config1: List by config(listOf()) + + @Configuration("description") + private val config2: List by config(emptyList()) + } """ val items = subject.run(code) - assertThat(items[0].severity).isEqualTo("Style") - assertThat(items[0].debt).isEqualTo("10min") - assertThat(items[0].aliases).isEqualTo("RULE, RULE2") + val expected = of(emptyList()) + assertThat(items[0].configuration[0].defaultValue).isEqualTo(expected) + assertThat(items[0].configuration[1].defaultValue).isEqualTo(expected) } - @Nested - inner class `collects configuration options` { - @Nested - inner class `using annotation` { - @Test - fun `contains no configuration options by default`() { - val code = """ - /** - * description - */ - class SomeRandomClass : Rule - """ - val items = subject.run(code) - assertThat(items[0].configuration).isEmpty() - } - - @Test - fun `contains one configuration option with correct formatting`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - private val config: String by config("[A-Z$]") - } - """ - val items = subject.run(code) - assertThat(items[0].configuration).hasSize(1) - val expectedConfiguration = Configuration( - name = "config", - description = "description", - defaultValue = of("[A-Z$]"), - defaultAndroidValue = null, - deprecated = null - ) - assertThat(items[0].configuration[0]).isEqualTo(expectedConfiguration) - } - - @Test - fun `contains one configuration option of type Int`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - private val config: Int by config(1_999_000) - } - """ - val items = subject.run(code) - assertThat(items[0].configuration).hasSize(1) - assertThat(items[0].configuration[0].defaultValue).isEqualTo(of(1_999_000)) - } - - @Test - fun `extracts default value when it is a multi line string`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - private val config: String by config(""${"\""}abcd""${"\""}) - } - """ - val items = subject.run(code) - assertThat(items[0].configuration[0].defaultValue).isEqualTo(of("abcd")) - } - - @Test - fun `extracts default value when defined with named parameter`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - private val config: Int by config(defaultValue = 99) - } - """ - val items = subject.run(code) - assertThat(items[0].configuration[0].defaultValue).isEqualTo(of(99)) - } - - @Test - fun `extracts default value for list of strings`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - private val config: List by config( - listOf( - "a", - "b" - ) - ) - } - """ - val items = subject.run(code) - val expected = of(listOf("a", "b")) - assertThat(items[0].configuration[0].defaultValue).isEqualTo(expected) - } - - @Test - fun `contains multiple configuration options`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - private val config: String by config("") - - @Configuration("description") - private val config2: String by config("") - } - """ - val items = subject.run(code) - assertThat(items[0].configuration).hasSize(2) - } - - @Test - fun `has description that is concatenated`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration( - "This is a " + - "multi line " + - "description") - private val config: String by config("a") - } - """ - val items = subject.run(code) - assertThat(items[0].configuration[0].description).isEqualTo("This is a multi line description") - assertThat(items[0].configuration[0].defaultValue).isEqualTo(of("a")) - } - - @Test - fun `extracts default value when it is an Int constant`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - private val config: Int by config(DEFAULT_CONFIG_VALUE) - - companion object { - private const val DEFAULT_CONFIG_VALUE = 99 - } - } - """ - val items = subject.run(code) - assertThat(items[0].configuration[0].defaultValue).isEqualTo(of(99)) - } - - @Test - fun `extracts default value when it is an Int constant as named parameter`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - private val config: Int by config(defaultValue = DEFAULT_CONFIG_VALUE) - - companion object { - private const val DEFAULT_CONFIG_VALUE = 99 - } - } - """ - val items = subject.run(code) - assertThat(items[0].configuration[0].defaultValue).isEqualTo(of(99)) - } - - @Test - fun `extracts default value when it is a String constant`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - private val config: String by config(DEFAULT_CONFIG_VALUE) - - companion object { - private const val DEFAULT_CONFIG_VALUE = "a" - } - } - """ - val items = subject.run(code) - assertThat(items[0].configuration[0].defaultValue).isEqualTo(of("a")) - } - - @Test - fun `extracts default value for list of strings from constant`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - private val config1: List by config(DEFAULT_CONFIG_VALUE) - - @Configuration("description") - private val config2: List by config(listOf(DEFAULT_CONFIG_VALUE_A, "b")) - - companion object { - private val DEFAULT_CONFIG_VALUE = listOf("a", "b") - private val DEFAULT_CONFIG_VALUE_A = "a" - } - } - """ - val items = subject.run(code) - val expected = of(listOf("a", "b")) - assertThat(items[0].configuration[0].defaultValue).isEqualTo(expected) - assertThat(items[0].configuration[1].defaultValue).isEqualTo(expected) - } - - @Test - fun `extracts emptyList default value`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - private val config1: List by config(listOf()) - - @Configuration("description") - private val config2: List by config(emptyList()) - } - """ - val items = subject.run(code) - val expected = of(emptyList()) - assertThat(items[0].configuration[0].defaultValue).isEqualTo(expected) - assertThat(items[0].configuration[1].defaultValue).isEqualTo(expected) - } - - @Test - fun `extracts emptyList default value of transformed list`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - private val config1: List by config(listOf()) { it.map(String::toInt) } - - @Configuration("description") - private val config2: List by config(DEFAULT_CONFIG_VALUE) { it.map(String::toInt) } - - companion object { - private val DEFAULT_CONFIG_VALUE: List = emptyList() - } - } - """ - val items = subject.run(code) - val expected = of(emptyList()) - assertThat(items[0].configuration[0].defaultValue).isEqualTo(expected) - assertThat(items[0].configuration[1].defaultValue).isEqualTo(expected) - } - - @Test - fun `is marked as deprecated as well`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Deprecated("use config1 instead") - @Configuration("description") - private val config: String by config("") - } - """ - val items = subject.run(code) - assertThat(items[0].configuration[0].deprecated).isEqualTo("use config1 instead") - } - - @Test - fun `fails if kdoc is used to define configuration`() { - val code = """ - /** - * description - * @configuration config1 - description (default: `''`) - */ - class SomeRandomClass() : Rule { - } - """ - assertThatExceptionOfType(InvalidDocumentationException::class.java).isThrownBy { subject.run(code) } - } - - @Test - fun `fails if not used in combination with delegate`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - private val config: String = "foo" - } - """ - assertThatExceptionOfType(InvalidDocumentationException::class.java).isThrownBy { subject.run(code) } - } - - @Test - fun `fails if not used in combination with config delegate`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - private val config: String by lazy { "foo" } - } - """ - assertThatExceptionOfType(InvalidDocumentationException::class.java).isThrownBy { subject.run(code) } - } - - @Test - fun `fails if config delegate is used without annotation`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - private val config: String by config("") - } - """ - assertThatExceptionOfType(InvalidDocumentationException::class.java).isThrownBy { subject.run(code) } - } - - @Nested - inner class `android variants` { - @Test - fun `extracts values with android variants`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - private val maxLineLength: Int by configWithAndroidVariants(120, 100) - } - """ - val items = subject.run(code) - assertThat(items[0].configuration[0]).isEqualTo( - Configuration( - name = "maxLineLength", - description = "description", - defaultValue = of(120), - defaultAndroidValue = of(100), - deprecated = null - ) - ) - } + @Test + fun `extracts emptyList default value of transformed list`() { + val code = """ + /** + * description + */ + class SomeRandomClass() : Rule { + @Configuration("description") + private val config1: List by config(listOf()) { it.map(String::toInt) } - @Test - fun `extracts values with android variants as named arguments`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - private val maxLineLength: Int by - configWithAndroidVariants(defaultValue = 120, defaultAndroidValue = 100) - } - """ - val items = subject.run(code) - assertThat(items[0].configuration[0]).isEqualTo( - Configuration( - name = "maxLineLength", - description = "description", - defaultValue = of(120), - defaultAndroidValue = of(100), - deprecated = null - ) - ) - } - } - - @Nested - inner class `fallback property` { - @Test - fun `extracts default value`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - val prop: Int by config(1) - @Configuration("description") - private val config1: Int by configWithFallback(this::prop, 99) - @Configuration("description") - private val config2: Int by configWithFallback(fallbackProperty = ::prop, defaultValue = 99) - @Configuration("description") - private val config3: Int by configWithFallback(defaultValue = 99, fallbackProperty = ::prop) - } - """ - val items = subject.run(code) - val fallbackProperties = items[0].configuration.filter { it.name.startsWith("config") } - assertThat(fallbackProperties).hasSize(3) - assertThat(fallbackProperties.map { it.defaultValue }).containsOnly(of(99)) - } + @Configuration("description") + private val config2: List by config(DEFAULT_CONFIG_VALUE) { it.map(String::toInt) } - @Test - fun `reports an error if the property to fallback on exists but is not a config property`() { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - val prop: Int = 1 - @Configuration("description") - private val config: Int by configWithFallback(::prop, 99) - } - """ - assertThatThrownBy { subject.run(code) } - .isInstanceOf(InvalidDocumentationException::class.java) - .hasMessageContaining("delegate") - } - } - - @Nested - inner class `transformed property` { - val code = """ - /** - * description - */ - class SomeRandomClass() : Rule { - @Configuration("description") - private val config1: Regex by config("[a-z]+") { it.toRegex() } - @Configuration("description") - private val config2: String by config(false, Boolean::toString) - } - """ - - @Test - fun `extracts default value with transformer function`() { - val items = subject.run(code) - assertThat(items[0].configuration[0].defaultValue).isEqualTo(of("[a-z]+")) + companion object { + private val DEFAULT_CONFIG_VALUE: List = emptyList() } + } + """ + val items = subject.run(code) + val expected = of(emptyList()) + assertThat(items[0].configuration[0].defaultValue).isEqualTo(expected) + assertThat(items[0].configuration[1].defaultValue).isEqualTo(expected) + } - @Test - fun `extracts default value with method reference`() { - val items = subject.run(code) - assertThat(items[0].configuration[1].defaultValue).isEqualTo(of(false)) - } - } - } + @Test + fun `is marked as deprecated as well`() { + val code = """ + /** + * description + */ + class SomeRandomClass() : Rule { + @Deprecated("use config1 instead") + @Configuration("description") + private val config: String by config("") + } + """ + val items = subject.run(code) + assertThat(items[0].configuration[0].deprecated).isEqualTo("use config1 instead") + } + + @Test + fun `fails if kdoc is used to define configuration`() { + val code = """ + /** + * description + * @configuration config1 - description (default: `''`) + */ + class SomeRandomClass() : Rule { + } + """ + assertThatExceptionOfType(InvalidDocumentationException::class.java).isThrownBy { subject.run(code) } + } + + @Test + fun `fails if not used in combination with delegate`() { + val code = """ + /** + * description + */ + class SomeRandomClass() : Rule { + @Configuration("description") + private val config: String = "foo" + } + """ + assertThatExceptionOfType(InvalidDocumentationException::class.java).isThrownBy { subject.run(code) } + } + + @Test + fun `fails if not used in combination with config delegate`() { + val code = """ + /** + * description + */ + class SomeRandomClass() : Rule { + @Configuration("description") + private val config: String by lazy { "foo" } + } + """ + assertThatExceptionOfType(InvalidDocumentationException::class.java).isThrownBy { subject.run(code) } + } + + @Test + fun `fails if config delegate is used without annotation`() { + val code = """ + /** + * description + */ + class SomeRandomClass() : Rule { + private val config: String by config("") + } + """ + assertThatExceptionOfType(InvalidDocumentationException::class.java).isThrownBy { subject.run(code) } } @Nested - inner class `collects type resolution information` { + inner class `android variants` { @Test - fun `has no type resolution by default`() { + fun `extracts values with android variants`() { val code = """ /** * description */ - class SomeRandomClass : Rule + class SomeRandomClass() : Rule { + @Configuration("description") + private val maxLineLength: Int by configWithAndroidVariants(120, 100) + } """ val items = subject.run(code) - assertThat(items[0].requiresTypeResolution).isFalse() + assertThat(items[0].configuration[0]).isEqualTo( + Configuration( + name = "maxLineLength", + description = "description", + defaultValue = of(120), + defaultAndroidValue = of(100), + deprecated = null + ) + ) } @Test - fun `collects the flag that it requires type resolution`() { + fun `extracts values with android variants as named arguments`() { val code = """ /** * description */ - @RequiresTypeResolution - class SomeRandomClass : Rule + class SomeRandomClass() : Rule { + @Configuration("description") + private val maxLineLength: Int by + configWithAndroidVariants(defaultValue = 120, defaultAndroidValue = 100) + } """ val items = subject.run(code) - assertThat(items[0].requiresTypeResolution).isTrue() + assertThat(items[0].configuration[0]).isEqualTo( + Configuration( + name = "maxLineLength", + description = "description", + defaultValue = of(120), + defaultAndroidValue = of(100), + deprecated = null + ) + ) } + } + @Nested + inner class `fallback property` { @Test - fun `collects the flag that it requires type resolution from fully qualified annotation`() { + fun `extracts default value`() { val code = """ - /** - * description - */ - @io.gitlab.arturbosch.detekt.api.internal.RequiresTypeResolution - class SomeRandomClass : Rule + /** + * description + */ + class SomeRandomClass() : Rule { + @Configuration("description") + val prop: Int by config(1) + @Configuration("description") + private val config1: Int by configWithFallback(this::prop, 99) + @Configuration("description") + private val config2: Int by configWithFallback(fallbackProperty = ::prop, defaultValue = 99) + @Configuration("description") + private val config3: Int by configWithFallback(defaultValue = 99, fallbackProperty = ::prop) + } """ val items = subject.run(code) - assertThat(items[0].requiresTypeResolution).isTrue() + val fallbackProperties = items[0].configuration.filter { it.name.startsWith("config") } + assertThat(fallbackProperties).hasSize(3) + assertThat(fallbackProperties.map { it.defaultValue }).containsOnly(of(99)) } - } - @Test - fun `contains compliant and noncompliant code examples`() { - val code = """ + @Test + fun `reports an error if the property to fallback on exists but is not a config property`() { + val code = """ /** * description - * - * - * val one = 2 - * - * - * - * val one = 1 - * */ - class RandomClass : Rule - """ - val items = subject.run(code) - assertThat(items[0].nonCompliantCodeExample).isEqualTo("val one = 2") - assertThat(items[0].compliantCodeExample).isEqualTo("val one = 1") + class SomeRandomClass() : Rule { + val prop: Int = 1 + @Configuration("description") + private val config: Int by configWithFallback(::prop, 99) + } + """ + assertThatThrownBy { subject.run(code) } + .isInstanceOf(InvalidDocumentationException::class.java) + .hasMessageContaining("delegate") + } } - @Test - fun `has wrong noncompliant code example declaration`() { + @Nested + inner class `transformed property` { val code = """ /** * description - * - * */ - class RandomClass : Rule + class SomeRandomClass() : Rule { + @Configuration("description") + private val config1: Regex by config("[a-z]+") { it.toRegex() } + @Configuration("description") + private val config2: String by config(false, Boolean::toString) + } """ - assertThatExceptionOfType(InvalidCodeExampleDocumentationException::class.java) - .isThrownBy { subject.run(code) } - } - @Test - fun `has wrong compliant code example declaration`() { - val code = """ - /** - * description - * - * - * val one = 2 - * - * - */ - class RandomClass : Rule - """ - assertThatExceptionOfType(InvalidCodeExampleDocumentationException::class.java) - .isThrownBy { subject.run(code) } - } + @Test + fun `extracts default value with transformer function`() { + val items = subject.run(code) + assertThat(items[0].configuration[0].defaultValue).isEqualTo(of("[a-z]+")) + } - @Test - fun `has wrong compliant without noncompliant code example declaration`() { - val code = """ - /** - * description - * - * - * val one = 1 - * - */ - class RandomClass : Rule - """ - assertThatExceptionOfType(InvalidCodeExampleDocumentationException::class.java) - .isThrownBy { subject.run(code) } + @Test + fun `extracts default value with method reference`() { + val items = subject.run(code) + assertThat(items[0].configuration[1].defaultValue).isEqualTo(of(false)) + } } + } + @Nested + inner class `collects type resolution information` { @Test - fun `has wrong issue style property`() { + fun `has no type resolution by default`() { val code = """ /** * description */ - class SomeRandomClass : Rule { - - val style = Severity.Style - override val issue = Issue(javaClass.simpleName, - style, - "", - debt = Debt.TEN_MINS) - } + class SomeRandomClass : Rule """ - assertThatExceptionOfType(InvalidIssueDeclaration::class.java).isThrownBy { subject.run(code) } + val items = subject.run(code) + assertThat(items[0].requiresTypeResolution).isFalse() } @Test - fun `has wrong aliases property structure`() { + fun `collects the flag that it requires type resolution`() { val code = """ /** * description */ - class SomeRandomClass : Rule { - - val a = setOf("UNUSED_VARIABLE") - override val defaultRuleIdAliases = a - override val issue = Issue(javaClass.simpleName, - Severity.Style, - "", - debt = Debt.TEN_MINS) - } + @RequiresTypeResolution + class SomeRandomClass : Rule """ - assertThatExceptionOfType(InvalidAliasesDeclaration::class.java).isThrownBy { subject.run(code) } + val items = subject.run(code) + assertThat(items[0].requiresTypeResolution).isTrue() } @Test - fun `contains tabs in KDoc`() { - val description = "\tdescription" + fun `collects the flag that it requires type resolution from fully qualified annotation`() { val code = """ /** - * $description + * description */ + @io.gitlab.arturbosch.detekt.api.internal.RequiresTypeResolution class SomeRandomClass : Rule """ - assertThatExceptionOfType(InvalidDocumentationException::class.java).isThrownBy { subject.run(code) } + val items = subject.run(code) + assertThat(items[0].requiresTypeResolution).isTrue() } } + + @Test + fun `contains compliant and noncompliant code examples`() { + val code = """ + /** + * description + * + * + * val one = 2 + * + * + * + * val one = 1 + * + */ + class RandomClass : Rule + """ + val items = subject.run(code) + assertThat(items[0].nonCompliantCodeExample).isEqualTo("val one = 2") + assertThat(items[0].compliantCodeExample).isEqualTo("val one = 1") + } + + @Test + fun `has wrong noncompliant code example declaration`() { + val code = """ + /** + * description + * + * + */ + class RandomClass : Rule + """ + assertThatExceptionOfType(InvalidCodeExampleDocumentationException::class.java) + .isThrownBy { subject.run(code) } + } + + @Test + fun `has wrong compliant code example declaration`() { + val code = """ + /** + * description + * + * + * val one = 2 + * + * + */ + class RandomClass : Rule + """ + assertThatExceptionOfType(InvalidCodeExampleDocumentationException::class.java) + .isThrownBy { subject.run(code) } + } + + @Test + fun `has wrong compliant without noncompliant code example declaration`() { + val code = """ + /** + * description + * + * + * val one = 1 + * + */ + class RandomClass : Rule + """ + assertThatExceptionOfType(InvalidCodeExampleDocumentationException::class.java) + .isThrownBy { subject.run(code) } + } + + @Test + fun `has wrong issue style property`() { + val code = """ + /** + * description + */ + class SomeRandomClass : Rule { + + val style = Severity.Style + override val issue = Issue(javaClass.simpleName, + style, + "", + debt = Debt.TEN_MINS) + } + """ + assertThatExceptionOfType(InvalidIssueDeclaration::class.java).isThrownBy { subject.run(code) } + } + + @Test + fun `has wrong aliases property structure`() { + val code = """ + /** + * description + */ + class SomeRandomClass : Rule { + + val a = setOf("UNUSED_VARIABLE") + override val defaultRuleIdAliases = a + override val issue = Issue(javaClass.simpleName, + Severity.Style, + "", + debt = Debt.TEN_MINS) + } + """ + assertThatExceptionOfType(InvalidAliasesDeclaration::class.java).isThrownBy { subject.run(code) } + } + + @Test + fun `contains tabs in KDoc`() { + val description = "\tdescription" + val code = """ + /** + * $description + */ + class SomeRandomClass : Rule + """ + assertThatExceptionOfType(InvalidDocumentationException::class.java).isThrownBy { subject.run(code) } + } } diff --git a/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/collection/RuleSetProviderCollectorSpec.kt b/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/collection/RuleSetProviderCollectorSpec.kt index ec3f95ffb63..f5bcb587294 100644 --- a/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/collection/RuleSetProviderCollectorSpec.kt +++ b/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/collection/RuleSetProviderCollectorSpec.kt @@ -20,410 +20,407 @@ class RuleSetProviderCollectorSpec { } @Nested - inner class `RuleSetProviderCollector rule` { - @Nested - inner class `a non-RuleSetProvider class extending nothing` { - val code = """ - package foo - - class SomeRandomClass { - fun logSomething(message: String) { - println(message) - } - } - """ + inner class `a non-RuleSetProvider class extending nothing` { + val code = """ + package foo - @Test - fun `collects no rulesets`() { - val items = subject.run(code) - assertThat(items).isEmpty() + class SomeRandomClass { + fun logSomething(message: String) { + println(message) } } + """ - @Nested - inner class `a non-RuleSetProvider class extending a class that is not related to rules` { - val code = """ - package foo + @Test + fun `collects no rulesets`() { + val items = subject.run(code) + assertThat(items).isEmpty() + } + } - class SomeRandomClass: SomeOtherClass { - fun logSomething(message: String) { - println(message) - } - } - """ + @Nested + inner class `a non-RuleSetProvider class extending a class that is not related to rules` { + val code = """ + package foo - @Test - fun `collects no rulesets`() { - val items = subject.run(code) - assertThat(items).isEmpty() + class SomeRandomClass: SomeOtherClass { + fun logSomething(message: String) { + println(message) } } + """ - @Nested - inner class `a RuleSetProvider without documentation` { - val code = """ - package foo + @Test + fun `collects no rulesets`() { + val items = subject.run(code) + assertThat(items).isEmpty() + } + } - class TestProvider: RuleSetProvider { - fun logSomething(message: String) { - println(message) - } - } - """ + @Nested + inner class `a RuleSetProvider without documentation` { + val code = """ + package foo - @Test - fun `throws an exception`() { - assertThatExceptionOfType(InvalidDocumentationException::class.java) - .isThrownBy { subject.run(code) } + class TestProvider: RuleSetProvider { + fun logSomething(message: String) { + println(message) } } + """ - @Nested - inner class `a correct RuleSetProvider class extending RuleSetProvider but missing parameters` { - val code = """ - package foo + @Test + fun `throws an exception`() { + assertThatExceptionOfType(InvalidDocumentationException::class.java) + .isThrownBy { subject.run(code) } + } + } - class TestProvider: RuleSetProvider { - fun logSomething(message: String) { - println(message) - } - } - """ + @Nested + inner class `a correct RuleSetProvider class extending RuleSetProvider but missing parameters` { + val code = """ + package foo - @Test - fun `throws an exception`() { - assertThatExceptionOfType(InvalidDocumentationException::class.java) - .isThrownBy { subject.run(code) } + class TestProvider: RuleSetProvider { + fun logSomething(message: String) { + println(message) } } + """ - @Nested - inner class `a correct RuleSetProvider class with full parameters` { - val description = "This is a description" - val ruleSetId = "test" - val ruleName = "TestRule" - val code = """ - package foo - - /** - * $description - * - * - */ - @ActiveByDefault("1.0.0") - class TestProvider: RuleSetProvider { - override val ruleSetId: String = "$ruleSetId" - - override fun instance(config: Config): RuleSet { - return RuleSet(ruleSetId, listOf( - $ruleName(config) - )) - } - } - """ + @Test + fun `throws an exception`() { + assertThatExceptionOfType(InvalidDocumentationException::class.java) + .isThrownBy { subject.run(code) } + } + } - @Test - fun `collects a RuleSetProvider`() { - val items = subject.run(code) - assertThat(items).hasSize(1) + @Nested + inner class `a correct RuleSetProvider class with full parameters` { + val description = "This is a description" + val ruleSetId = "test" + val ruleName = "TestRule" + val code = """ + package foo + + /** + * $description + * + * + */ + @ActiveByDefault("1.0.0") + class TestProvider: RuleSetProvider { + override val ruleSetId: String = "$ruleSetId" + + override fun instance(config: Config): RuleSet { + return RuleSet(ruleSetId, listOf( + $ruleName(config) + )) } + } + """ - @Test - fun `has one rule`() { - val items = subject.run(code) - val provider = items[0] - assertThat(provider.rules).hasSize(1) - assertThat(provider.rules[0]).isEqualTo(ruleName) - } + @Test + fun `collects a RuleSetProvider`() { + val items = subject.run(code) + assertThat(items).hasSize(1) + } - @Test - fun `has correct name`() { - val items = subject.run(code) - val provider = items[0] - assertThat(provider.name).isEqualTo(ruleSetId) - } + @Test + fun `has one rule`() { + val items = subject.run(code) + val provider = items[0] + assertThat(provider.rules).hasSize(1) + assertThat(provider.rules[0]).isEqualTo(ruleName) + } - @Test - fun `has correct description`() { - val items = subject.run(code) - val provider = items[0] - assertThat(provider.description).isEqualTo(description) - } + @Test + fun `has correct name`() { + val items = subject.run(code) + val provider = items[0] + assertThat(provider.name).isEqualTo(ruleSetId) + } - @Test - fun `is active`() { - val items = subject.run(code) - val provider = items[0] - assertThat(provider.defaultActivationStatus.active).isTrue() - } + @Test + fun `has correct description`() { + val items = subject.run(code) + val provider = items[0] + assertThat(provider.description).isEqualTo(description) } - @Nested - inner class `an inactive RuleSetProvider` { - val description = "This is a description" - val ruleSetId = "test" - val ruleName = "TestRule" - val code = """ - package foo - - /** - * $description - */ - class TestProvider: RuleSetProvider { - override val ruleSetId: String = "$ruleSetId" - - override fun instance(config: Config): RuleSet { - return RuleSet(ruleSetId, listOf( - $ruleName(config) - )) - } - } - """ + @Test + fun `is active`() { + val items = subject.run(code) + val provider = items[0] + assertThat(provider.defaultActivationStatus.active).isTrue() + } + } - @Test - fun `is not active`() { - val items = subject.run(code) - val provider = items[0] - assertThat(provider.defaultActivationStatus.active).isFalse() + @Nested + inner class `an inactive RuleSetProvider` { + val description = "This is a description" + val ruleSetId = "test" + val ruleName = "TestRule" + val code = """ + package foo + + /** + * $description + */ + class TestProvider: RuleSetProvider { + override val ruleSetId: String = "$ruleSetId" + + override fun instance(config: Config): RuleSet { + return RuleSet(ruleSetId, listOf( + $ruleName(config) + )) } } + """ - @Nested - inner class `a RuleSetProvider with missing name` { - val description = "This is a description" - val ruleName = "TestRule" - val code = """ - package foo - - /** - * $description - */ - class TestProvider: RuleSetProvider { - override fun instance(config: Config): RuleSet { - return RuleSet(ruleSetId, listOf( - $ruleName(config) - )) - } - } - """ + @Test + fun `is not active`() { + val items = subject.run(code) + val provider = items[0] + assertThat(provider.defaultActivationStatus.active).isFalse() + } + } - @Test - fun `throws an exception`() { - assertThatExceptionOfType(InvalidDocumentationException::class.java) - .isThrownBy { subject.run(code) } + @Nested + inner class `a RuleSetProvider with missing name` { + val description = "This is a description" + val ruleName = "TestRule" + val code = """ + package foo + + /** + * $description + */ + class TestProvider: RuleSetProvider { + override fun instance(config: Config): RuleSet { + return RuleSet(ruleSetId, listOf( + $ruleName(config) + )) } } + """ - @Nested - inner class `a RuleSetProvider with missing description` { - val ruleSetId = "test" - val ruleName = "TestRule" - val code = """ - package foo + @Test + fun `throws an exception`() { + assertThatExceptionOfType(InvalidDocumentationException::class.java) + .isThrownBy { subject.run(code) } + } + } - class TestProvider: RuleSetProvider { - override val ruleSetId: String = "$ruleSetId" + @Nested + inner class `a RuleSetProvider with missing description` { + val ruleSetId = "test" + val ruleName = "TestRule" + val code = """ + package foo - override fun instance(config: Config): RuleSet { - return RuleSet(ruleSetId, listOf( - $ruleName(config) - )) - } - } - """ + class TestProvider: RuleSetProvider { + override val ruleSetId: String = "$ruleSetId" - @Test - fun `throws an exception`() { - assertThatExceptionOfType(InvalidDocumentationException::class.java) - .isThrownBy { subject.run(code) } + override fun instance(config: Config): RuleSet { + return RuleSet(ruleSetId, listOf( + $ruleName(config) + )) } } + """ - @Nested - inner class `a RuleSetProvider with invalid activation version` { - val code = """ - package foo - - /** - * description - */ - @ActiveByDefault(since = "1.2.xyz") - class TestProvider: RuleSetProvider { - override val ruleSetId: String = "ruleSetId" + @Test + fun `throws an exception`() { + assertThatExceptionOfType(InvalidDocumentationException::class.java) + .isThrownBy { subject.run(code) } + } + } - override fun instance(config: Config): RuleSet { - return RuleSet(ruleSetId, listOf( - TestRule(config) - )) - } + @Nested + inner class `a RuleSetProvider with invalid activation version` { + val code = """ + package foo + + /** + * description + */ + @ActiveByDefault(since = "1.2.xyz") + class TestProvider: RuleSetProvider { + override val ruleSetId: String = "ruleSetId" + + override fun instance(config: Config): RuleSet { + return RuleSet(ruleSetId, listOf( + TestRule(config) + )) } - """ + } + """ - @Test - fun `throws an exception`() { - assertThatExceptionOfType(InvalidDocumentationException::class.java) - .isThrownBy { subject.run(code) } - } + @Test + fun `throws an exception`() { + assertThatExceptionOfType(InvalidDocumentationException::class.java) + .isThrownBy { subject.run(code) } } + } - @Nested - inner class `a RuleSetProvider with no rules` { - val ruleSetId = "test" - val code = """ - package foo + @Nested + inner class `a RuleSetProvider with no rules` { + val ruleSetId = "test" + val code = """ + package foo - class TestProvider: RuleSetProvider { - override val ruleSetId: String = "$ruleSetId" + class TestProvider: RuleSetProvider { + override val ruleSetId: String = "$ruleSetId" - override fun instance(config: Config): RuleSet { - return RuleSet(ruleSetId, emptyListOf()) - } + override fun instance(config: Config): RuleSet { + return RuleSet(ruleSetId, emptyListOf()) } - """ + } + """ - @Test - fun `throws an exception`() { - assertThatExceptionOfType(InvalidDocumentationException::class.java) - .isThrownBy { subject.run(code) } - } + @Test + fun `throws an exception`() { + assertThatExceptionOfType(InvalidDocumentationException::class.java) + .isThrownBy { subject.run(code) } } + } - @Nested - inner class `a correct RuleSetProvider class with full parameters and multiple rules` { - val description = "This is a description" - val ruleSetId = "test" - val ruleName = "TestRule" - val secondRuleName = "SecondRule" - val code = """ - package foo - - /** - * $description - */ - @ActiveByDefault("1.0.0") - class TestProvider: RuleSetProvider { - override val ruleSetId: String = "$ruleSetId" - - override fun instance(config: Config): RuleSet { - return RuleSet(ruleSetId, listOf( - $ruleName(config), - $secondRuleName(config) - )) - } + @Nested + inner class `a correct RuleSetProvider class with full parameters and multiple rules` { + val description = "This is a description" + val ruleSetId = "test" + val ruleName = "TestRule" + val secondRuleName = "SecondRule" + val code = """ + package foo + + /** + * $description + */ + @ActiveByDefault("1.0.0") + class TestProvider: RuleSetProvider { + override val ruleSetId: String = "$ruleSetId" + + override fun instance(config: Config): RuleSet { + return RuleSet(ruleSetId, listOf( + $ruleName(config), + $secondRuleName(config) + )) } - """ + } + """ - @Test - fun `collects multiple rules`() { - val items = subject.run(code) - assertThat(items[0].rules).containsExactly(ruleName, secondRuleName) - } + @Test + fun `collects multiple rules`() { + val items = subject.run(code) + assertThat(items[0].rules).containsExactly(ruleName, secondRuleName) } + } - @Nested - inner class `a RuleSetProvider with configurations in kdoc` { - val code = """ - package foo + @Nested + inner class `a RuleSetProvider with configurations in kdoc` { + val code = """ + package foo + + /** + * description + * @configuration android - if android style guides should be preferred (default: `false`) + */ + class TestProvider: RuleSetProvider { + """.trimIndent() + + @Test + fun `throws exception for configuration in kdoc`() { + assertThatExceptionOfType(InvalidDocumentationException::class.java) + .isThrownBy { subject.run(code) } + } + } - /** - * description - * @configuration android - if android style guides should be preferred (default: `false`) - */ - class TestProvider: RuleSetProvider { - """.trimIndent() + @Nested + inner class `a RuleSetProvider with configurations` { + val code = """ + package foo - @Test - fun `throws exception for configuration in kdoc`() { - assertThatExceptionOfType(InvalidDocumentationException::class.java) - .isThrownBy { subject.run(code) } - } - } + /** + * description + */ + class TestProvider: RuleSetProvider { + override val ruleSetId: String = "ruleSetId" - @Nested - inner class `a RuleSetProvider with configurations` { - val code = """ - package foo - - /** - * description - */ - class TestProvider: RuleSetProvider { - override val ruleSetId: String = "ruleSetId" - - override fun instance(config: Config): RuleSet { - return RuleSet(ruleSetId, listOf(RruleName(config))) - } - - companion object { - @Configuration("bool description") - val aBool by ruleSetConfig(true) - - @Configuration("int description") - val anInt by ruleSetConfig(99) - - @Deprecated("use something else") - @Configuration("string description") - val aString by ruleSetConfig("a") - } - } - """ - private val items = subject.run(code) - - @Test - fun `extracts boolean configuration option`() { - val conf = items[0].configuration[0] - assertThat(conf.name).isEqualTo("aBool") - assertThat(conf.description).isEqualTo("bool description") - assertThat(conf.defaultValue).isEqualTo(of(true)) - assertThat(conf.deprecated).isNull() + override fun instance(config: Config): RuleSet { + return RuleSet(ruleSetId, listOf(RruleName(config))) } - @Test - fun `extracts int configuration option`() { - val conf = items[0].configuration[1] - assertThat(conf.name).isEqualTo("anInt") - assertThat(conf.description).isEqualTo("int description") - assertThat(conf.defaultValue).isEqualTo(of(99)) - } + companion object { + @Configuration("bool description") + val aBool by ruleSetConfig(true) - @Test - fun `extracts string configuration option`() { - val conf = items[0].configuration[2] - assertThat(conf.name).isEqualTo("aString") - assertThat(conf.description).isEqualTo("string description") - assertThat(conf.defaultValue).isEqualTo(of("a")) - assertThat(conf.deprecated).isEqualTo("use something else") + @Configuration("int description") + val anInt by ruleSetConfig(99) + + @Deprecated("use something else") + @Configuration("string description") + val aString by ruleSetConfig("a") } } + """ + private val items = subject.run(code) + + @Test + fun `extracts boolean configuration option`() { + val conf = items[0].configuration[0] + assertThat(conf.name).isEqualTo("aBool") + assertThat(conf.description).isEqualTo("bool description") + assertThat(conf.defaultValue).isEqualTo(of(true)) + assertThat(conf.deprecated).isNull() + } + + @Test + fun `extracts int configuration option`() { + val conf = items[0].configuration[1] + assertThat(conf.name).isEqualTo("anInt") + assertThat(conf.description).isEqualTo("int description") + assertThat(conf.defaultValue).isEqualTo(of(99)) + } - @Nested - inner class `a RuleSetProvider with unsupported configuration format` { - val code = """ - package foo + @Test + fun `extracts string configuration option`() { + val conf = items[0].configuration[2] + assertThat(conf.name).isEqualTo("aString") + assertThat(conf.description).isEqualTo("string description") + assertThat(conf.defaultValue).isEqualTo(of("a")) + assertThat(conf.deprecated).isEqualTo("use something else") + } + } - /** - * description - */ - class TestProvider: RuleSetProvider { - override val ruleSetId: String = "ruleSetId" + @Nested + inner class `a RuleSetProvider with unsupported configuration format` { + val code = """ + package foo - override fun instance(config: Config): RuleSet { - return RuleSet(ruleSetId, listOf(RruleName(config))) - } + /** + * description + */ + class TestProvider: RuleSetProvider { + override val ruleSetId: String = "ruleSetId" - companion object { - @Configuration("a description") - val aConfig by ruleSetConfig(listOf("a")) - } + override fun instance(config: Config): RuleSet { + return RuleSet(ruleSetId, listOf(RruleName(config))) } - """ - @Test - fun `fails`() { - assertThatThrownBy { subject.run(code) } - .isInstanceOf(InvalidDocumentationException::class.java) - .hasMessageContaining("""Unsupported default value format 'listOf("a")'""") + companion object { + @Configuration("a description") + val aConfig by ruleSetConfig(listOf("a")) } } + """ + + @Test + fun `fails`() { + assertThatThrownBy { subject.run(code) } + .isInstanceOf(InvalidDocumentationException::class.java) + .hasMessageContaining("""Unsupported default value format 'listOf("a")'""") + } } } diff --git a/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/printer/CliOptionsPrinterSpec.kt b/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/printer/CliOptionsPrinterSpec.kt index 64fd9f6215e..08713af6c26 100644 --- a/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/printer/CliOptionsPrinterSpec.kt +++ b/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/printer/CliOptionsPrinterSpec.kt @@ -2,22 +2,17 @@ package io.gitlab.arturbosch.detekt.generator.printer import io.github.detekt.test.utils.createTempFileForTest import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class CliOptionsPrinterSpec { - @Nested - inner class `Cli Options Printer` { + @Test + fun `prints the correct cli-options_md`() { + val cliOptionsFile = createTempFileForTest("cli-options", ".md") + CliOptionsPrinter().print(cliOptionsFile.toAbsolutePath()) + val markdownString = cliOptionsFile.toFile().readText() - @Test - fun `prints the correct cli-options_md`() { - val cliOptionsFile = createTempFileForTest("cli-options", ".md") - CliOptionsPrinter().print(cliOptionsFile.toAbsolutePath()) - val markdownString = cliOptionsFile.toFile().readText() - - assertThat(markdownString).contains("Usage: detekt [options]") - assertThat(markdownString).contains("--input, -i") - } + assertThat(markdownString).contains("Usage: detekt [options]") + assertThat(markdownString).contains("--input, -i") } } diff --git a/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/printer/DeprecatedPrinterSpec.kt b/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/printer/DeprecatedPrinterSpec.kt index 1b42fe62dc3..44b5d3cbef6 100644 --- a/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/printer/DeprecatedPrinterSpec.kt +++ b/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/printer/DeprecatedPrinterSpec.kt @@ -2,22 +2,18 @@ package io.gitlab.arturbosch.detekt.generator.printer import io.gitlab.arturbosch.detekt.generator.util.createRuleSetPage import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class DeprecatedPrinterSpec { - @Nested - inner class `Deprecated page printer` { - @Test - fun `prints the correct properties`() { - val markdownString = DeprecatedPrinter.print(listOf(createRuleSetPage())) - val expectedMarkdownString = """ - style>WildcardImport>conf2=use conf1 instead - style>WildcardImport>conf4=use conf3 instead - - """.trimIndent() - assertThat(markdownString).isEqualTo(expectedMarkdownString) - } + @Test + fun `prints the correct properties`() { + val markdownString = DeprecatedPrinter.print(listOf(createRuleSetPage())) + val expectedMarkdownString = """ + style>WildcardImport>conf2=use conf1 instead + style>WildcardImport>conf4=use conf3 instead + + """.trimIndent() + assertThat(markdownString).isEqualTo(expectedMarkdownString) } } diff --git a/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/printer/defaultconfig/ConfigPrinterSpec.kt b/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/printer/defaultconfig/ConfigPrinterSpec.kt index 324d7b6c77b..0bc758c4ee9 100644 --- a/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/printer/defaultconfig/ConfigPrinterSpec.kt +++ b/detekt-generator/src/test/kotlin/io/gitlab/arturbosch/detekt/generator/printer/defaultconfig/ConfigPrinterSpec.kt @@ -3,54 +3,50 @@ package io.gitlab.arturbosch.detekt.generator.printer.defaultconfig import io.github.detekt.test.utils.readResourceContent import io.gitlab.arturbosch.detekt.generator.util.createRuleSetPage import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ConfigPrinterSpec { - @Nested - inner class `Config printer` { - val ruleSetPage = createRuleSetPage() - val yamlString = ConfigPrinter.print(listOf(ruleSetPage)) - - @Test - fun `prints the rule set in the correct yaml format`() { - val expectedRulePart = readResourceContent("RuleSetConfig.yml") - - assertThat(yamlString).contains(expectedRulePart) - } - - @Test - fun `prints default build configuration`() { - assertThat(yamlString).contains("build:") - } - - @Test - fun `prints default config configuration`() { - assertThat(yamlString).contains("config:") - } - - @Test - fun `prints default processor configuration`() { - assertThat(yamlString).contains("processors:") - } - - @Test - fun `prints default report configuration`() { - assertThat(yamlString).contains("output-reports:") - assertThat(yamlString).contains("console-reports:") - } - - @Test - fun `omits deprecated ruleset properties`() { - assertThat(yamlString).doesNotContain("deprecatedSimpleConfig") - assertThat(yamlString).doesNotContain("deprecatedListConfig") - } - - @Test - fun `omits deprecated rule properties`() { - assertThat(yamlString).doesNotContain("conf2") - assertThat(yamlString).doesNotContain("conf4") - } + private val ruleSetPage = createRuleSetPage() + private val yamlString = ConfigPrinter.print(listOf(ruleSetPage)) + + @Test + fun `prints the rule set in the correct yaml format`() { + val expectedRulePart = readResourceContent("RuleSetConfig.yml") + + assertThat(yamlString).contains(expectedRulePart) + } + + @Test + fun `prints default build configuration`() { + assertThat(yamlString).contains("build:") + } + + @Test + fun `prints default config configuration`() { + assertThat(yamlString).contains("config:") + } + + @Test + fun `prints default processor configuration`() { + assertThat(yamlString).contains("processors:") + } + + @Test + fun `prints default report configuration`() { + assertThat(yamlString).contains("output-reports:") + assertThat(yamlString).contains("console-reports:") + } + + @Test + fun `omits deprecated ruleset properties`() { + assertThat(yamlString).doesNotContain("deprecatedSimpleConfig") + assertThat(yamlString).doesNotContain("deprecatedListConfig") + } + + @Test + fun `omits deprecated rule properties`() { + assertThat(yamlString).doesNotContain("conf2") + assertThat(yamlString).doesNotContain("conf4") } } diff --git a/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/DetektAndroidSpec.kt b/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/DetektAndroidSpec.kt index 54e32f757d1..d46637ff373 100644 --- a/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/DetektAndroidSpec.kt +++ b/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/DetektAndroidSpec.kt @@ -10,417 +10,414 @@ import org.junit.jupiter.api.condition.EnabledForJreRange import org.junit.jupiter.api.condition.EnabledIf import org.junit.jupiter.api.condition.JRE +@EnabledForJreRange(min = JRE.JAVA_11, disabledReason = "Android Gradle Plugin 7.0+ requires JDK 11 or newer") +@EnabledIf("io.gitlab.arturbosch.detekt.DetektAndroidSpecKt#isAndroidSdkInstalled") class DetektAndroidSpec { + @Nested - @EnabledForJreRange(min = JRE.JAVA_11, disabledReason = "Android Gradle Plugin 7.0+ requires JDK 11 or newer") - @EnabledIf("io.gitlab.arturbosch.detekt.DetektAndroidSpecKt#isAndroidSdkInstalled") - inner class `When applying detekt in an Android project` { - - @Nested - inner class `configures android tasks for android application` { - val projectLayout = ProjectLayout( - numberOfSourceFilesInRootPerSourceDir = 0, - ).apply { - addSubmodule( - name = "app", - numberOfSourceFilesPerSourceDir = 1, - numberOfCodeSmells = 1, - buildFileContent = """ - $APP_PLUGIN_BLOCK - $ANDROID_BLOCK - $DETEKT_REPORTS_BLOCK - """.trimIndent(), - srcDirs = listOf( - "src/main/java", - "src/debug/java", - "src/test/java", - "src/androidTest/java", - "src/main/kotlin", - "src/debug/kotlin", - "src/test/kotlin", - "src/androidTest/kotlin", - ), - baselineFiles = listOf( - "detekt-baseline.xml", - "detekt-baseline-release.xml", - "detekt-baseline-debug.xml", - "detekt-baseline-releaseUnitTest.xml", - "detekt-baseline-debugUnitTest.xml", - "detekt-baseline-debugAndroidTest.xml" - ) + inner class `configures android tasks for android application` { + val projectLayout = ProjectLayout( + numberOfSourceFilesInRootPerSourceDir = 0, + ).apply { + addSubmodule( + name = "app", + numberOfSourceFilesPerSourceDir = 1, + numberOfCodeSmells = 1, + buildFileContent = """ + $APP_PLUGIN_BLOCK + $ANDROID_BLOCK + $DETEKT_REPORTS_BLOCK + """.trimIndent(), + srcDirs = listOf( + "src/main/java", + "src/debug/java", + "src/test/java", + "src/androidTest/java", + "src/main/kotlin", + "src/debug/kotlin", + "src/test/kotlin", + "src/androidTest/kotlin", + ), + baselineFiles = listOf( + "detekt-baseline.xml", + "detekt-baseline-release.xml", + "detekt-baseline-debug.xml", + "detekt-baseline-releaseUnitTest.xml", + "detekt-baseline-debugUnitTest.xml", + "detekt-baseline-debugAndroidTest.xml" ) - } - val gradleRunner = createGradleRunnerAndSetupProject(projectLayout).also { - it.writeProjectFile("app/src/main/AndroidManifest.xml", manifestContent()) - } - - @Test - @DisplayName("task :app:detektMain") - fun appDetektMain() { - gradleRunner.runTasksAndCheckResult(":app:detektMain") { buildResult -> - assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-release.xml """) - assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-debug.xml """) - assertThat(buildResult.output).containsPattern("""--input \S*[/\\]app[/\\]src[/\\]main[/\\]java""") - assertThat(buildResult.output).containsPattern("""--input \S*[/\\]app[/\\]src[/\\]debug[/\\]java""") - assertThat(buildResult.output).containsPattern("""--input \S*[/\\]app[/\\]src[/\\]main[/\\]kotlin""") - assertThat(buildResult.output).containsPattern("""--input \S*[/\\]app[/\\]src[/\\]debug[/\\]kotlin""") - assertThat(buildResult.output).contains("--report xml:") - assertThat(buildResult.output).contains("--report sarif:") - assertThat(buildResult.output).doesNotContain("--report txt:") - assertThat(buildResult.tasks.map { it.path }).containsAll( - listOf( - ":app:detektMain", - ":app:detektDebug" - ) - ) - } - } + ) + } + val gradleRunner = createGradleRunnerAndSetupProject(projectLayout).also { + it.writeProjectFile("app/src/main/AndroidManifest.xml", manifestContent()) + } - @Test - @DisplayName("task :app:detektTest") - fun appDetektTest() { - gradleRunner.runTasksAndCheckResult(":app:detektTest") { buildResult -> - assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-releaseUnitTest.xml """) - assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-debugUnitTest.xml """) - assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-debugAndroidTest.xml """) - assertThat(buildResult.output).containsPattern("""--input \S*[/\\]app[/\\]src[/\\]test[/\\]java""") - assertThat(buildResult.output).containsPattern("""--input \S*[/\\]app[/\\]src[/\\]androidTest[/\\]java""") - assertThat(buildResult.output).containsPattern("""--input \S*[/\\]app[/\\]src[/\\]test[/\\]kotlin""") - assertThat(buildResult.output).containsPattern("""--input \S*[/\\]app[/\\]src[/\\]androidTest[/\\]kotlin""") - assertThat(buildResult.output).contains("--report xml:") - assertThat(buildResult.output).contains("--report sarif:") - assertThat(buildResult.output).doesNotContain("--report txt:") - assertThat(buildResult.tasks.map { it.path }).containsAll( - listOf( - ":app:detektDebugUnitTest", - ":app:detektDebugAndroidTest" - ) + @Test + @DisplayName("task :app:detektMain") + fun appDetektMain() { + gradleRunner.runTasksAndCheckResult(":app:detektMain") { buildResult -> + assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-release.xml """) + assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-debug.xml """) + assertThat(buildResult.output).containsPattern("""--input \S*[/\\]app[/\\]src[/\\]main[/\\]java""") + assertThat(buildResult.output).containsPattern("""--input \S*[/\\]app[/\\]src[/\\]debug[/\\]java""") + assertThat(buildResult.output).containsPattern("""--input \S*[/\\]app[/\\]src[/\\]main[/\\]kotlin""") + assertThat(buildResult.output).containsPattern("""--input \S*[/\\]app[/\\]src[/\\]debug[/\\]kotlin""") + assertThat(buildResult.output).contains("--report xml:") + assertThat(buildResult.output).contains("--report sarif:") + assertThat(buildResult.output).doesNotContain("--report txt:") + assertThat(buildResult.tasks.map { it.path }).containsAll( + listOf( + ":app:detektMain", + ":app:detektDebug" ) - } + ) } } - @Nested - inner class `does not configures android tasks if user opts out` { - val projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 0).apply { - addSubmodule( - name = "app", - numberOfSourceFilesPerSourceDir = 1, - numberOfCodeSmells = 1, - buildFileContent = """ - $APP_PLUGIN_BLOCK - $ANDROID_BLOCK - $DETEKT_REPORTS_BLOCK - """.trimIndent(), - srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java") + @Test + @DisplayName("task :app:detektTest") + fun appDetektTest() { + gradleRunner.runTasksAndCheckResult(":app:detektTest") { buildResult -> + assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-releaseUnitTest.xml """) + assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-debugUnitTest.xml """) + assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-debugAndroidTest.xml """) + assertThat(buildResult.output).containsPattern("""--input \S*[/\\]app[/\\]src[/\\]test[/\\]java""") + assertThat(buildResult.output).containsPattern("""--input \S*[/\\]app[/\\]src[/\\]androidTest[/\\]java""") + assertThat(buildResult.output).containsPattern("""--input \S*[/\\]app[/\\]src[/\\]test[/\\]kotlin""") + assertThat(buildResult.output).containsPattern("""--input \S*[/\\]app[/\\]src[/\\]androidTest[/\\]kotlin""") + assertThat(buildResult.output).contains("--report xml:") + assertThat(buildResult.output).contains("--report sarif:") + assertThat(buildResult.output).doesNotContain("--report txt:") + assertThat(buildResult.tasks.map { it.path }).containsAll( + listOf( + ":app:detektDebugUnitTest", + ":app:detektDebugAndroidTest" + ) ) } - val gradleRunner = createGradleRunnerAndSetupProject(projectLayout).also { - it.writeProjectFile("gradle.properties", "detekt.android.disabled=true") - it.writeProjectFile("app/src/main/AndroidManifest.xml", manifestContent()) - } - - @Test - @DisplayName("task :app:detekt") - fun appDetekt() { - gradleRunner.runTasks(":app:detekt") - } - - @Test - @DisplayName("task :app:detektMain") - fun appDetektMain() { - gradleRunner.runTasksAndExpectFailure(":app:detektMain") { result -> - assertThat(result.output).contains("Task 'detektMain' not found in project") - } - } + } + } - @Test - @DisplayName("task :app:detektTest") - fun appDetektTest() { - gradleRunner.runTasksAndExpectFailure(":app:detektTest") { result -> - assertThat(result.output).contains("Task 'detektTest' not found in project") - } - } + @Nested + inner class `does not configures android tasks if user opts out` { + val projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 0).apply { + addSubmodule( + name = "app", + numberOfSourceFilesPerSourceDir = 1, + numberOfCodeSmells = 1, + buildFileContent = """ + $APP_PLUGIN_BLOCK + $ANDROID_BLOCK + $DETEKT_REPORTS_BLOCK + """.trimIndent(), + srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java") + ) + } + val gradleRunner = createGradleRunnerAndSetupProject(projectLayout).also { + it.writeProjectFile("gradle.properties", "detekt.android.disabled=true") + it.writeProjectFile("app/src/main/AndroidManifest.xml", manifestContent()) } - @Nested - inner class `configures android tasks for android library` { - val projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 0).apply { - addSubmodule( - name = "lib", - numberOfSourceFilesPerSourceDir = 1, - numberOfCodeSmells = 1, - buildFileContent = """ - $LIB_PLUGIN_BLOCK - $ANDROID_BLOCK - $DETEKT_REPORTS_BLOCK - """.trimIndent(), - srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java"), - baselineFiles = listOf( - "detekt-baseline.xml", - "detekt-baseline-release.xml", - "detekt-baseline-debug.xml", - "detekt-baseline-releaseUnitTest.xml", - "detekt-baseline-debugUnitTest.xml", - "detekt-baseline-debugAndroidTest.xml" - ) - ) - } - val gradleRunner = createGradleRunnerAndSetupProject(projectLayout).also { - it.writeProjectFile("lib/src/main/AndroidManifest.xml", manifestContent()) - } + @Test + @DisplayName("task :app:detekt") + fun appDetekt() { + gradleRunner.runTasks(":app:detekt") + } - @Test - @DisplayName("task :lib:detektMain") - fun libDetektMain() { - gradleRunner.runTasksAndCheckResult(":lib:detektMain") { buildResult -> - assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-release.xml """) - assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-debug.xml """) - assertThat(buildResult.output).contains("--report xml:") - assertThat(buildResult.output).contains("--report sarif:") - assertThat(buildResult.output).doesNotContain("--report txt:") - assertThat(buildResult.tasks.map { it.path }).containsAll( - listOf( - ":lib:detektMain", - ":lib:detektDebug" - ) - ) - } + @Test + @DisplayName("task :app:detektMain") + fun appDetektMain() { + gradleRunner.runTasksAndExpectFailure(":app:detektMain") { result -> + assertThat(result.output).contains("Task 'detektMain' not found in project") } + } - @Test - @DisplayName("task :lib:detektTest") - fun libDetektTest() { - gradleRunner.runTasksAndCheckResult(":lib:detektTest") { buildResult -> - assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-releaseUnitTest.xml """) - assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-debugUnitTest.xml """) - assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-debugAndroidTest.xml """) - assertThat(buildResult.output).contains("--report xml:") - assertThat(buildResult.output).contains("--report sarif:") - assertThat(buildResult.output).doesNotContain("--report txt:") - assertThat(buildResult.tasks.map { it.path }).containsAll( - listOf( - ":lib:detektDebugUnitTest", - ":lib:detektDebugAndroidTest" - ) - ) - } + @Test + @DisplayName("task :app:detektTest") + fun appDetektTest() { + gradleRunner.runTasksAndExpectFailure(":app:detektTest") { result -> + assertThat(result.output).contains("Task 'detektTest' not found in project") } } + } - @Nested - inner class `configures android tasks for different build variants` { - - val projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 0).apply { - addSubmodule( - name = "lib", - numberOfSourceFilesPerSourceDir = 1, - numberOfCodeSmells = 1, - buildFileContent = """ - $LIB_PLUGIN_BLOCK - $ANDROID_BLOCK_WITH_FLAVOR - $DETEKT_REPORTS_BLOCK - """.trimIndent(), - srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java") + @Nested + inner class `configures android tasks for android library` { + val projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 0).apply { + addSubmodule( + name = "lib", + numberOfSourceFilesPerSourceDir = 1, + numberOfCodeSmells = 1, + buildFileContent = """ + $LIB_PLUGIN_BLOCK + $ANDROID_BLOCK + $DETEKT_REPORTS_BLOCK + """.trimIndent(), + srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java"), + baselineFiles = listOf( + "detekt-baseline.xml", + "detekt-baseline-release.xml", + "detekt-baseline-debug.xml", + "detekt-baseline-releaseUnitTest.xml", + "detekt-baseline-debugUnitTest.xml", + "detekt-baseline-debugAndroidTest.xml" ) - } - val gradleRunner = createGradleRunnerAndSetupProject(projectLayout).also { - it.writeProjectFile("lib/src/main/AndroidManifest.xml", manifestContent()) - } + ) + } + val gradleRunner = createGradleRunnerAndSetupProject(projectLayout).also { + it.writeProjectFile("lib/src/main/AndroidManifest.xml", manifestContent()) + } - @Test - @DisplayName("task :lib:detektMain") - fun libDetektMain() { - gradleRunner.runTasksAndCheckResult(":lib:detektMain") { buildResult -> - assertThat(buildResult.tasks.map { it.path }).containsAll( - listOf( - ":lib:detektYoungHarryDebug", - ":lib:detektOldHarryDebug", - ":lib:detektOldHarryRelease" - ) + @Test + @DisplayName("task :lib:detektMain") + fun libDetektMain() { + gradleRunner.runTasksAndCheckResult(":lib:detektMain") { buildResult -> + assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-release.xml """) + assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-debug.xml """) + assertThat(buildResult.output).contains("--report xml:") + assertThat(buildResult.output).contains("--report sarif:") + assertThat(buildResult.output).doesNotContain("--report txt:") + assertThat(buildResult.tasks.map { it.path }).containsAll( + listOf( + ":lib:detektMain", + ":lib:detektDebug" ) - } + ) } + } - @Test - @DisplayName("task :lib:detektTest") - fun libDetektTest() { - gradleRunner.runTasksAndCheckResult(":lib:detektTest") { buildResult -> - assertThat(buildResult.tasks.map { it.path }).containsAll( - listOf( - ":lib:detektYoungHarryDebugUnitTest", - ":lib:detektOldHarryDebugUnitTest", - ":lib:detektOldHarryReleaseUnitTest", - ":lib:detektYoungHarryDebugAndroidTest", - ":lib:detektOldHarryDebugAndroidTest" - ) + @Test + @DisplayName("task :lib:detektTest") + fun libDetektTest() { + gradleRunner.runTasksAndCheckResult(":lib:detektTest") { buildResult -> + assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-releaseUnitTest.xml """) + assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-debugUnitTest.xml """) + assertThat(buildResult.output).containsPattern("""--baseline \S*[/\\]detekt-baseline-debugAndroidTest.xml """) + assertThat(buildResult.output).contains("--report xml:") + assertThat(buildResult.output).contains("--report sarif:") + assertThat(buildResult.output).doesNotContain("--report txt:") + assertThat(buildResult.tasks.map { it.path }).containsAll( + listOf( + ":lib:detektDebugUnitTest", + ":lib:detektDebugAndroidTest" ) - } + ) } } + } - @Nested - inner class `configures android tasks for different build variants excluding ignored build types` { - - val projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 0).apply { - addSubmodule( - name = "lib", - numberOfSourceFilesPerSourceDir = 1, - numberOfCodeSmells = 1, - buildFileContent = """ - $LIB_PLUGIN_BLOCK - $ANDROID_BLOCK_WITH_FLAVOR - detekt { - ignoredBuildTypes = listOf("release") - } - """.trimIndent(), - srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java") - ) - } - val gradleRunner = createGradleRunnerAndSetupProject(projectLayout).also { - it.writeProjectFile("lib/src/main/AndroidManifest.xml", manifestContent()) - } + @Nested + inner class `configures android tasks for different build variants` { + + val projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 0).apply { + addSubmodule( + name = "lib", + numberOfSourceFilesPerSourceDir = 1, + numberOfCodeSmells = 1, + buildFileContent = """ + $LIB_PLUGIN_BLOCK + $ANDROID_BLOCK_WITH_FLAVOR + $DETEKT_REPORTS_BLOCK + """.trimIndent(), + srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java") + ) + } + val gradleRunner = createGradleRunnerAndSetupProject(projectLayout).also { + it.writeProjectFile("lib/src/main/AndroidManifest.xml", manifestContent()) + } - @Test - @DisplayName("task :lib:detektMain") - fun libDetektMain() { - gradleRunner.runTasksAndCheckResult(":lib:detektMain") { buildResult -> - assertThat(buildResult.tasks.map { it.path }).containsAll( - listOf( - ":lib:detektYoungHarryDebug", - ":lib:detektOldHarryDebug" - ) - ).doesNotContain( + @Test + @DisplayName("task :lib:detektMain") + fun libDetektMain() { + gradleRunner.runTasksAndCheckResult(":lib:detektMain") { buildResult -> + assertThat(buildResult.tasks.map { it.path }).containsAll( + listOf( + ":lib:detektYoungHarryDebug", + ":lib:detektOldHarryDebug", ":lib:detektOldHarryRelease" ) - } + ) } + } - @Test - @DisplayName("task :lib:detektTest") - fun libDetektTest() { - gradleRunner.runTasksAndCheckResult(":lib:detektTest") { buildResult -> - assertThat(buildResult.tasks.map { it.path }).containsAll( - listOf( - ":lib:detektYoungHarryDebugUnitTest", - ":lib:detektOldHarryDebugUnitTest", - ":lib:detektYoungHarryDebugAndroidTest", - ":lib:detektOldHarryDebugAndroidTest" - ) - ).doesNotContain( - ":lib:detektOldHarryReleaseUnitTest" + @Test + @DisplayName("task :lib:detektTest") + fun libDetektTest() { + gradleRunner.runTasksAndCheckResult(":lib:detektTest") { buildResult -> + assertThat(buildResult.tasks.map { it.path }).containsAll( + listOf( + ":lib:detektYoungHarryDebugUnitTest", + ":lib:detektOldHarryDebugUnitTest", + ":lib:detektOldHarryReleaseUnitTest", + ":lib:detektYoungHarryDebugAndroidTest", + ":lib:detektOldHarryDebugAndroidTest" ) - } + ) } } + } - @Nested - inner class `configures android tasks for different build variants excluding ignored variants` { - - val projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 0).apply { - addSubmodule( - name = "lib", - numberOfSourceFilesPerSourceDir = 1, - numberOfCodeSmells = 1, - buildFileContent = """ - $LIB_PLUGIN_BLOCK - $ANDROID_BLOCK_WITH_FLAVOR - detekt { - ignoredVariants = listOf("youngHarryDebug", "oldHarryRelease") - } - """.trimIndent(), - srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java") - ) - } - val gradleRunner = createGradleRunnerAndSetupProject(projectLayout).also { - it.writeProjectFile("lib/src/main/AndroidManifest.xml", manifestContent()) - } + @Nested + inner class `configures android tasks for different build variants excluding ignored build types` { + + val projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 0).apply { + addSubmodule( + name = "lib", + numberOfSourceFilesPerSourceDir = 1, + numberOfCodeSmells = 1, + buildFileContent = """ + $LIB_PLUGIN_BLOCK + $ANDROID_BLOCK_WITH_FLAVOR + detekt { + ignoredBuildTypes = listOf("release") + } + """.trimIndent(), + srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java") + ) + } + val gradleRunner = createGradleRunnerAndSetupProject(projectLayout).also { + it.writeProjectFile("lib/src/main/AndroidManifest.xml", manifestContent()) + } - @Test - @DisplayName("task :lib:detektMain") - fun libDetektMain() { - gradleRunner.runTasksAndCheckResult(":lib:detektMain") { buildResult -> - assertThat(buildResult.tasks.map { it.path }).containsAll( - listOf( - ":lib:detektOldHarryDebug" - ) - ).doesNotContain( + @Test + @DisplayName("task :lib:detektMain") + fun libDetektMain() { + gradleRunner.runTasksAndCheckResult(":lib:detektMain") { buildResult -> + assertThat(buildResult.tasks.map { it.path }).containsAll( + listOf( ":lib:detektYoungHarryDebug", - ":lib:detektOldHarryRelease" + ":lib:detektOldHarryDebug" ) - } + ).doesNotContain( + ":lib:detektOldHarryRelease" + ) } + } - @Test - @DisplayName("task :lib:detektTest") - fun libDetektTest() { - gradleRunner.runTasksAndCheckResult(":lib:detektTest") { buildResult -> - assertThat(buildResult.tasks.map { it.path }).containsAll( - listOf( - ":lib:detektOldHarryDebugUnitTest", - ":lib:detektOldHarryDebugAndroidTest" - ) - ).doesNotContain( + @Test + @DisplayName("task :lib:detektTest") + fun libDetektTest() { + gradleRunner.runTasksAndCheckResult(":lib:detektTest") { buildResult -> + assertThat(buildResult.tasks.map { it.path }).containsAll( + listOf( ":lib:detektYoungHarryDebugUnitTest", + ":lib:detektOldHarryDebugUnitTest", ":lib:detektYoungHarryDebugAndroidTest", - ":lib:detektOldHarryReleaseUnitTest" + ":lib:detektOldHarryDebugAndroidTest" ) - } + ).doesNotContain( + ":lib:detektOldHarryReleaseUnitTest" + ) } } + } - @Nested - inner class `configures android tasks for different build variants excluding ignored flavors` { - - val projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 0).apply { - addSubmodule( - name = "lib", - numberOfSourceFilesPerSourceDir = 1, - numberOfCodeSmells = 1, - buildFileContent = """ - $LIB_PLUGIN_BLOCK - $ANDROID_BLOCK_WITH_FLAVOR - detekt { - ignoredFlavors = listOf("youngHarry") - } - """.trimIndent(), - srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java") + @Nested + inner class `configures android tasks for different build variants excluding ignored variants` { + + val projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 0).apply { + addSubmodule( + name = "lib", + numberOfSourceFilesPerSourceDir = 1, + numberOfCodeSmells = 1, + buildFileContent = """ + $LIB_PLUGIN_BLOCK + $ANDROID_BLOCK_WITH_FLAVOR + detekt { + ignoredVariants = listOf("youngHarryDebug", "oldHarryRelease") + } + """.trimIndent(), + srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java") + ) + } + val gradleRunner = createGradleRunnerAndSetupProject(projectLayout).also { + it.writeProjectFile("lib/src/main/AndroidManifest.xml", manifestContent()) + } + + @Test + @DisplayName("task :lib:detektMain") + fun libDetektMain() { + gradleRunner.runTasksAndCheckResult(":lib:detektMain") { buildResult -> + assertThat(buildResult.tasks.map { it.path }).containsAll( + listOf( + ":lib:detektOldHarryDebug" + ) + ).doesNotContain( + ":lib:detektYoungHarryDebug", + ":lib:detektOldHarryRelease" ) } - val gradleRunner = createGradleRunnerAndSetupProject(projectLayout).also { - it.writeProjectFile("lib/src/main/AndroidManifest.xml", manifestContent()) + } + + @Test + @DisplayName("task :lib:detektTest") + fun libDetektTest() { + gradleRunner.runTasksAndCheckResult(":lib:detektTest") { buildResult -> + assertThat(buildResult.tasks.map { it.path }).containsAll( + listOf( + ":lib:detektOldHarryDebugUnitTest", + ":lib:detektOldHarryDebugAndroidTest" + ) + ).doesNotContain( + ":lib:detektYoungHarryDebugUnitTest", + ":lib:detektYoungHarryDebugAndroidTest", + ":lib:detektOldHarryReleaseUnitTest" + ) } + } + } - @Test - @DisplayName("task :lib:detektMain") - fun libDetektMain() { - gradleRunner.runTasksAndCheckResult(":lib:detektMain") { buildResult -> - assertThat(buildResult.tasks.map { it.path }).containsAll( - listOf( - ":lib:detektOldHarryDebug", - ":lib:detektOldHarryRelease" - ) - ).doesNotContain( - ":lib:detektYoungHarryDebug" + @Nested + inner class `configures android tasks for different build variants excluding ignored flavors` { + + val projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 0).apply { + addSubmodule( + name = "lib", + numberOfSourceFilesPerSourceDir = 1, + numberOfCodeSmells = 1, + buildFileContent = """ + $LIB_PLUGIN_BLOCK + $ANDROID_BLOCK_WITH_FLAVOR + detekt { + ignoredFlavors = listOf("youngHarry") + } + """.trimIndent(), + srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java") + ) + } + val gradleRunner = createGradleRunnerAndSetupProject(projectLayout).also { + it.writeProjectFile("lib/src/main/AndroidManifest.xml", manifestContent()) + } + + @Test + @DisplayName("task :lib:detektMain") + fun libDetektMain() { + gradleRunner.runTasksAndCheckResult(":lib:detektMain") { buildResult -> + assertThat(buildResult.tasks.map { it.path }).containsAll( + listOf( + ":lib:detektOldHarryDebug", + ":lib:detektOldHarryRelease" ) - } + ).doesNotContain( + ":lib:detektYoungHarryDebug" + ) } + } - @Test - @DisplayName("task :lib:detektTest") - fun libDetektTest() { - gradleRunner.runTasksAndCheckResult(":lib:detektTest") { buildResult -> - assertThat(buildResult.tasks.map { it.path }).containsAll( - listOf( - ":lib:detektOldHarryDebugUnitTest", - ":lib:detektOldHarryDebugAndroidTest", - ":lib:detektOldHarryReleaseUnitTest" - ) - ).doesNotContain( - ":lib:detektYoungHarryDebugUnitTest", - ":lib:detektYoungHarryDebugAndroidTest" + @Test + @DisplayName("task :lib:detektTest") + fun libDetektTest() { + gradleRunner.runTasksAndCheckResult(":lib:detektTest") { buildResult -> + assertThat(buildResult.tasks.map { it.path }).containsAll( + listOf( + ":lib:detektOldHarryDebugUnitTest", + ":lib:detektOldHarryDebugAndroidTest", + ":lib:detektOldHarryReleaseUnitTest" ) - } + ).doesNotContain( + ":lib:detektYoungHarryDebugUnitTest", + ":lib:detektYoungHarryDebugAndroidTest" + ) } } } diff --git a/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/DetektJvmSpec.kt b/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/DetektJvmSpec.kt index 326a73144c3..6ab22b1923e 100644 --- a/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/DetektJvmSpec.kt +++ b/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/DetektJvmSpec.kt @@ -7,82 +7,79 @@ import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class DetektJvmSpec { - @Nested - inner class `When applying detekt in a JVM project` { - @Nested - inner class `report location set on extension & task` { - val gradleRunner = DslGradleRunner( - projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 1), - buildFileName = "build.gradle.kts", - mainBuildFileContent = """ - plugins { - kotlin("jvm") - id("io.gitlab.arturbosch.detekt") - } + @Nested + inner class `report location set on extension & task` { + val gradleRunner = DslGradleRunner( + projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 1), + buildFileName = "build.gradle.kts", + mainBuildFileContent = """ + plugins { + kotlin("jvm") + id("io.gitlab.arturbosch.detekt") + } - repositories { - mavenCentral() - mavenLocal() - } + repositories { + mavenCentral() + mavenLocal() + } - detekt { - reports { - txt.destination = file("output-path.txt") - } + detekt { + reports { + txt.destination = file("output-path.txt") } + } - tasks.withType().configureEach { - reports { - txt.destination = file("output-path2.txt") - } + tasks.withType().configureEach { + reports { + txt.destination = file("output-path2.txt") } - """.trimIndent(), - dryRun = false - ).also { - it.setupProject() - } - - @Test - fun `logs a warning`() { - gradleRunner.runTasksAndCheckResult(":detektMain") { buildResult -> - assertThat(buildResult.output).contains("TXT report location set on detekt {} extension will be ignored for detektMain task.") } + """.trimIndent(), + dryRun = false + ).also { + it.setupProject() + } + + @Test + fun `logs a warning`() { + gradleRunner.runTasksAndCheckResult(":detektMain") { buildResult -> + assertThat(buildResult.output).contains("TXT report location set on detekt {} extension will be ignored for detektMain task.") } } + } - @Nested - inner class `report location set on task only` { - val gradleRunner = DslGradleRunner( - projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 1), - buildFileName = "build.gradle.kts", - mainBuildFileContent = """ - plugins { - kotlin("jvm") - id("io.gitlab.arturbosch.detekt") - } + @Nested + inner class `report location set on task only` { + val gradleRunner = DslGradleRunner( + projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 1), + buildFileName = "build.gradle.kts", + mainBuildFileContent = """ + plugins { + kotlin("jvm") + id("io.gitlab.arturbosch.detekt") + } - repositories { - mavenCentral() - mavenLocal() - } + repositories { + mavenCentral() + mavenLocal() + } - tasks.withType().configureEach { - reports { - txt.destination = file("output-path2.txt") - } + tasks.withType().configureEach { + reports { + txt.destination = file("output-path2.txt") } - """.trimIndent(), - dryRun = false - ).also { - it.setupProject() - } - - @Test - fun `logs a warning`() { - gradleRunner.runTasksAndCheckResult(":detektMain") { buildResult -> - assertThat(buildResult.output).doesNotContain("report location set on detekt {} extension will be ignored") } + """.trimIndent(), + dryRun = false + ).also { + it.setupProject() + } + + @Test + fun `logs a warning`() { + gradleRunner.runTasksAndCheckResult(":detektMain") { buildResult -> + assertThat(buildResult.output).doesNotContain("report location set on detekt {} extension will be ignored") } } } diff --git a/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/DetektTaskDslSpec.kt b/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/DetektTaskDslSpec.kt index cd5fd267c1c..33009439de8 100644 --- a/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/DetektTaskDslSpec.kt +++ b/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/DetektTaskDslSpec.kt @@ -17,711 +17,704 @@ import org.junit.jupiter.params.provider.EnumSource class DetektTaskDslSpec { + lateinit var gradleRunner: DslGradleRunner + lateinit var result: BuildResult + val defaultDetektVersion = loadDetektVersion(DetektTaskDslSpec::class.java.classLoader) + val builder = kotlin().dryRun() + @Nested - inner class `When applying the detekt gradle plugin` { + inner class `without detekt config` { - lateinit var gradleRunner: DslGradleRunner - lateinit var result: BuildResult - val defaultDetektVersion = loadDetektVersion(DetektTaskDslSpec::class.java.classLoader) - val builder = kotlin().dryRun() + @BeforeAll + fun beforeGroup() { + gradleRunner = builder.build() + result = gradleRunner.runDetektTask() + } - @Nested - inner class `without detekt config` { + @Test + fun `completes successfully`() { + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + } - @BeforeAll - fun beforeGroup() { - gradleRunner = builder.build() - result = gradleRunner.runDetektTask() - } + @Test + fun `enables xml report to default location`() { + val xmlReportFile = gradleRunner.projectFile("build/reports/detekt/detekt.xml") + assertThat(result.output).contains("--report xml:$xmlReportFile") + } - @Test - fun `completes successfully`() { - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } + @Test + fun `enables html report to default location`() { + val htmlReportFile = gradleRunner.projectFile("build/reports/detekt/detekt.html") + assertThat(result.output).contains("--report html:$htmlReportFile") + } - @Test - fun `enables xml report to default location`() { - val xmlReportFile = gradleRunner.projectFile("build/reports/detekt/detekt.xml") - assertThat(result.output).contains("--report xml:$xmlReportFile") - } + @Test + fun `enables text report to default location`() { + val textReportFile = gradleRunner.projectFile("build/reports/detekt/detekt.txt") + assertThat(result.output).contains("--report txt:$textReportFile") + } - @Test - fun `enables html report to default location`() { - val htmlReportFile = gradleRunner.projectFile("build/reports/detekt/detekt.html") - assertThat(result.output).contains("--report html:$htmlReportFile") - } + @Test + fun `enables sarif report to default location`() { + val sarifReportFile = gradleRunner.projectFile("build/reports/detekt/detekt.sarif") + assertThat(result.output).contains("--report sarif:$sarifReportFile") + } - @Test - fun `enables text report to default location`() { - val textReportFile = gradleRunner.projectFile("build/reports/detekt/detekt.txt") - assertThat(result.output).contains("--report txt:$textReportFile") - } + @Test + @DisplayName("set as input all the kotlin files in src/main/java and src/main/kotlin") + fun setInputFiles() { + val file1 = gradleRunner.projectFile("src/main/java/My0Root0Class.kt") + val file2 = gradleRunner.projectFile("src/test/java/My1Root0Class.kt") + val file3 = gradleRunner.projectFile("src/main/kotlin/My2Root0Class.kt") + val file4 = gradleRunner.projectFile("src/test/kotlin/My3Root0Class.kt") + assertThat(result.output).contains("--input $file1,$file2,$file3,$file4 ") + } + } - @Test - fun `enables sarif report to default location`() { - val sarifReportFile = gradleRunner.projectFile("build/reports/detekt/detekt.sarif") - assertThat(result.output).contains("--report sarif:$sarifReportFile") - } + @Nested + inner class `without multiple detekt configs` { - @Test - @DisplayName("set as input all the kotlin files in src/main/java and src/main/kotlin") - fun setInputFiles() { - val file1 = gradleRunner.projectFile("src/main/java/My0Root0Class.kt") - val file2 = gradleRunner.projectFile("src/test/java/My1Root0Class.kt") - val file3 = gradleRunner.projectFile("src/main/kotlin/My2Root0Class.kt") - val file4 = gradleRunner.projectFile("src/test/kotlin/My3Root0Class.kt") - assertThat(result.output).contains("--input $file1,$file2,$file3,$file4 ") - } - } + @BeforeAll + fun beforeGroup() { + val config = """ + |detekt { + | config.setFrom(files("firstConfig.yml", "secondConfig.yml")) + |} + """ - @Nested - inner class `without multiple detekt configs` { + gradleRunner = builder.withDetektConfig(config).build() - @BeforeAll - fun beforeGroup() { - val config = """ - |detekt { - | config.setFrom(files("firstConfig.yml", "secondConfig.yml")) - |} - """ + result = gradleRunner.runDetektTask() + } - gradleRunner = builder.withDetektConfig(config).build() + @Test + fun `passes absolute filename of both config files to detekt cli`() { + val firstConfig = gradleRunner.projectFile("firstConfig.yml") + val secondConfig = gradleRunner.projectFile("secondConfig.yml") - result = gradleRunner.runDetektTask() - } + val expectedConfigParam = "--config $firstConfig,$secondConfig" + assertThat(result.output).contains(expectedConfigParam) + } + } - @Test - fun `passes absolute filename of both config files to detekt cli`() { - val firstConfig = gradleRunner.projectFile("firstConfig.yml") - val secondConfig = gradleRunner.projectFile("secondConfig.yml") + @Nested + inner class `with custom baseline file` { + val baselineFilename = "custom-baseline.xml" + + @BeforeAll + fun beforeGroup() { + val config = """ + |detekt { + | baseline = file("$baselineFilename") + |} + """ + + gradleRunner = builder + .withDetektConfig(config) + .withBaseline(baselineFilename) + .build() + result = gradleRunner.runDetektTask() + } - val expectedConfigParam = "--config $firstConfig,$secondConfig" - assertThat(result.output).contains(expectedConfigParam) - } + @Test + fun `sets baseline parameter with absolute filename`() { + val baselineFile = gradleRunner.projectFile(baselineFilename) + val expectedBaselineArgument = "--baseline $baselineFile" + assertThat(result.output).contains(expectedBaselineArgument) } + } - @Nested - inner class `with custom baseline file` { - val baselineFilename = "custom-baseline.xml" + @Nested + inner class `with custom baseline file that doesn't exist` { + val baselineFilename = "detekt-baseline-no-exist.xml" + + @BeforeAll + fun beforeGroup() { + val config = """ + |detekt { + | baseline = file("$baselineFilename") + |} + """ + + gradleRunner = builder + .withDetektConfig(config) + .build() + result = gradleRunner.runDetektTask() + } - @BeforeAll - fun beforeGroup() { - val config = """ - |detekt { - | baseline = file("$baselineFilename") - |} - """ + @Test + fun `doesn't set the baseline parameter`() { + assertThat(result.output).doesNotContain("--baseline") + } + } - gradleRunner = builder - .withDetektConfig(config) - .withBaseline(baselineFilename) - .build() - result = gradleRunner.runDetektTask() - } + @Nested + @DisplayName("[deprecated] with custom input directories using input") + inner class CustomInputDirectoriesUsingInput { + val customSrc1 = "gensrc/kotlin" + val customSrc2 = "src/main/kotlin" + + @BeforeAll + fun beforeGroup() { + val config = """ + |detekt { + | input = files("$customSrc1", "$customSrc2", "folder_that_does_not_exist") + |} + """ + + val projectLayout = ProjectLayout(1, srcDirs = listOf(customSrc1, customSrc2)) + gradleRunner = builder + .withProjectLayout(projectLayout) + .withDetektConfig(config) + .build() + result = gradleRunner.runDetektTask() + } - @Test - fun `sets baseline parameter with absolute filename`() { - val baselineFile = gradleRunner.projectFile(baselineFilename) - val expectedBaselineArgument = "--baseline $baselineFile" - assertThat(result.output).contains(expectedBaselineArgument) - } + @Test + fun `sets input parameter to absolute filenames of all source files`() { + val file1 = gradleRunner.projectFile("$customSrc1/My0Root0Class.kt") + val file2 = gradleRunner.projectFile("$customSrc2/My1Root0Class.kt") + val expectedInputParam = "--input $file1,$file2" + assertThat(result.output).contains(expectedInputParam) } - @Nested - inner class `with custom baseline file that doesn't exist` { - val baselineFilename = "detekt-baseline-no-exist.xml" + @Test + fun `ignores input directories that do not exist`() { + assertThat(result.output).doesNotContain("folder_that_does_not_exist") + } + } - @BeforeAll - fun beforeGroup() { - val config = """ - |detekt { - | baseline = file("$baselineFilename") - |} - """ + @Nested + inner class `with custom input directories` { + val customSrc1 = "gensrc/kotlin" + val customSrc2 = "src/main/kotlin" + + @BeforeAll + fun beforeGroup() { + val config = """ + |detekt { + | source = files("$customSrc1", "$customSrc2", "folder_that_does_not_exist") + |} + """ + + val projectLayout = ProjectLayout(1, srcDirs = listOf(customSrc1, customSrc2)) + gradleRunner = builder + .withProjectLayout(projectLayout) + .withDetektConfig(config) + .build() + result = gradleRunner.runDetektTask() + } - gradleRunner = builder - .withDetektConfig(config) - .build() - result = gradleRunner.runDetektTask() - } + @Test + fun `sets input parameter to absolute filenames of all source files`() { + val file1 = gradleRunner.projectFile("$customSrc1/My0Root0Class.kt") + val file2 = gradleRunner.projectFile("$customSrc2/My1Root0Class.kt") + val expectedInputParam = "--input $file1,$file2" + assertThat(result.output).contains(expectedInputParam) + } - @Test - fun `doesn't set the baseline parameter`() { - assertThat(result.output).doesNotContain("--baseline") - } + @Test + fun `ignores input directories that do not exist`() { + assertThat(result.output).doesNotContain("folder_that_does_not_exist") } + } - @Nested - @DisplayName("[deprecated] with custom input directories using input") - inner class CustomInputDirectoriesUsingInput { - val customSrc1 = "gensrc/kotlin" - val customSrc2 = "src/main/kotlin" + @Nested + inner class `with custom reports dir` { + + @BeforeAll + fun beforeGroup() { + val config = """ + |detekt { + | reportsDir = file("build/detekt-reports") + |} + """ + + gradleRunner = builder + .withDetektConfig(config) + .build() + result = gradleRunner.runDetektTask() + } - @BeforeAll - fun beforeGroup() { - val config = """ - |detekt { - | input = files("$customSrc1", "$customSrc2", "folder_that_does_not_exist") - |} - """ + @Test + fun `configures xml report to custom directory`() { + val xmlReportFile = gradleRunner.projectFile("build/detekt-reports/detekt.xml") + assertThat(result.output).contains("--report xml:$xmlReportFile") + } - val projectLayout = ProjectLayout(1, srcDirs = listOf(customSrc1, customSrc2)) - gradleRunner = builder - .withProjectLayout(projectLayout) - .withDetektConfig(config) - .build() - result = gradleRunner.runDetektTask() - } + @Test + fun `configures html report to custom directory`() { + val htmlReportFile = gradleRunner.projectFile("build/detekt-reports/detekt.html") + assertThat(result.output).contains("--report html:$htmlReportFile") + } - @Test - fun `sets input parameter to absolute filenames of all source files`() { - val file1 = gradleRunner.projectFile("$customSrc1/My0Root0Class.kt") - val file2 = gradleRunner.projectFile("$customSrc2/My1Root0Class.kt") - val expectedInputParam = "--input $file1,$file2" - assertThat(result.output).contains(expectedInputParam) - } + @Test + fun `configures text report to custom directory`() { + val textReportFile = gradleRunner.projectFile("build/detekt-reports/detekt.txt") + assertThat(result.output).contains("--report txt:$textReportFile") + } - @Test - fun `ignores input directories that do not exist`() { - assertThat(result.output).doesNotContain("folder_that_does_not_exist") - } + @Test + fun `configures sarif report to custom directory`() { + val sarifReportFile = gradleRunner.projectFile("build/detekt-reports/detekt.sarif") + assertThat(result.output).contains("--report sarif:$sarifReportFile") } + } - @Nested - inner class `with custom input directories` { - val customSrc1 = "gensrc/kotlin" - val customSrc2 = "src/main/kotlin" + @Nested + inner class `with custom reports dir and custom report filename` { + + @BeforeAll + fun beforeGroup() { + val config = """ + |detekt { + | reportsDir = file("build/detekt-reports") + |} + | + |tasks.detekt { + | reports { + | xml.destination = file("build/xml-reports/custom-detekt.xml") + | } + |} + """ + + gradleRunner = builder + .withDetektConfig(config) + .build() + result = gradleRunner.runDetektTask() + } - @BeforeAll - fun beforeGroup() { - val config = """ - |detekt { - | source = files("$customSrc1", "$customSrc2", "folder_that_does_not_exist") - |} - """ + @Test + fun `configures xml report to specific absolute filename`() { + val xmlReportFile = gradleRunner.projectFile("build/xml-reports/custom-detekt.xml") + assertThat(result.output).contains("--report xml:$xmlReportFile") + } - val projectLayout = ProjectLayout(1, srcDirs = listOf(customSrc1, customSrc2)) - gradleRunner = builder - .withProjectLayout(projectLayout) - .withDetektConfig(config) - .build() - result = gradleRunner.runDetektTask() - } + @Test + fun `configures html report to default name in custom directory`() { + val htmlReportFile = gradleRunner.projectFile("build/detekt-reports/detekt.html") + assertThat(result.output).contains("--report html:$htmlReportFile") + } - @Test - fun `sets input parameter to absolute filenames of all source files`() { - val file1 = gradleRunner.projectFile("$customSrc1/My0Root0Class.kt") - val file2 = gradleRunner.projectFile("$customSrc2/My1Root0Class.kt") - val expectedInputParam = "--input $file1,$file2" - assertThat(result.output).contains(expectedInputParam) - } + @Test + fun `configures text report to default name in custom directory`() { + val textReportFile = gradleRunner.projectFile("build/detekt-reports/detekt.txt") + assertThat(result.output).contains("--report txt:$textReportFile") + } + } - @Test - fun `ignores input directories that do not exist`() { - assertThat(result.output).doesNotContain("folder_that_does_not_exist") - } + @Nested + inner class `with disabled reports` { + + @BeforeAll + fun beforeGroup() { + val config = """ + |tasks.detekt { + | reports { + | xml.enabled = false + | html { + | enabled = false + | } + | txt { + | enabled = false + | } + | sarif { + | enabled = false + | } + | } + |} + """ + + gradleRunner = builder + .withDetektConfig(config) + .build() + result = gradleRunner.runDetektTask() } - @Nested - inner class `with custom reports dir` { + @Test + fun `no report param is set`() { + assertThat(result.output).doesNotContain("--report") + } + } + @Nested + inner class `with custom report types` { + @Nested + inner class `configured correctly` { @BeforeAll fun beforeGroup() { val config = """ - |detekt { - | reportsDir = file("build/detekt-reports") - |} + |tasks.detekt { + | reports { + | custom { + | reportId = "customXml" + | destination = file("build/reports/custom.xml") + | } + | custom { + | reportId = "customJson" + | destination = file("build/reports/custom.json") + | } + | } + |} """ - gradleRunner = builder - .withDetektConfig(config) - .build() + gradleRunner = builder.withDetektConfig(config).build() result = gradleRunner.runDetektTask() } @Test - fun `configures xml report to custom directory`() { - val xmlReportFile = gradleRunner.projectFile("build/detekt-reports/detekt.xml") - assertThat(result.output).contains("--report xml:$xmlReportFile") - } - - @Test - fun `configures html report to custom directory`() { - val htmlReportFile = gradleRunner.projectFile("build/detekt-reports/detekt.html") - assertThat(result.output).contains("--report html:$htmlReportFile") - } - - @Test - fun `configures text report to custom directory`() { - val textReportFile = gradleRunner.projectFile("build/detekt-reports/detekt.txt") - assertThat(result.output).contains("--report txt:$textReportFile") + fun `configures custom xml report to absolute filename`() { + val xmlReportFile = gradleRunner.projectFile("build/reports/custom.xml") + assertThat(result.output).contains("--report customXml:$xmlReportFile") } @Test - fun `configures sarif report to custom directory`() { - val sarifReportFile = gradleRunner.projectFile("build/detekt-reports/detekt.sarif") - assertThat(result.output).contains("--report sarif:$sarifReportFile") + fun `configures custom json report to absolute filename`() { + val xmlReportFile = gradleRunner.projectFile("build/reports/custom.json") + assertThat(result.output).contains("--report customJson:$xmlReportFile") } } @Nested - inner class `with custom reports dir and custom report filename` { - + inner class `report id is missing` { @BeforeAll fun beforeGroup() { val config = """ - |detekt { - | reportsDir = file("build/detekt-reports") - |} - | - |tasks.detekt { - | reports { - | xml.destination = file("build/xml-reports/custom-detekt.xml") - | } - |} + |tasks.withType().configureEach { + | reports { + | custom { + | destination = file("build/reports/custom.xml") + | } + | } + |} """ - gradleRunner = builder - .withDetektConfig(config) - .build() - result = gradleRunner.runDetektTask() - } - - @Test - fun `configures xml report to specific absolute filename`() { - val xmlReportFile = gradleRunner.projectFile("build/xml-reports/custom-detekt.xml") - assertThat(result.output).contains("--report xml:$xmlReportFile") - } - - @Test - fun `configures html report to default name in custom directory`() { - val htmlReportFile = gradleRunner.projectFile("build/detekt-reports/detekt.html") - assertThat(result.output).contains("--report html:$htmlReportFile") + gradleRunner = builder.withDetektConfig(config).build() } @Test - fun `configures text report to default name in custom directory`() { - val textReportFile = gradleRunner.projectFile("build/detekt-reports/detekt.txt") - assertThat(result.output).contains("--report txt:$textReportFile") + fun `fails the build`() { + gradleRunner.runDetektTaskAndExpectFailure { result -> + assertThat(result.output) + .contains("If a custom report is specified, the reportId must be present") + } } } @Nested - inner class `with disabled reports` { - + inner class `report filename is missing` { @BeforeAll fun beforeGroup() { val config = """ - |tasks.detekt { - | reports { - | xml.enabled = false - | html { - | enabled = false - | } - | txt { - | enabled = false - | } - | sarif { - | enabled = false - | } - | } - |} + |tasks.withType().configureEach { + | reports { + | custom { + | reportId = "customJson" + | } + | } + |} """ - gradleRunner = builder - .withDetektConfig(config) - .build() - result = gradleRunner.runDetektTask() + gradleRunner = builder.withDetektConfig(config).build() } @Test - fun `no report param is set`() { - assertThat(result.output).doesNotContain("--report") + fun `fails the build`() { + gradleRunner.runDetektTaskAndExpectFailure { result -> + assertThat(result.output) + .contains("If a custom report is specified, the destination must be present") + } } } @Nested - inner class `with custom report types` { - @Nested - inner class `configured correctly` { - @BeforeAll - fun beforeGroup() { - val config = """ - |tasks.detekt { - | reports { - | custom { - | reportId = "customXml" - | destination = file("build/reports/custom.xml") - | } - | custom { - | reportId = "customJson" - | destination = file("build/reports/custom.json") - | } - | } - |} - """ - - gradleRunner = builder.withDetektConfig(config).build() - result = gradleRunner.runDetektTask() - } - - @Test - fun `configures custom xml report to absolute filename`() { - val xmlReportFile = gradleRunner.projectFile("build/reports/custom.xml") - assertThat(result.output).contains("--report customXml:$xmlReportFile") - } - - @Test - fun `configures custom json report to absolute filename`() { - val xmlReportFile = gradleRunner.projectFile("build/reports/custom.json") - assertThat(result.output).contains("--report customJson:$xmlReportFile") - } - } - - @Nested - inner class `report id is missing` { - @BeforeAll - fun beforeGroup() { - val config = """ - |tasks.withType().configureEach { - | reports { - | custom { - | destination = file("build/reports/custom.xml") - | } - | } - |} - """ - - gradleRunner = builder.withDetektConfig(config).build() - } - - @Test - fun `fails the build`() { - gradleRunner.runDetektTaskAndExpectFailure { result -> - assertThat(result.output) - .contains("If a custom report is specified, the reportId must be present") - } - } - } - - @Nested - inner class `report filename is missing` { - @BeforeAll - fun beforeGroup() { - val config = """ - |tasks.withType().configureEach { - | reports { - | custom { - | reportId = "customJson" - | } - | } - |} - """ - - gradleRunner = builder.withDetektConfig(config).build() - } - - @Test - fun `fails the build`() { - gradleRunner.runDetektTaskAndExpectFailure { result -> - assertThat(result.output) - .contains("If a custom report is specified, the destination must be present") - } - } - } + inner class `report filename is a directory` { + @BeforeAll + fun beforeGroup() { + val aDirectory = "\${rootDir}/src" - @Nested - inner class `report filename is a directory` { - @BeforeAll - fun beforeGroup() { - val aDirectory = "\${rootDir}/src" - - val config = """ - |tasks.withType().configureEach { - | reports { - | custom { - | reportId = "foo" - | destination = file("$aDirectory") - | } - | } - |} - """ - - gradleRunner = builder.withDetektConfig(config).build() - } + val config = """ + |tasks.withType().configureEach { + | reports { + | custom { + | reportId = "foo" + | destination = file("$aDirectory") + | } + | } + |} + """ - @Test - fun `fails the build`() { - gradleRunner.runDetektTaskAndExpectFailure { result -> - assertThat(result.output).contains("Cannot write a file to a location pointing at a directory.") - } - } + gradleRunner = builder.withDetektConfig(config).build() } - @Nested - inner class `using the report id of a well known type` { - @ParameterizedTest - @EnumSource(DetektReportType::class) - fun `fails the build`(wellKnownType: DetektReportType) { - val config = """ - |tasks.withType().configureEach { - | reports { - | custom { - | reportId = "${wellKnownType.reportId}" - | destination = file("build/reports/custom.xml") - | } - | } - |} - """ - - gradleRunner = builder.withDetektConfig(config).build() - gradleRunner.runDetektTaskAndExpectFailure { result -> - assertThat(result.output) - .contains("The custom report reportId may not be same as one of the default reports") - } + @Test + fun `fails the build`() { + gradleRunner.runDetektTaskAndExpectFailure { result -> + assertThat(result.output).contains("Cannot write a file to a location pointing at a directory.") } } } @Nested - inner class `with flags` { - - @BeforeAll - fun beforeGroup() { + inner class `using the report id of a well known type` { + @ParameterizedTest + @EnumSource(DetektReportType::class) + fun `fails the build`(wellKnownType: DetektReportType) { val config = """ - |detekt { - | debug = true - | parallel = true - | disableDefaultRuleSets = true - | failFast = true - | allRules = true - | autoCorrect = true - | buildUponDefaultConfig = true - | ignoreFailures = true - |} + |tasks.withType().configureEach { + | reports { + | custom { + | reportId = "${wellKnownType.reportId}" + | destination = file("build/reports/custom.xml") + | } + | } + |} """ - gradleRunner = builder - .withDetektConfig(config) - .build() - result = gradleRunner.runDetektTask() + gradleRunner = builder.withDetektConfig(config).build() + gradleRunner.runDetektTaskAndExpectFailure { result -> + assertThat(result.output) + .contains("The custom report reportId may not be same as one of the default reports") + } } + } + } - @Test - fun `enables debug mode`() { - assertThat(result.output).contains("--debug") - } + @Nested + inner class `with flags` { + + @BeforeAll + fun beforeGroup() { + val config = """ + |detekt { + | debug = true + | parallel = true + | disableDefaultRuleSets = true + | failFast = true + | allRules = true + | autoCorrect = true + | buildUponDefaultConfig = true + | ignoreFailures = true + |} + """ + + gradleRunner = builder + .withDetektConfig(config) + .build() + result = gradleRunner.runDetektTask() + } - @Test - fun `enables parallel processing`() { - assertThat(result.output).contains("--parallel") - } + @Test + fun `enables debug mode`() { + assertThat(result.output).contains("--debug") + } - @Test - fun `disables default ruleset`() { - assertThat(result.output).contains("--disable-default-rulesets") - } + @Test + fun `enables parallel processing`() { + assertThat(result.output).contains("--parallel") + } - @Test - fun `ignores failures`() { - assertThat(result.output).contains("Ignore failures: true") - } + @Test + fun `disables default ruleset`() { + assertThat(result.output).contains("--disable-default-rulesets") + } - @Test - fun `enables all rules`() { - assertThat(result.output).contains("--all-rules") - } + @Test + fun `ignores failures`() { + assertThat(result.output).contains("Ignore failures: true") + } - @Test - fun `enables fail fast`() { - assertThat(result.output).contains("--fail-fast") - } + @Test + fun `enables all rules`() { + assertThat(result.output).contains("--all-rules") + } - @Test - fun `enables auto correcting`() { - assertThat(result.output).contains("--auto-correct") - } + @Test + fun `enables fail fast`() { + assertThat(result.output).contains("--fail-fast") + } - @Test - fun `enables using default config as baseline`() { - assertThat(result.output).contains("--build-upon-default-config") - } + @Test + fun `enables auto correcting`() { + assertThat(result.output).contains("--auto-correct") } - @Nested - inner class `with cmdline args` { + @Test + fun `enables using default config as baseline`() { + assertThat(result.output).contains("--build-upon-default-config") + } + } - @BeforeAll - fun beforeGroup() { - gradleRunner = builder.build() - result = gradleRunner.runDetektTask("--auto-correct") - } + @Nested + inner class `with cmdline args` { - @Test - fun `enables auto correcting`() { - assertThat(result.output).containsPattern("""Arguments:[^\r\n]*--auto-correct""") - } + @BeforeAll + fun beforeGroup() { + gradleRunner = builder.build() + result = gradleRunner.runDetektTask("--auto-correct") } - @Nested - inner class `with an additional plugin` { - @BeforeAll - fun beforeGroup() { - val config = """ - |dependencies { - | detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:$defaultDetektVersion") - |} - """ - - gradleRunner = builder - .withDetektConfig(config) - .build() - result = gradleRunner.runTasks("dependencies", "--configuration", "detektPlugins") - } + @Test + fun `enables auto correcting`() { + assertThat(result.output).containsPattern("""Arguments:[^\r\n]*--auto-correct""") + } + } - @Test - fun `successfully checks dependencies`() { - assertThat(result.task(":dependencies")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } + @Nested + inner class `with an additional plugin` { + @BeforeAll + fun beforeGroup() { + val config = """ + |dependencies { + | detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:$defaultDetektVersion") + |} + """ - @Test - fun `adds the formatting lib to the project dependencies`() { - assertThat(result.output).contains("io.gitlab.arturbosch.detekt:detekt-formatting:$defaultDetektVersion") - } + gradleRunner = builder + .withDetektConfig(config) + .build() + result = gradleRunner.runTasks("dependencies", "--configuration", "detektPlugins") } - @Nested - inner class `with a custom tool version` { - val customVersion = "1.0.0.RC8" + @Test + fun `successfully checks dependencies`() { + assertThat(result.task(":dependencies")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + } - @BeforeAll - fun beforeGroup() { - val config = """ - |detekt { - | toolVersion = "$customVersion" - |} - """ + @Test + fun `adds the formatting lib to the project dependencies`() { + assertThat(result.output).contains("io.gitlab.arturbosch.detekt:detekt-formatting:$defaultDetektVersion") + } + } - gradleRunner = builder - .withDetektConfig(config) - .build() - result = gradleRunner.runTasks("dependencies", "--offline", "--configuration", "detekt") - } + @Nested + inner class `with a custom tool version` { + val customVersion = "1.0.0.RC8" - @Test - fun `successfully checks dependencies`() { - assertThat(result.task(":dependencies")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } + @BeforeAll + fun beforeGroup() { + val config = """ + |detekt { + | toolVersion = "$customVersion" + |} + """ - @Test - fun `adds the custom detekt version to the dependencies`() { - assertThat(result.output).contains("io.gitlab.arturbosch.detekt:detekt-cli:$customVersion") - } + gradleRunner = builder + .withDetektConfig(config) + .build() + result = gradleRunner.runTasks("dependencies", "--offline", "--configuration", "detekt") } - @Nested - inner class `and creating a custom task` { - @Nested - inner class `using the kotlin dsl` { - @BeforeAll - fun beforeGroup() { - val config = """ - |task("myDetekt") { - | description = "Runs a custom detekt build." - | - | setSource(files("${"$"}projectDir")) - | setIncludes(listOf("**/*.kt", "**/*.kts")) - | setExcludes(listOf("build/")) - | config.setFrom(files("config.yml")) - | debug = true - | parallel = true - | disableDefaultRuleSets = true - | buildUponDefaultConfig = true - | failFast = false - | allRules = false - | ignoreFailures = false - | autoCorrect = false - | reports { - | xml { - | enabled = true - | destination = file("build/reports/mydetekt.xml") - | } - | html.destination = file("build/reports/mydetekt.html") - | txt.destination = file("build/reports/mydetekt.txt") - | sarif { - | enabled = true - | destination = file("build/reports/mydetekt.sarif") - | } - | } - | basePath = projectDir.toString() - |} - """ + @Test + fun `successfully checks dependencies`() { + assertThat(result.task(":dependencies")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + } - gradleRunner = builder - .withDetektConfig(config) - .build() - .apply { writeProjectFile("config.yml", "") } + @Test + fun `adds the custom detekt version to the dependencies`() { + assertThat(result.output).contains("io.gitlab.arturbosch.detekt:detekt-cli:$customVersion") + } + } - result = gradleRunner.runTasks("myDetekt") - } + @Nested + inner class `and creating a custom task` { + @BeforeAll + fun beforeGroup() { + val config = """ + |task("myDetekt") { + | description = "Runs a custom detekt build." + | + | setSource(files("${"$"}projectDir")) + | setIncludes(listOf("**/*.kt", "**/*.kts")) + | setExcludes(listOf("build/")) + | config.setFrom(files("config.yml")) + | debug = true + | parallel = true + | disableDefaultRuleSets = true + | buildUponDefaultConfig = true + | failFast = false + | allRules = false + | ignoreFailures = false + | autoCorrect = false + | reports { + | xml { + | enabled = true + | destination = file("build/reports/mydetekt.xml") + | } + | html.destination = file("build/reports/mydetekt.html") + | txt.destination = file("build/reports/mydetekt.txt") + | sarif { + | enabled = true + | destination = file("build/reports/mydetekt.sarif") + | } + | } + | basePath = projectDir.toString() + |} + """ + + gradleRunner = builder + .withDetektConfig(config) + .build() + .apply { writeProjectFile("config.yml", "") } + + result = gradleRunner.runTasks("myDetekt") + } - @Test - fun `completes successfully`() { - assertThat(result.task(":myDetekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } + @Test + fun `completes successfully`() { + assertThat(result.task(":myDetekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + } - @Test - fun `enables xml report to specified location`() { - val xmlReportFile = gradleRunner.projectFile("build/reports/mydetekt.xml") - assertThat(result.output).contains("--report xml:$xmlReportFile") - } + @Test + fun `enables xml report to specified location`() { + val xmlReportFile = gradleRunner.projectFile("build/reports/mydetekt.xml") + assertThat(result.output).contains("--report xml:$xmlReportFile") + } - @Test - fun `enables html report to specified location`() { - val htmlReportFile = gradleRunner.projectFile("build/reports/mydetekt.html") - assertThat(result.output).contains("--report html:$htmlReportFile") - } + @Test + fun `enables html report to specified location`() { + val htmlReportFile = gradleRunner.projectFile("build/reports/mydetekt.html") + assertThat(result.output).contains("--report html:$htmlReportFile") + } - @Test - fun `enables text report to specified location`() { - val textReportFile = gradleRunner.projectFile("build/reports/mydetekt.txt") - assertThat(result.output).contains("--report txt:$textReportFile") - } + @Test + fun `enables text report to specified location`() { + val textReportFile = gradleRunner.projectFile("build/reports/mydetekt.txt") + assertThat(result.output).contains("--report txt:$textReportFile") + } - @Test - fun `enables sarif report to specified location`() { - val sarifReportFile = gradleRunner.projectFile("build/reports/mydetekt.sarif") - assertThat(result.output).contains("--report sarif:$sarifReportFile") - } + @Test + fun `enables sarif report to specified location`() { + val sarifReportFile = gradleRunner.projectFile("build/reports/mydetekt.sarif") + assertThat(result.output).contains("--report sarif:$sarifReportFile") + } - @Test - fun `sets base path`() { - assertThat(result.output).contains("--base-path") - } + @Test + fun `sets base path`() { + assertThat(result.output).contains("--base-path") + } - @Test - fun `sets absolute filename of both config file to detekt cli`() { - val config = gradleRunner.projectFile("config.yml") + @Test + fun `sets absolute filename of both config file to detekt cli`() { + val config = gradleRunner.projectFile("config.yml") - val expectedConfigParam = "--config $config" - assertThat(result.output).contains(expectedConfigParam) - } + val expectedConfigParam = "--config $config" + assertThat(result.output).contains(expectedConfigParam) + } - @Test - fun `enables debug mode`() { - assertThat(result.output).contains("--debug") - } + @Test + fun `enables debug mode`() { + assertThat(result.output).contains("--debug") + } - @Test - fun `enables parallel processing`() { - assertThat(result.output).contains("--parallel") - } + @Test + fun `enables parallel processing`() { + assertThat(result.output).contains("--parallel") + } - @Test - fun `disables the default ruleset`() { - assertThat(result.output).contains("--disable-default-rulesets") - } - } + @Test + fun `disables the default ruleset`() { + assertThat(result.output).contains("--disable-default-rulesets") } } } diff --git a/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/DetektTaskMultiModuleSpec.kt b/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/DetektTaskMultiModuleSpec.kt index 5230ce3106c..c88ad928739 100644 --- a/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/DetektTaskMultiModuleSpec.kt +++ b/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/DetektTaskMultiModuleSpec.kt @@ -6,231 +6,226 @@ import io.gitlab.arturbosch.detekt.testkit.ProjectLayout import org.assertj.core.api.Assertions.assertThat import org.gradle.testkit.runner.TaskOutcome import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class DetektTaskMultiModuleSpec { - @Nested - inner class `The Detekt Gradle plugin used in a multi module project` { - - @Test - @DisplayName( - "it is applied with defaults to all subprojects individually without " + - "sources in root project using the subprojects block" - ) - fun applyToSubprojectsWithoutSources() { - val projectLayout = ProjectLayout(0).apply { - addSubmodule("child1", 2) - addSubmodule("child2", 4) + @Test + @DisplayName( + "it is applied with defaults to all subprojects individually without " + + "sources in root project using the subprojects block" + ) + fun applyToSubprojectsWithoutSources() { + val projectLayout = ProjectLayout(0).apply { + addSubmodule("child1", 2) + addSubmodule("child2", 4) + } + + val builder = DslTestBuilder.kotlin() + + val mainBuildFileContent: String = """ + |${builder.gradlePlugins} + | + |allprojects { + | ${builder.gradleRepositories} + |} + |subprojects { + | ${builder.gradleSubprojectsApplyPlugins} + |} + | + """.trimMargin() + + val gradleRunner = DslGradleRunner(projectLayout, builder.gradleBuildName, mainBuildFileContent) + + gradleRunner.setupProject() + gradleRunner.runDetektTaskAndCheckResult { result -> + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.NO_SOURCE) + projectLayout.submodules.forEach { submodule -> + assertThat(result.task(":${submodule.name}:detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) } - val builder = DslTestBuilder.kotlin() - - val mainBuildFileContent: String = """ - |${builder.gradlePlugins} - | - |allprojects { - | ${builder.gradleRepositories} - |} - |subprojects { - | ${builder.gradleSubprojectsApplyPlugins} - |} - | - """.trimMargin() - - val gradleRunner = DslGradleRunner(projectLayout, builder.gradleBuildName, mainBuildFileContent) - - gradleRunner.setupProject() - gradleRunner.runDetektTaskAndCheckResult { result -> - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.NO_SOURCE) - projectLayout.submodules.forEach { submodule -> - assertThat(result.task(":${submodule.name}:detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } - - assertThat(projectFile("build/reports/detekt/detekt.xml")).doesNotExist() - assertThat(projectFile("build/reports/detekt/detekt.html")).doesNotExist() - assertThat(projectFile("build/reports/detekt/detekt.txt")).doesNotExist() - projectLayout.submodules.forEach { - assertThat(projectFile("${it.name}/build/reports/detekt/detekt.xml")).exists() - assertThat(projectFile("${it.name}/build/reports/detekt/detekt.html")).exists() - assertThat(projectFile("${it.name}/build/reports/detekt/detekt.txt")).exists() - } + assertThat(projectFile("build/reports/detekt/detekt.xml")).doesNotExist() + assertThat(projectFile("build/reports/detekt/detekt.html")).doesNotExist() + assertThat(projectFile("build/reports/detekt/detekt.txt")).doesNotExist() + projectLayout.submodules.forEach { + assertThat(projectFile("${it.name}/build/reports/detekt/detekt.xml")).exists() + assertThat(projectFile("${it.name}/build/reports/detekt/detekt.html")).exists() + assertThat(projectFile("${it.name}/build/reports/detekt/detekt.txt")).exists() } } + } + + @Test + @DisplayName( + "it is applied with defaults to main project and subprojects " + + "individually using the allprojects block" + ) + fun applyWithAllprojectsBlock() { + val projectLayout = ProjectLayout(1).apply { + addSubmodule("child1", 2) + addSubmodule("child2", 4) + } - @Test - @DisplayName( - "it is applied with defaults to main project and subprojects " + - "individually using the allprojects block" - ) - fun applyWithAllprojectsBlock() { - val projectLayout = ProjectLayout(1).apply { - addSubmodule("child1", 2) - addSubmodule("child2", 4) + val builder = DslTestBuilder.kotlin() + + val mainBuildFileContent: String = """ + |${builder.gradlePlugins} + | + |allprojects { + | ${builder.gradleRepositories} + | ${builder.gradleSubprojectsApplyPlugins} + |} + | + """.trimMargin() + + val gradleRunner = DslGradleRunner(projectLayout, builder.gradleBuildName, mainBuildFileContent) + + gradleRunner.setupProject() + gradleRunner.runDetektTaskAndCheckResult { result -> + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + projectLayout.submodules.forEach { submodule -> + assertThat(result.task(":${submodule.name}:detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) } - val builder = DslTestBuilder.kotlin() - - val mainBuildFileContent: String = """ - |${builder.gradlePlugins} - | - |allprojects { - | ${builder.gradleRepositories} - | ${builder.gradleSubprojectsApplyPlugins} - |} - | - """.trimMargin() - - val gradleRunner = DslGradleRunner(projectLayout, builder.gradleBuildName, mainBuildFileContent) - - gradleRunner.setupProject() - gradleRunner.runDetektTaskAndCheckResult { result -> - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - projectLayout.submodules.forEach { submodule -> - assertThat(result.task(":${submodule.name}:detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } - - assertThat(projectFile("build/reports/detekt/detekt.xml")).exists() - assertThat(projectFile("build/reports/detekt/detekt.html")).exists() - assertThat(projectFile("build/reports/detekt/detekt.txt")).exists() - projectLayout.submodules.forEach { - assertThat(projectFile("${it.name}/build/reports/detekt/detekt.xml")).exists() - assertThat(projectFile("${it.name}/build/reports/detekt/detekt.html")).exists() - assertThat(projectFile("${it.name}/build/reports/detekt/detekt.txt")).exists() - } + assertThat(projectFile("build/reports/detekt/detekt.xml")).exists() + assertThat(projectFile("build/reports/detekt/detekt.html")).exists() + assertThat(projectFile("build/reports/detekt/detekt.txt")).exists() + projectLayout.submodules.forEach { + assertThat(projectFile("${it.name}/build/reports/detekt/detekt.xml")).exists() + assertThat(projectFile("${it.name}/build/reports/detekt/detekt.html")).exists() + assertThat(projectFile("${it.name}/build/reports/detekt/detekt.txt")).exists() } } + } + + @Test + fun `it uses custom configs when configured in allprojects block`() { + val projectLayout = ProjectLayout(1).apply { + addSubmodule("child1", 2) + addSubmodule("child2", 4) + } - @Test - fun `it uses custom configs when configured in allprojects block`() { - val projectLayout = ProjectLayout(1).apply { - addSubmodule("child1", 2) - addSubmodule("child2", 4) + val builder = DslTestBuilder.kotlin() + + val mainBuildFileContent: String = """ + |${builder.gradlePlugins} + | + |allprojects { + | ${builder.gradleRepositories} + | ${builder.gradleSubprojectsApplyPlugins} + | + | detekt { + | reportsDir = file("build/detekt-reports") + | } + |} + | + """.trimMargin() + + val gradleRunner = DslGradleRunner(projectLayout, builder.gradleBuildName, mainBuildFileContent) + gradleRunner.setupProject() + gradleRunner.runDetektTaskAndCheckResult { result -> + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + projectLayout.submodules.forEach { submodule -> + assertThat(result.task(":${submodule.name}:detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) } - val builder = DslTestBuilder.kotlin() - - val mainBuildFileContent: String = """ - |${builder.gradlePlugins} - | - |allprojects { - | ${builder.gradleRepositories} - | ${builder.gradleSubprojectsApplyPlugins} - | - | detekt { - | reportsDir = file("build/detekt-reports") - | } - |} - | - """.trimMargin() - - val gradleRunner = DslGradleRunner(projectLayout, builder.gradleBuildName, mainBuildFileContent) - gradleRunner.setupProject() - gradleRunner.runDetektTaskAndCheckResult { result -> - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - projectLayout.submodules.forEach { submodule -> - assertThat(result.task(":${submodule.name}:detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } - - assertThat(projectFile("build/detekt-reports/detekt.xml")).exists() - assertThat(projectFile("build/detekt-reports/detekt.html")).exists() - assertThat(projectFile("build/detekt-reports/detekt.txt")).exists() - projectLayout.submodules.forEach { - assertThat(projectFile("${it.name}/build/detekt-reports/detekt.xml")).exists() - assertThat(projectFile("${it.name}/build/detekt-reports/detekt.html")).exists() - assertThat(projectFile("${it.name}/build/detekt-reports/detekt.txt")).exists() - } + assertThat(projectFile("build/detekt-reports/detekt.xml")).exists() + assertThat(projectFile("build/detekt-reports/detekt.html")).exists() + assertThat(projectFile("build/detekt-reports/detekt.txt")).exists() + projectLayout.submodules.forEach { + assertThat(projectFile("${it.name}/build/detekt-reports/detekt.xml")).exists() + assertThat(projectFile("${it.name}/build/detekt-reports/detekt.html")).exists() + assertThat(projectFile("${it.name}/build/detekt-reports/detekt.txt")).exists() } } + } - @Test - @DisplayName("it allows changing defaults in allprojects block that can be overwritten in subprojects") - fun allowsChangingDefaultsInAllProjectsThatAreOverwrittenInSubprojects() { - val child2DetektConfig = """ - |detekt { - | reportsDir = file("build/custom") - |} - | - """.trimMargin() - - val projectLayout = ProjectLayout(1).apply { - addSubmodule("child1", 2) - addSubmodule("child2", 4, buildFileContent = child2DetektConfig) - } + @Test + @DisplayName("it allows changing defaults in allprojects block that can be overwritten in subprojects") + fun allowsChangingDefaultsInAllProjectsThatAreOverwrittenInSubprojects() { + val child2DetektConfig = """ + |detekt { + | reportsDir = file("build/custom") + |} + | + """.trimMargin() + + val projectLayout = ProjectLayout(1).apply { + addSubmodule("child1", 2) + addSubmodule("child2", 4, buildFileContent = child2DetektConfig) + } - val builder = DslTestBuilder.kotlin() - - val mainBuildFileContent: String = """ - |${builder.gradlePlugins} - | - |allprojects { - | ${builder.gradleRepositories} - | ${builder.gradleSubprojectsApplyPlugins} - | - | detekt { - | reportsDir = file("build/detekt-reports") - | } - |} - | - """.trimMargin() - - val gradleRunner = DslGradleRunner(projectLayout, builder.gradleBuildName, mainBuildFileContent) - - gradleRunner.setupProject() - gradleRunner.runDetektTaskAndCheckResult { result -> - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - projectLayout.submodules.forEach { submodule -> - assertThat(result.task(":${submodule.name}:detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } - - assertThat(projectFile("build/detekt-reports/detekt.xml")).exists() - assertThat(projectFile("build/detekt-reports/detekt.html")).exists() - assertThat(projectFile("build/detekt-reports/detekt.txt")).exists() - assertThat(projectFile("child1/build/detekt-reports/detekt.xml")).exists() - assertThat(projectFile("child1/build/detekt-reports/detekt.html")).exists() - assertThat(projectFile("child1/build/detekt-reports/detekt.txt")).exists() - assertThat(projectFile("child2/build/custom/detekt.xml")).exists() - assertThat(projectFile("child2/build/custom/detekt.html")).exists() - assertThat(projectFile("child2/build/custom/detekt.txt")).exists() + val builder = DslTestBuilder.kotlin() + + val mainBuildFileContent: String = """ + |${builder.gradlePlugins} + | + |allprojects { + | ${builder.gradleRepositories} + | ${builder.gradleSubprojectsApplyPlugins} + | + | detekt { + | reportsDir = file("build/detekt-reports") + | } + |} + | + """.trimMargin() + + val gradleRunner = DslGradleRunner(projectLayout, builder.gradleBuildName, mainBuildFileContent) + + gradleRunner.setupProject() + gradleRunner.runDetektTaskAndCheckResult { result -> + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + projectLayout.submodules.forEach { submodule -> + assertThat(result.task(":${submodule.name}:detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) } + + assertThat(projectFile("build/detekt-reports/detekt.xml")).exists() + assertThat(projectFile("build/detekt-reports/detekt.html")).exists() + assertThat(projectFile("build/detekt-reports/detekt.txt")).exists() + assertThat(projectFile("child1/build/detekt-reports/detekt.xml")).exists() + assertThat(projectFile("child1/build/detekt-reports/detekt.html")).exists() + assertThat(projectFile("child1/build/detekt-reports/detekt.txt")).exists() + assertThat(projectFile("child2/build/custom/detekt.xml")).exists() + assertThat(projectFile("child2/build/custom/detekt.html")).exists() + assertThat(projectFile("child2/build/custom/detekt.txt")).exists() + } + } + + @Test + fun `it can be applied to all files in entire project resulting in 1 report`() { + val projectLayout = ProjectLayout(1).apply { + addSubmodule("child1", 2) + addSubmodule("child2", 4) } - @Test - fun `it can be applied to all files in entire project resulting in 1 report`() { - val projectLayout = ProjectLayout(1).apply { - addSubmodule("child1", 2) - addSubmodule("child2", 4) + val detektConfig: String = """ + |detekt { + | source = files( + | "${"$"}projectDir/src", + | "${"$"}projectDir/child1/src", + | "${"$"}projectDir/child2/src" + | ) + |} + """.trimMargin() + val gradleRunner = DslTestBuilder.kotlin() + .withProjectLayout(projectLayout) + .withDetektConfig(detektConfig) + .build() + + gradleRunner.runDetektTaskAndCheckResult { result -> + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + projectLayout.submodules.forEach { submodule -> + assertThat(result.task(":${submodule.name}:detekt")).isNull() } - val detektConfig: String = """ - |detekt { - | source = files( - | "${"$"}projectDir/src", - | "${"$"}projectDir/child1/src", - | "${"$"}projectDir/child2/src" - | ) - |} - """.trimMargin() - val gradleRunner = DslTestBuilder.kotlin() - .withProjectLayout(projectLayout) - .withDetektConfig(detektConfig) - .build() - - gradleRunner.runDetektTaskAndCheckResult { result -> - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - projectLayout.submodules.forEach { submodule -> - assertThat(result.task(":${submodule.name}:detekt")).isNull() - } - - assertThat(projectFile("build/reports/detekt/detekt.xml")).exists() - assertThat(projectFile("build/reports/detekt/detekt.html")).exists() - assertThat(projectFile("build/reports/detekt/detekt.txt")).exists() - projectLayout.submodules.forEach { submodule -> - assertThat(projectFile("${submodule.name}/build/reports/detekt/detekt.xml")).doesNotExist() - assertThat(projectFile("${submodule.name}/build/reports/detekt/detekt.html")).doesNotExist() - assertThat(projectFile("${submodule.name}/build/reports/detekt/detekt.txt")).doesNotExist() - } + assertThat(projectFile("build/reports/detekt/detekt.xml")).exists() + assertThat(projectFile("build/reports/detekt/detekt.html")).exists() + assertThat(projectFile("build/reports/detekt/detekt.txt")).exists() + projectLayout.submodules.forEach { submodule -> + assertThat(projectFile("${submodule.name}/build/reports/detekt/detekt.xml")).doesNotExist() + assertThat(projectFile("${submodule.name}/build/reports/detekt/detekt.html")).doesNotExist() + assertThat(projectFile("${submodule.name}/build/reports/detekt/detekt.txt")).doesNotExist() } } } diff --git a/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/PluginTaskBehaviorSpec.kt b/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/PluginTaskBehaviorSpec.kt index 060e625fb9d..666768777d4 100644 --- a/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/PluginTaskBehaviorSpec.kt +++ b/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/PluginTaskBehaviorSpec.kt @@ -5,7 +5,6 @@ import io.gitlab.arturbosch.detekt.testkit.DslTestBuilder.Companion.kotlin import org.assertj.core.api.Assertions.assertThat import org.gradle.testkit.runner.TaskOutcome import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test /** @@ -24,106 +23,103 @@ class PluginTaskBehaviorSpec { |} """ - @Nested - inner class `The Detekt Gradle Plugin 'detekt' Task` { - lateinit var gradleRunner: DslGradleRunner - - @BeforeEach - fun setupGradleRunner() { - gradleRunner = kotlin() - .withDetektConfig(detektConfig) - .withBaseline(baselineFileName) - .withConfigFile(configFileName) - .build() - } + lateinit var gradleRunner: DslGradleRunner + + @BeforeEach + fun setupGradleRunner() { + gradleRunner = kotlin() + .withDetektConfig(detektConfig) + .withBaseline(baselineFileName) + .withConfigFile(configFileName) + .build() + } - @Test - fun `should be UP-TO-DATE the 2nd run without changes`() { - gradleRunner.runDetektTaskAndCheckResult { result -> - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } - gradleRunner.runDetektTaskAndCheckResult { result -> - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.UP_TO_DATE) - } + @Test + fun `should be UP-TO-DATE the 2nd run without changes`() { + gradleRunner.runDetektTaskAndCheckResult { result -> + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + } + gradleRunner.runDetektTaskAndCheckResult { result -> + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.UP_TO_DATE) } + } - @Test - fun `should pick up build artifacts from the build cache on a 2nd run after deleting the build dir`() { - gradleRunner.runDetektTaskAndCheckResult { result -> - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } + @Test + fun `should pick up build artifacts from the build cache on a 2nd run after deleting the build dir`() { + gradleRunner.runDetektTaskAndCheckResult { result -> + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + } - gradleRunner.projectFile("build").deleteRecursively() + gradleRunner.projectFile("build").deleteRecursively() - // Running detekt again should pick up artifacts from Build Cache - gradleRunner.runDetektTaskAndCheckResult { result -> - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.FROM_CACHE) - } + // Running detekt again should pick up artifacts from Build Cache + gradleRunner.runDetektTaskAndCheckResult { result -> + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.FROM_CACHE) } + } - @Test - fun `should pick up build artifacts from the build cache on a 2nd run after running 'clean'`() { - gradleRunner.runDetektTaskAndCheckResult { result -> - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } - gradleRunner.runTasksAndCheckResult("clean", "detekt") { result -> - assertThat(result.task(":clean")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.FROM_CACHE) - } + @Test + fun `should pick up build artifacts from the build cache on a 2nd run after running 'clean'`() { + gradleRunner.runDetektTaskAndCheckResult { result -> + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + } + gradleRunner.runTasksAndCheckResult("clean", "detekt") { result -> + assertThat(result.task(":clean")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.FROM_CACHE) } + } + + @Test + fun `should run again after changing config`() { + val configFileWithCommentsDisabled = """ + |comments: + | active: false + """.trimMargin() - @Test - fun `should run again after changing config`() { - val configFileWithCommentsDisabled = """ - |comments: - | active: false - """.trimMargin() + gradleRunner.runDetektTaskAndCheckResult { result -> + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + } - gradleRunner.runDetektTaskAndCheckResult { result -> - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } + // update config file + gradleRunner.writeProjectFile(configFileName, configFileWithCommentsDisabled) - // update config file - gradleRunner.writeProjectFile(configFileName, configFileWithCommentsDisabled) + gradleRunner.runTasksAndCheckResult("detekt") { result -> + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + } + } - gradleRunner.runTasksAndCheckResult("detekt") { result -> - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } + @Test + fun `should run again after changing baseline`() { + val changedBaselineContent = """ + | + | + | + | + """.trimMargin() + + gradleRunner.runDetektTaskAndCheckResult { result -> + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) } - @Test - fun `should run again after changing baseline`() { - val changedBaselineContent = """ - | - | - | - | - """.trimMargin() - - gradleRunner.runDetektTaskAndCheckResult { result -> - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } - - // update baseline file - gradleRunner.writeProjectFile(baselineFileName, changedBaselineContent) - - gradleRunner.runTasksAndCheckResult("detekt") { result -> - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } + // update baseline file + gradleRunner.writeProjectFile(baselineFileName, changedBaselineContent) + + gradleRunner.runTasksAndCheckResult("detekt") { result -> + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) } + } - @Test - fun `should run again after changing inputs`() { - gradleRunner.runDetektTaskAndCheckResult { result -> - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } + @Test + fun `should run again after changing inputs`() { + gradleRunner.runDetektTaskAndCheckResult { result -> + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + } - // add a new File - gradleRunner.writeKtFile(gradleRunner.projectLayout.srcDirs.first(), "OtherKotlinClass") + // add a new File + gradleRunner.writeKtFile(gradleRunner.projectLayout.srcDirs.first(), "OtherKotlinClass") - gradleRunner.runTasksAndCheckResult("detekt") { result -> - assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } + gradleRunner.runTasksAndCheckResult("detekt") { result -> + assertThat(result.task(":detekt")?.outcome).isEqualTo(TaskOutcome.SUCCESS) } } } diff --git a/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/report/ReportMergeSpec.kt b/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/report/ReportMergeSpec.kt index ab72c2406ad..00b1d586272 100644 --- a/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/report/ReportMergeSpec.kt +++ b/detekt-gradle-plugin/src/functionalTest/kotlin/io/gitlab/arturbosch/detekt/report/ReportMergeSpec.kt @@ -6,7 +6,6 @@ import io.gitlab.arturbosch.detekt.testkit.DslTestBuilder import io.gitlab.arturbosch.detekt.testkit.ProjectLayout import org.assertj.core.api.Assertions.assertThat import org.gradle.testkit.runner.TaskOutcome -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import org.junit.jupiter.api.condition.EnabledForJreRange import org.junit.jupiter.api.condition.EnabledIf @@ -14,187 +13,183 @@ import org.junit.jupiter.api.condition.JRE.JAVA_11 class ReportMergeSpec { - @Nested - inner class `Merging reports in a multi module projects` { - - @Suppress("LongMethod") - @Test - fun `for jvm detekt`() { - val builder = DslTestBuilder.kotlin() - val projectLayout = ProjectLayout(0).apply { - addSubmodule( - "child1", - numberOfSourceFilesPerSourceDir = 2, - buildFileContent = """ - ${builder.gradleSubprojectsApplyPlugins} - |plugins.apply("java-library") - """.trimMargin() - ) - addSubmodule( - "child2", - numberOfSourceFilesPerSourceDir = 2, - buildFileContent = """ - ${builder.gradleSubprojectsApplyPlugins} - |plugins.apply("java-library") - """.trimMargin() - ) - } - val mainBuildFileContent: String = """ - |plugins { - | id("io.gitlab.arturbosch.detekt") - |} - | - |allprojects { - | ${builder.gradleRepositories} - |} - | - |val reportMerge by tasks.registering(io.gitlab.arturbosch.detekt.report.ReportMergeTask::class) { - | output.set(project.layout.buildDirectory.file("reports/detekt/merge.xml")) - | outputs.cacheIf { false } - | outputs.upToDateWhen { false } - |} - | - |subprojects { - | apply(plugin = "org.jetbrains.kotlin.jvm") - | apply(plugin = "io.gitlab.arturbosch.detekt") - | - | detekt { - | reports.xml.enabled = true - | } - | - | plugins.withType { - | tasks.withType().configureEach { - | finalizedBy(reportMerge) - | reportMerge.configure { input.from(xmlReportFile) } - | } - | } - |} - """.trimMargin() - - val gradleRunner = DslGradleRunner( - projectLayout = projectLayout, - buildFileName = builder.gradleBuildName, - mainBuildFileContent = mainBuildFileContent + @Suppress("LongMethod") + @Test + fun `for jvm detekt`() { + val builder = DslTestBuilder.kotlin() + val projectLayout = ProjectLayout(0).apply { + addSubmodule( + "child1", + numberOfSourceFilesPerSourceDir = 2, + buildFileContent = """ + ${builder.gradleSubprojectsApplyPlugins} + |plugins.apply("java-library") + """.trimMargin() ) + addSubmodule( + "child2", + numberOfSourceFilesPerSourceDir = 2, + buildFileContent = """ + ${builder.gradleSubprojectsApplyPlugins} + |plugins.apply("java-library") + """.trimMargin() + ) + } + val mainBuildFileContent: String = """ + |plugins { + | id("io.gitlab.arturbosch.detekt") + |} + | + |allprojects { + | ${builder.gradleRepositories} + |} + | + |val reportMerge by tasks.registering(io.gitlab.arturbosch.detekt.report.ReportMergeTask::class) { + | output.set(project.layout.buildDirectory.file("reports/detekt/merge.xml")) + | outputs.cacheIf { false } + | outputs.upToDateWhen { false } + |} + | + |subprojects { + | apply(plugin = "org.jetbrains.kotlin.jvm") + | apply(plugin = "io.gitlab.arturbosch.detekt") + | + | detekt { + | reports.xml.enabled = true + | } + | + | plugins.withType { + | tasks.withType().configureEach { + | finalizedBy(reportMerge) + | reportMerge.configure { input.from(xmlReportFile) } + | } + | } + |} + """.trimMargin() - gradleRunner.setupProject() - gradleRunner.runTasksAndCheckResult("detektMain", "reportMerge", "--continue") { result -> - projectLayout.submodules.forEach { submodule -> - assertThat(result.task(":${submodule.name}:detektMain")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } - - projectLayout.submodules.forEach { - assertThat(projectFile("${it.name}/build/reports/detekt/main.xml")).exists() - } + val gradleRunner = DslGradleRunner( + projectLayout = projectLayout, + buildFileName = builder.gradleBuildName, + mainBuildFileContent = mainBuildFileContent + ) - assertThat(projectFile("build/reports/detekt/merge.xml")).exists() + gradleRunner.setupProject() + gradleRunner.runTasksAndCheckResult("detektMain", "reportMerge", "--continue") { result -> + projectLayout.submodules.forEach { submodule -> + assertThat(result.task(":${submodule.name}:detektMain")?.outcome).isEqualTo(TaskOutcome.SUCCESS) } - } - @Suppress("LongMethod") - @Test - @EnabledForJreRange(min = JAVA_11, disabledReason = "Android Gradle Plugin 7.0+ requires JDK 11 or newer") - @EnabledIf("io.gitlab.arturbosch.detekt.DetektAndroidSpecKt#isAndroidSdkInstalled") - fun `for android detekt`() { - val builder = DslTestBuilder.kotlin() - val projectLayout = ProjectLayout(0).apply { - addSubmodule( - name = "app", - numberOfSourceFilesPerSourceDir = 1, - buildFileContent = """ - plugins { - id("com.android.application") - kotlin("android") - id("io.gitlab.arturbosch.detekt") - } - android { - compileSdkVersion(30) - } - dependencies { - implementation(project(":lib")) - } - """.trimIndent(), - srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java"), - ) - addSubmodule( - name = "lib", - numberOfSourceFilesPerSourceDir = 1, - buildFileContent = """ - plugins { - id("com.android.library") - kotlin("android") - } - android { - compileSdkVersion(30) - } - """.trimIndent(), - srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java") - ) + projectLayout.submodules.forEach { + assertThat(projectFile("${it.name}/build/reports/detekt/main.xml")).exists() } - val mainBuildFileContent: String = """ - |plugins { - | id("io.gitlab.arturbosch.detekt") - |} - | - |allprojects { - | repositories { - | mavenCentral() - | google() - | mavenLocal() - | } - |} - | - |val reportMerge by tasks.registering(io.gitlab.arturbosch.detekt.report.ReportMergeTask::class) { - | output.set(project.layout.buildDirectory.file("reports/detekt/merge.xml")) - | outputs.cacheIf { false } - | outputs.upToDateWhen { false } - |} - | - |subprojects { - | apply(plugin = "io.gitlab.arturbosch.detekt") - | - | detekt { - | reports.xml.enabled = true - | } - | - | plugins.withType { - | tasks.withType().configureEach { - | finalizedBy(reportMerge) - | reportMerge.configure { input.from(xmlReportFile) } - | } - | } - |} - """.trimMargin() - - val jvmArgs = "-Xmx2g -XX:MaxMetaspaceSize=1g" - val gradleRunner = DslGradleRunner( - projectLayout = projectLayout, - buildFileName = builder.gradleBuildName, - mainBuildFileContent = mainBuildFileContent, - jvmArgs = jvmArgs - ) + assertThat(projectFile("build/reports/detekt/merge.xml")).exists() + } + } - gradleRunner.setupProject() - gradleRunner.writeProjectFile( - "app/src/main/AndroidManifest.xml", - manifestContent("io.github.detekt.app") + @Suppress("LongMethod") + @Test + @EnabledForJreRange(min = JAVA_11, disabledReason = "Android Gradle Plugin 7.0+ requires JDK 11 or newer") + @EnabledIf("io.gitlab.arturbosch.detekt.DetektAndroidSpecKt#isAndroidSdkInstalled") + fun `for android detekt`() { + val builder = DslTestBuilder.kotlin() + val projectLayout = ProjectLayout(0).apply { + addSubmodule( + name = "app", + numberOfSourceFilesPerSourceDir = 1, + buildFileContent = """ + plugins { + id("com.android.application") + kotlin("android") + id("io.gitlab.arturbosch.detekt") + } + android { + compileSdkVersion(30) + } + dependencies { + implementation(project(":lib")) + } + """.trimIndent(), + srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java"), ) - gradleRunner.writeProjectFile( - "lib/src/main/AndroidManifest.xml", - manifestContent("io.github.detekt.lib") + addSubmodule( + name = "lib", + numberOfSourceFilesPerSourceDir = 1, + buildFileContent = """ + plugins { + id("com.android.library") + kotlin("android") + } + android { + compileSdkVersion(30) + } + """.trimIndent(), + srcDirs = listOf("src/main/java", "src/debug/java", "src/test/java", "src/androidTest/java") ) - gradleRunner.runTasksAndCheckResult("detektMain", "reportMerge", "--continue") { result -> - projectLayout.submodules.forEach { submodule -> - assertThat(result.task(":${submodule.name}:detektMain")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - } + } + val mainBuildFileContent: String = """ + |plugins { + | id("io.gitlab.arturbosch.detekt") + |} + | + |allprojects { + | repositories { + | mavenCentral() + | google() + | mavenLocal() + | } + |} + | + |val reportMerge by tasks.registering(io.gitlab.arturbosch.detekt.report.ReportMergeTask::class) { + | output.set(project.layout.buildDirectory.file("reports/detekt/merge.xml")) + | outputs.cacheIf { false } + | outputs.upToDateWhen { false } + |} + | + |subprojects { + | apply(plugin = "io.gitlab.arturbosch.detekt") + | + | detekt { + | reports.xml.enabled = true + | } + | + | plugins.withType { + | tasks.withType().configureEach { + | finalizedBy(reportMerge) + | reportMerge.configure { input.from(xmlReportFile) } + | } + | } + |} + """.trimMargin() + + val jvmArgs = "-Xmx2g -XX:MaxMetaspaceSize=1g" + + val gradleRunner = DslGradleRunner( + projectLayout = projectLayout, + buildFileName = builder.gradleBuildName, + mainBuildFileContent = mainBuildFileContent, + jvmArgs = jvmArgs + ) + + gradleRunner.setupProject() + gradleRunner.writeProjectFile( + "app/src/main/AndroidManifest.xml", + manifestContent("io.github.detekt.app") + ) + gradleRunner.writeProjectFile( + "lib/src/main/AndroidManifest.xml", + manifestContent("io.github.detekt.lib") + ) + gradleRunner.runTasksAndCheckResult("detektMain", "reportMerge", "--continue") { result -> + projectLayout.submodules.forEach { submodule -> + assertThat(result.task(":${submodule.name}:detektMain")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + } - projectLayout.submodules.forEach { - assertThat(projectFile("${it.name}/build/reports/detekt/debug.xml")).exists() - } - // #4192 this should exist by default - assertThat(projectFile("build/reports/detekt/merge.xml")).doesNotExist() + projectLayout.submodules.forEach { + assertThat(projectFile("${it.name}/build/reports/detekt/debug.xml")).exists() } + // #4192 this should exist by default + assertThat(projectFile("build/reports/detekt/merge.xml")).doesNotExist() } } } diff --git a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektJvmSpec.kt b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektJvmSpec.kt index 394454dbc11..f38eb9f1510 100644 --- a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektJvmSpec.kt +++ b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/DetektJvmSpec.kt @@ -6,62 +6,54 @@ import org.assertj.core.api.Assertions.assertThat import org.gradle.kotlin.dsl.apply import org.gradle.kotlin.dsl.repositories import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class DetektJvmSpec { - @Nested - inner class `When applying detekt in a JVM project` { - @Nested - inner class `disabled TXT report` { - - val gradleRunner = DslGradleRunner( - projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 1), - buildFileName = "build.gradle.kts", - baselineFiles = listOf("detekt-baseline.xml", "detekt-baseline-main.xml", "detekt-baseline-test.xml"), - projectScript = { - apply() - apply() - repositories { - mavenCentral() - mavenLocal() - } - tasks.withType(Detekt::class.java).configureEach { - it.reports { reports -> - reports.txt.required.set(false) - } - } - }, - ).also(DslGradleRunner::setupProject) + val gradleRunner = DslGradleRunner( + projectLayout = ProjectLayout(numberOfSourceFilesInRootPerSourceDir = 1), + buildFileName = "build.gradle.kts", + baselineFiles = listOf("detekt-baseline.xml", "detekt-baseline-main.xml", "detekt-baseline-test.xml"), + projectScript = { + apply() + apply() + repositories { + mavenCentral() + mavenLocal() + } + tasks.withType(Detekt::class.java).configureEach { + it.reports { reports -> + reports.txt.required.set(false) + } + } + }, + ).also(DslGradleRunner::setupProject) - @Test - fun `configures detekt type resolution task main`() { - val project = gradleRunner.buildProject() + @Test + fun `configures detekt type resolution task main`() { + val project = gradleRunner.buildProject() - val detektTask = project.tasks.getByPath("detektMain") as Detekt - val argumentString = detektTask.arguments.get().joinToString(" ") + val detektTask = project.tasks.getByPath("detektMain") as Detekt + val argumentString = detektTask.arguments.get().joinToString(" ") - assertThat(argumentString).containsPattern("""--baseline \S*[/\\]detekt-baseline-main.xml """) - assertThat(argumentString).contains("--report xml:") - assertThat(argumentString).contains("--report sarif:") - assertThat(argumentString).doesNotContain("--report txt:") - assertThat(argumentString).contains("--classpath") - } + assertThat(argumentString).containsPattern("""--baseline \S*[/\\]detekt-baseline-main.xml """) + assertThat(argumentString).contains("--report xml:") + assertThat(argumentString).contains("--report sarif:") + assertThat(argumentString).doesNotContain("--report txt:") + assertThat(argumentString).contains("--classpath") + } - @Test - fun `configures detekt type resolution task test`() { - val project = gradleRunner.buildProject() + @Test + fun `configures detekt type resolution task test`() { + val project = gradleRunner.buildProject() - val detektTask = project.tasks.getByPath("detektTest") as Detekt - val argumentString = detektTask.arguments.get().joinToString(" ") + val detektTask = project.tasks.getByPath("detektTest") as Detekt + val argumentString = detektTask.arguments.get().joinToString(" ") - assertThat(argumentString).containsPattern("""--baseline \S*[/\\]detekt-baseline-test.xml """) - assertThat(argumentString).contains("--report xml:") - assertThat(argumentString).contains("--report sarif:") - assertThat(argumentString).doesNotContain("--report txt:") - assertThat(argumentString).contains("--classpath") - } - } + assertThat(argumentString).containsPattern("""--baseline \S*[/\\]detekt-baseline-test.xml """) + assertThat(argumentString).contains("--report xml:") + assertThat(argumentString).contains("--report sarif:") + assertThat(argumentString).doesNotContain("--report txt:") + assertThat(argumentString).contains("--classpath") } } diff --git a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/internal/ClassLoaderCacheSpec.kt b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/internal/ClassLoaderCacheSpec.kt index ff84d211bdb..46e56b037db 100644 --- a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/internal/ClassLoaderCacheSpec.kt +++ b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/internal/ClassLoaderCacheSpec.kt @@ -3,7 +3,6 @@ package io.gitlab.arturbosch.detekt.internal import io.gitlab.arturbosch.detekt.gradle.TestFileCollection import org.assertj.core.api.Assertions.assertThat import org.gradle.api.internal.file.AbstractFileCollection -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import java.io.File import java.util.concurrent.CompletableFuture @@ -14,66 +13,62 @@ import java.util.function.Supplier class ClassLoaderCacheSpec { - @Nested - inner class ClasspathChanges { + @Test + fun `same classloader is returned for the same files`() { + val cache = DefaultClassLoaderCache() + val initialClassLoader = cache.getOrCreate(TestFileCollection(File("a/b/c"))) + val secondClassLoader = cache.getOrCreate(TestFileCollection(File("a/b/c"))) - @Test - fun `same classloader is returned for the same files`() { - val cache = DefaultClassLoaderCache() - val initialClassLoader = cache.getOrCreate(TestFileCollection(File("a/b/c"))) - val secondClassLoader = cache.getOrCreate(TestFileCollection(File("a/b/c"))) - - assertThat(initialClassLoader === secondClassLoader).isTrue() - } - - @Test - fun `different classloaders are returned for different files`() { - val cache = DefaultClassLoaderCache() - val firstClassLoader = cache.getOrCreate(TestFileCollection(File("a/b/c"))) - val secondClassLoader = cache.getOrCreate(TestFileCollection(File("c/b/a"))) - - assertThat(firstClassLoader === secondClassLoader).isFalse() - } + assertThat(initialClassLoader === secondClassLoader).isTrue() + } - @Test - fun `same classloader for the same files in different order`() { - val cache = DefaultClassLoaderCache() - val firstClassLoader = cache.getOrCreate(TestFileCollection(File("a/b/c"), File("d/e/f"))) - val secondClassLoader = cache.getOrCreate(TestFileCollection(File("d/e/f"), File("a/b/c"))) + @Test + fun `different classloaders are returned for different files`() { + val cache = DefaultClassLoaderCache() + val firstClassLoader = cache.getOrCreate(TestFileCollection(File("a/b/c"))) + val secondClassLoader = cache.getOrCreate(TestFileCollection(File("c/b/a"))) - assertThat(firstClassLoader === secondClassLoader).isTrue() - } + assertThat(firstClassLoader === secondClassLoader).isFalse() + } - @Test - fun `resolves files without synchronization`() { - val file1 = File("/a/b/c") - val collection1 = CountdownFileCollection(file1) + @Test + fun `same classloader for the same files in different order`() { + val cache = DefaultClassLoaderCache() + val firstClassLoader = cache.getOrCreate(TestFileCollection(File("a/b/c"), File("d/e/f"))) + val secondClassLoader = cache.getOrCreate(TestFileCollection(File("d/e/f"), File("a/b/c"))) - val file2 = File("/c/b/a") - val collection2 = TestFileCollection(file2) + assertThat(firstClassLoader === secondClassLoader).isTrue() + } - val cache = DefaultClassLoaderCache() - val executor = Executors.newSingleThreadExecutor() - val latch = CountDownLatch(1) - try { - val supplier = Supplier { - latch.countDown() - cache.getOrCreate(collection1) - } - val task = CompletableFuture.supplyAsync(supplier, executor) - @Suppress("UsePropertyAccessSyntax") - assertThat(latch.await(10L, TimeUnit.SECONDS)).isTrue() - // Will call `getOrCreate` next - wait a moment to be sure - Thread.sleep(2000L) - val classpath2 = cache.getOrCreate(collection2) - collection1.latch.countDown() - val classpath1 = task.join() - assertThat(classpath1.urLs).isEqualTo(arrayOf(file1.toURI().toURL())) - assertThat(classpath2.urLs).isEqualTo(arrayOf(file2.toURI().toURL())) - } finally { - val remaining = executor.shutdownNow() - assertThat(remaining).isEmpty() + @Test + fun `resolves files without synchronization`() { + val file1 = File("/a/b/c") + val collection1 = CountdownFileCollection(file1) + + val file2 = File("/c/b/a") + val collection2 = TestFileCollection(file2) + + val cache = DefaultClassLoaderCache() + val executor = Executors.newSingleThreadExecutor() + val latch = CountDownLatch(1) + try { + val supplier = Supplier { + latch.countDown() + cache.getOrCreate(collection1) } + val task = CompletableFuture.supplyAsync(supplier, executor) + @Suppress("UsePropertyAccessSyntax") + assertThat(latch.await(10L, TimeUnit.SECONDS)).isTrue() + // Will call `getOrCreate` next - wait a moment to be sure + Thread.sleep(2000L) + val classpath2 = cache.getOrCreate(collection2) + collection1.latch.countDown() + val classpath1 = task.join() + assertThat(classpath1.urLs).isEqualTo(arrayOf(file1.toURI().toURL())) + assertThat(classpath2.urLs).isEqualTo(arrayOf(file2.toURI().toURL())) + } finally { + val remaining = executor.shutdownNow() + assertThat(remaining).isEmpty() } } } diff --git a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/report/XmlReportMergerSpec.kt b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/report/XmlReportMergerSpec.kt index c12def8e5bc..6a22dea2bfc 100644 --- a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/report/XmlReportMergerSpec.kt +++ b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/report/XmlReportMergerSpec.kt @@ -1,7 +1,6 @@ package io.gitlab.arturbosch.detekt.report import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import java.io.File @@ -9,49 +8,45 @@ private const val TAB = "\t" class XmlReportMergerSpec { - @Nested - inner class `classpath changes` { - - @Test - fun `passes for same files`() { - val file1 = File.createTempFile("detekt1", "xml").apply { - writeText( - """ - - - - $TAB - - - """.trimIndent() - ) - } - val file2 = File.createTempFile("detekt2", "xml").apply { - writeText( - """ - - - - $TAB - - - """.trimIndent() - ) - } - val output = File.createTempFile("output", "xml") - XmlReportMerger.merge(setOf(file1, file2), output) - - val expectedText = """ - - - - - - - + @Test + fun `passes for same files`() { + val file1 = File.createTempFile("detekt1", "xml").apply { + writeText( + """ + + + + $TAB + - """.trimIndent() - assertThat(output.readText()).isEqualToIgnoringNewLines(expectedText) + """.trimIndent() + ) } + val file2 = File.createTempFile("detekt2", "xml").apply { + writeText( + """ + + + + $TAB + + + """.trimIndent() + ) + } + val output = File.createTempFile("output", "xml") + XmlReportMerger.merge(setOf(file1, file2), output) + + val expectedText = """ + + + + + + + + + """.trimIndent() + assertThat(output.readText()).isEqualToIgnoringNewLines(expectedText) } } diff --git a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/CognitiveComplexitySpec.kt b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/CognitiveComplexitySpec.kt index bf128350153..a69ba4a9008 100644 --- a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/CognitiveComplexitySpec.kt +++ b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/CognitiveComplexitySpec.kt @@ -7,282 +7,278 @@ import org.junit.jupiter.api.Test class CognitiveComplexitySpec { - @Nested - inner class `cognitive complexity` { - - @Test - fun `sums seven for sumOfPrimes example`() { - val code = compileContentForTest( - """ - fun sumOfPrimes(max: Int): Int { - var total = 0 - next@ for (i in 1..max) { - for (j in 2 until i) { - if (i % j == 0) { - continue@next - } + @Test + fun `sums seven for sumOfPrimes example`() { + val code = compileContentForTest( + """ + fun sumOfPrimes(max: Int): Int { + var total = 0 + next@ for (i in 1..max) { + for (j in 2 until i) { + if (i % j == 0) { + continue@next } - println(i) - total++ } - return total + println(i) + total++ } - """ - ) + return total + } + """ + ) - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(7) - } + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(7) + } + + @Test + fun `sums one for getWords example for a single when expression`() { + val code = compileContentForTest( + """ + fun getWords(number: Int): String = when (number) { + 1 -> "one" + 2 -> "a couple" + 3 -> "a few" + else -> "lots" + } + """ + ) + + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(1) + } + + @Nested + inner class `recursion` { @Test - fun `sums one for getWords example for a single when expression`() { + fun `adds one for recursion inside class`() { val code = compileContentForTest( """ - fun getWords(number: Int): String = when (number) { - 1 -> "one" - 2 -> "a couple" - 3 -> "a few" - else -> "lots" - } + class A { + fun factorial(n: Int): Int = + if (n >= 1) n * this.factorial(n - 1) else 1 + } """ ) - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(1) - } - - @Nested - inner class `recursion` { - - @Test - fun `adds one for recursion inside class`() { - val code = compileContentForTest( - """ - class A { - fun factorial(n: Int): Int = - if (n >= 1) n * this.factorial(n - 1) else 1 - } - """ - ) - - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(2) - } - - @Test - fun `adds one for top level recursion`() { - val code = compileContentForTest( - """ - fun factorial(n: Int): Int = - if (n >= 1) n * factorial(n - 1) else 1 - """ - ) - - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(2) - } - - @Test - fun `does not add as it is only the same name`() { - val code = compileContentForTest( - """ - object O { fun factorial(i: Int): Int = i - 1 } - fun factorial(n: Int): Int = - if (n >= 1) n * O.factorial(n - 1) else 1 - """ - ) - - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(1) - } + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(2) } @Test - fun `ignores shorthand operators`() { + fun `adds one for top level recursion`() { val code = compileContentForTest( """ - fun parse(args: Array): Nothing = TODO() - fun main(args: Array) { - args.takeIf { it.size > 3 }?.let(::parse) ?: error("not enough arguments") - } + fun factorial(n: Int): Int = + if (n >= 1) n * factorial(n - 1) else 1 """ ) - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(0) + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(2) } @Test - fun `adds one per catch clause`() { + fun `does not add as it is only the same name`() { val code = compileContentForTest( """ - fun main() { - try { - } catch (e: IllegalArgumentException) { - } catch (e: IllegalStateException) { - } catch (e: Throwable) {} - } + object O { fun factorial(i: Int): Int = i - 1 } + fun factorial(n: Int): Int = + if (n >= 1) n * O.factorial(n - 1) else 1 """ ) - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(3) + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(1) } + } - @Test - fun `adds extra complexity for nesting`() { - val code = compileContentForTest( - """ - fun main() { - try { - if (true) { // +1 - for (i in 0..10) { // +2 - while(true) { // +3 - // more code - } + @Test + fun `ignores shorthand operators`() { + val code = compileContentForTest( + """ + fun parse(args: Array): Nothing = TODO() + fun main(args: Array) { + args.takeIf { it.size > 3 }?.let(::parse) ?: error("not enough arguments") + } + """ + ) + + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(0) + } + + @Test + fun `adds one per catch clause`() { + val code = compileContentForTest( + """ + fun main() { + try { + } catch (e: IllegalArgumentException) { + } catch (e: IllegalStateException) { + } catch (e: Throwable) {} + } + """ + ) + + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(3) + } + + @Test + fun `adds extra complexity for nesting`() { + val code = compileContentForTest( + """ + fun main() { + try { + if (true) { // +1 + for (i in 0..10) { // +2 + while(true) { // +3 + // more code } } - } catch (e: Exception) { // +1 - do {} while(true) // +2 } + } catch (e: Exception) { // +1 + do {} while(true) // +2 } - """ - ) + } + """ + ) - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(9) - } + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(9) + } - @Test - fun `adds nesting for lambdas but not complexity`() { - val code = compileContentForTest( - """ - fun main() { run { if (true) {} } } - """ - ) + @Test + fun `adds nesting for lambdas but not complexity`() { + val code = compileContentForTest( + """ + fun main() { run { if (true) {} } } + """ + ) - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(2) - } + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(2) + } + + @Test + fun `adds nesting for nested functions but not complexity`() { + val code = compileContentForTest( + """ + fun main() { fun run() { if (true) {} } } + """ + ) + + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(2) + } + + @Nested + inner class `binary expressions` { @Test - fun `adds nesting for nested functions but not complexity`() { + fun `does not increment on just a condition`() { val code = compileContentForTest( """ - fun main() { fun run() { if (true) {} } } + fun test(cond_ Boolean) = !cond """ ) - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(2) + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(0) } @Nested - inner class `binary expressions` { + inner class `increments for every non-like operator` { @Test - fun `does not increment on just a condition`() { + fun `adds one for just a &&`() { val code = compileContentForTest( """ - fun test(cond_ Boolean) = !cond + fun test(cond_ Boolean) = !cond && !cond """ ) - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(0) + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(1) } - @Nested - inner class `increments for every non-like operator` { - - @Test - fun `adds one for just a &&`() { - val code = compileContentForTest( - """ - fun test(cond_ Boolean) = !cond && !cond - """ - ) - - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(1) - } - - @Test - fun `adds only one for repeated &&`() { - val code = compileContentForTest( - """ - fun test(cond_ Boolean) = !cond && !cond && !cond - """ - ) + @Test + fun `adds only one for repeated &&`() { + val code = compileContentForTest( + """ + fun test(cond_ Boolean) = !cond && !cond && !cond + """ + ) - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(1) - } + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(1) + } - @Test - fun `adds one per logical alternate operator`() { - val code = compileContentForTest( - """ - fun test(cond_ Boolean) = !cond && !cond || cond - """ - ) + @Test + fun `adds one per logical alternate operator`() { + val code = compileContentForTest( + """ + fun test(cond_ Boolean) = !cond && !cond || cond + """ + ) - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(2) - } + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(2) + } - @Test - fun `adds one per logical alternate operator with like operators in between`() { - val code = compileContentForTest( - """ - fun test(cond_ Boolean) { - if ( // +1 - !cond - && !cond && !cond // +1 - || cond || cond // +1 - && cond // +1 - ) {} - } - """ - ) + @Test + fun `adds one per logical alternate operator with like operators in between`() { + val code = compileContentForTest( + """ + fun test(cond_ Boolean) { + if ( // +1 + !cond + && !cond && !cond // +1 + || cond || cond // +1 + && cond // +1 + ) {} + } + """ + ) - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(4) - } + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(4) + } - @Test - fun `adds one for negated but similar operators`() { - val code = compileContentForTest( - """ - fun test(cond_ Boolean) { - if ( // +1 - !cond - && !(cond && cond) // +2 - ) {} - } - """ - ) + @Test + fun `adds one for negated but similar operators`() { + val code = compileContentForTest( + """ + fun test(cond_ Boolean) { + if ( // +1 + !cond + && !(cond && cond) // +2 + ) {} + } + """ + ) - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(3) - } + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(3) + } - @Test - fun `adds only one for a negated chain of similar operators`() { - val code = compileContentForTest( - """ - fun test(cond_ Boolean) { - if ( // +1 - !cond - && !(cond && cond && cond) // +2 - ) {} - } - """ - ) + @Test + fun `adds only one for a negated chain of similar operators`() { + val code = compileContentForTest( + """ + fun test(cond_ Boolean) { + if ( // +1 + !cond + && !(cond && cond && cond) // +2 + ) {} + } + """ + ) - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(3) - } + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(3) + } - @Test - fun `adds one for every negated similar operator chain`() { - val code = compileContentForTest( - """ - fun test(cond_ Boolean) { - if ( // +1 - !cond - && !(cond && cond && cond) // +2 - || !(cond || cond) // +2 - ) {} - } - """ - ) + @Test + fun `adds one for every negated similar operator chain`() { + val code = compileContentForTest( + """ + fun test(cond_ Boolean) { + if ( // +1 + !cond + && !(cond && cond && cond) // +2 + || !(cond || cond) // +2 + ) {} + } + """ + ) - assertThat(CognitiveComplexity.calculate(code)).isEqualTo(5) - } + assertThat(CognitiveComplexity.calculate(code)).isEqualTo(5) } } } diff --git a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/ComplexityReportGeneratorSpec.kt b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/ComplexityReportGeneratorSpec.kt index 3ce56b6475d..9a11e5eec0a 100644 --- a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/ComplexityReportGeneratorSpec.kt +++ b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/ComplexityReportGeneratorSpec.kt @@ -17,72 +17,68 @@ import org.junit.jupiter.api.Test internal class ComplexityReportGeneratorSpec { + private lateinit var detektion: TestDetektion + + @BeforeEach + fun setupMocks() { + val finding = mockk() + every { finding.id }.returns("test") + detektion = TestDetektion(finding).withTestData() + } + + @Nested + inner class `several complexity metrics` { + + @Test + fun `successfully generates a complexity report`() { + val expectedContent = listOf( + "1,000 lines of code (loc)", + "6 source lines of code (sloc)", + "5 logical lines of code (lloc)", + "4 comment lines of code (cloc)", + "2 cyclomatic complexity (mcc)", + "2 cognitive complexity", + "1 number of total code smells", + "66% comment source ratio", + "400 mcc per 1,000 lloc", + "200 code smells per 1,000 lloc" + ) + + assertThat(generateComplexityReport(detektion)).isEqualTo(expectedContent) + } + } + @Nested - inner class `complexity report generator` { + inner class `several invalid complexity metrics` { - private lateinit var detektion: TestDetektion + @Test + fun `returns null for missing mcc`() { + detektion.removeData(complexityKey) + assertThat(generateComplexityReport(detektion)).isNull() + } - @BeforeEach - fun setupMocks() { - val finding = mockk() - every { finding.id }.returns("test") - detektion = TestDetektion(finding).withTestData() + @Test + fun `returns null for missing lloc`() { + detektion.removeData(logicalLinesKey) + assertThat(generateComplexityReport(detektion)).isNull() + + detektion.addData(logicalLinesKey, 0) + assertThat(generateComplexityReport(detektion)).isNull() } - @Nested - inner class `several complexity metrics` { - - @Test - fun `successfully generates a complexity report`() { - val expectedContent = listOf( - "1,000 lines of code (loc)", - "6 source lines of code (sloc)", - "5 logical lines of code (lloc)", - "4 comment lines of code (cloc)", - "2 cyclomatic complexity (mcc)", - "2 cognitive complexity", - "1 number of total code smells", - "66% comment source ratio", - "400 mcc per 1,000 lloc", - "200 code smells per 1,000 lloc" - ) - - assertThat(generateComplexityReport(detektion)).isEqualTo(expectedContent) - } + @Test + fun `returns null for missing sloc`() { + detektion.removeData(sourceLinesKey) + assertThat(generateComplexityReport(detektion)).isNull() + + detektion.addData(sourceLinesKey, 0) + assertThat(generateComplexityReport(detektion)).isNull() } - @Nested - inner class `several invalid complexity metrics` { - - @Test - fun `returns null for missing mcc`() { - detektion.removeData(complexityKey) - assertThat(generateComplexityReport(detektion)).isNull() - } - - @Test - fun `returns null for missing lloc`() { - detektion.removeData(logicalLinesKey) - assertThat(generateComplexityReport(detektion)).isNull() - - detektion.addData(logicalLinesKey, 0) - assertThat(generateComplexityReport(detektion)).isNull() - } - - @Test - fun `returns null for missing sloc`() { - detektion.removeData(sourceLinesKey) - assertThat(generateComplexityReport(detektion)).isNull() - - detektion.addData(sourceLinesKey, 0) - assertThat(generateComplexityReport(detektion)).isNull() - } - - @Test - fun `returns null for missing cloc`() { - detektion.removeData(complexityKey) - assertThat(generateComplexityReport(detektion)).isNull() - } + @Test + fun `returns null for missing cloc`() { + detektion.removeData(complexityKey) + assertThat(generateComplexityReport(detektion)).isNull() } } } diff --git a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/CLOCVisitorSpec.kt b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/CLOCVisitorSpec.kt index e50f62fda16..04dca23a7ea 100644 --- a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/CLOCVisitorSpec.kt +++ b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/CLOCVisitorSpec.kt @@ -2,21 +2,17 @@ package io.github.detekt.metrics.processors import io.github.detekt.test.utils.compileContentForTest import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class CLOCVisitorSpec { - @Nested - inner class `CLOC` { - @Test - fun `commentCases`() { - val file = compileContentForTest(commentsClass) - val commentLines = with(file) { - accept(CLOCVisitor()) - getUserData(commentLinesKey) - } - assertThat(commentLines).isEqualTo(10) + @Test + fun `commentCases`() { + val file = compileContentForTest(commentsClass) + val commentLines = with(file) { + accept(CLOCVisitor()) + getUserData(commentLinesKey) } + assertThat(commentLines).isEqualTo(10) } } diff --git a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/ClassCountVisitorSpec.kt b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/ClassCountVisitorSpec.kt index f0f01ec11fd..076dc45b86b 100644 --- a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/ClassCountVisitorSpec.kt +++ b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/ClassCountVisitorSpec.kt @@ -3,39 +3,34 @@ package io.github.detekt.metrics.processors import io.github.detekt.test.utils.compileContentForTest import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.psi.KtFile -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ClassCountVisitorSpec { - @Nested - inner class `something` { - - @Test - fun `twoClassesInSeparateFile`() { - val files = arrayOf( - compileContentForTest(default), - compileContentForTest(classWithFields) - ) - val count = getClassCount(files) - assertThat(count).isEqualTo(2) - } + @Test + fun `twoClassesInSeparateFile`() { + val files = arrayOf( + compileContentForTest(default), + compileContentForTest(classWithFields) + ) + val count = getClassCount(files) + assertThat(count).isEqualTo(2) + } - @Test - fun `oneClassWithOneNestedClass`() { - val file = compileContentForTest(complexClass) - val count = getClassCount(arrayOf(file)) - assertThat(count).isEqualTo(2) - } + @Test + fun `oneClassWithOneNestedClass`() { + val file = compileContentForTest(complexClass) + val count = getClassCount(arrayOf(file)) + assertThat(count).isEqualTo(2) + } - @Test - fun `testEnumAndInterface`() { - val files = arrayOf( - compileContentForTest(emptyEnum), - compileContentForTest(emptyInterface) - ) - val count = getClassCount(files) - assertThat(count).isEqualTo(2) - } + @Test + fun `testEnumAndInterface`() { + val files = arrayOf( + compileContentForTest(emptyEnum), + compileContentForTest(emptyInterface) + ) + val count = getClassCount(files) + assertThat(count).isEqualTo(2) } } diff --git a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/CognitiveComplexityProcessorSpec.kt b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/CognitiveComplexityProcessorSpec.kt index 4756b9c0777..b3d4ea669d3 100644 --- a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/CognitiveComplexityProcessorSpec.kt +++ b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/CognitiveComplexityProcessorSpec.kt @@ -3,22 +3,17 @@ package io.github.detekt.metrics.processors import io.github.detekt.metrics.CognitiveComplexity import io.github.detekt.test.utils.compileContentForTest import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class CognitiveComplexityProcessorSpec { - @Nested - inner class `CognitiveComplexityProcessor` { + @Test + fun `counts the complexity for the whole file`() { + val file = compileContentForTest(complexClass) - @Test - fun `counts the complexity for the whole file`() { - val file = compileContentForTest(complexClass) + val value = MetricProcessorTester(file) + .test(ProjectCognitiveComplexityProcessor(), CognitiveComplexity.KEY) - val value = MetricProcessorTester(file) - .test(ProjectCognitiveComplexityProcessor(), CognitiveComplexity.KEY) - - assertThat(value).isEqualTo(46) - } + assertThat(value).isEqualTo(46) } } diff --git a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/ComplexityVisitorSpec.kt b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/ComplexityVisitorSpec.kt index dfd2764e0fc..97910d38761 100644 --- a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/ComplexityVisitorSpec.kt +++ b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/ComplexityVisitorSpec.kt @@ -2,26 +2,21 @@ package io.github.detekt.metrics.processors import io.github.detekt.test.utils.compileContentForTest import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ComplexityVisitorSpec { - @Nested - inner class `something` { + @Test + fun `complexityOfDefaultCaseIsOne`() { + val mcc = calcComplexity(default) - @Test - fun `complexityOfDefaultCaseIsOne`() { - val mcc = calcComplexity(default) - - assertThat(mcc).isEqualTo(0) - } + assertThat(mcc).isEqualTo(0) + } - @Test - fun `complexityOfComplexAndNestedClass`() { - val mcc = calcComplexity(complexClass) + @Test + fun `complexityOfComplexAndNestedClass`() { + val mcc = calcComplexity(complexClass) - assertThat(mcc).isEqualTo(44) - } + assertThat(mcc).isEqualTo(44) } } diff --git a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/FieldCountVisitorSpec.kt b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/FieldCountVisitorSpec.kt index a2b3b4948d9..ec4c570808c 100644 --- a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/FieldCountVisitorSpec.kt +++ b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/FieldCountVisitorSpec.kt @@ -2,21 +2,17 @@ package io.github.detekt.metrics.processors import io.github.detekt.test.utils.compileContentForTest import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class FieldCountVisitorSpec { - @Nested - inner class `something` { - @Test - fun `defaultFieldCount`() { - val file = compileContentForTest(classWithFields) - val count = with(file) { - accept(PropertyCountVisitor()) - getUserData(numberOfFieldsKey) - } - assertThat(count).isEqualTo(2) + @Test + fun `defaultFieldCount`() { + val file = compileContentForTest(classWithFields) + val count = with(file) { + accept(PropertyCountVisitor()) + getUserData(numberOfFieldsKey) } + assertThat(count).isEqualTo(2) } } diff --git a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/KtFileCountVisitorSpec.kt b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/KtFileCountVisitorSpec.kt index 9293f906342..c585dc64c84 100644 --- a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/KtFileCountVisitorSpec.kt +++ b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/KtFileCountVisitorSpec.kt @@ -3,22 +3,18 @@ package io.github.detekt.metrics.processors import io.github.detekt.test.utils.compileContentForTest import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.psi.KtFile -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class KtFileCountVisitorSpec { - @Nested - inner class `files` { - @Test - fun `twoFiles`() { - val files = arrayOf( - compileContentForTest(default), - compileContentForTest(complexClass) - ) - val count = files.sumOf { getData(it) } - assertThat(count).isEqualTo(2) - } + @Test + fun `twoFiles`() { + val files = arrayOf( + compileContentForTest(default), + compileContentForTest(complexClass) + ) + val count = files.sumOf { getData(it) } + assertThat(count).isEqualTo(2) } } diff --git a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/LLOCVisitorSpec.kt b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/LLOCVisitorSpec.kt index 2bc059671d8..46d056076b4 100644 --- a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/LLOCVisitorSpec.kt +++ b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/LLOCVisitorSpec.kt @@ -2,35 +2,31 @@ package io.github.detekt.metrics.processors import io.github.detekt.test.utils.compileContentForTest import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class LLOCVisitorSpec { - @Nested - inner class `LLOC Visitor` { - @Test - fun `defaultCaseHasOneClassAndAnnotationLine`() { - val file = compileContentForTest(default) + @Test + fun `defaultCaseHasOneClassAndAnnotationLine`() { + val file = compileContentForTest(default) - val lloc = with(file) { - accept(LLOCVisitor()) - getUserData(logicalLinesKey) - } - - assertThat(lloc).isEqualTo(2) + val lloc = with(file) { + accept(LLOCVisitor()) + getUserData(logicalLinesKey) } - @Test - fun `llocOfComplexClass`() { - val file = compileContentForTest(complexClass) + assertThat(lloc).isEqualTo(2) + } - val lloc = with(file) { - accept(LLOCVisitor()) - getUserData(logicalLinesKey) - } + @Test + fun `llocOfComplexClass`() { + val file = compileContentForTest(complexClass) - assertThat(lloc).isEqualTo(85) + val lloc = with(file) { + accept(LLOCVisitor()) + getUserData(logicalLinesKey) } + + assertThat(lloc).isEqualTo(85) } } diff --git a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/LOCVisitorSpec.kt b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/LOCVisitorSpec.kt index 429ad1a6b5a..b62630f46f4 100644 --- a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/LOCVisitorSpec.kt +++ b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/LOCVisitorSpec.kt @@ -2,21 +2,17 @@ package io.github.detekt.metrics.processors import io.github.detekt.test.utils.compileContentForTest import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class LOCVisitorSpec { - @Nested - inner class `LOC Visitor` { - @Test - fun `defaultClass`() { - val file = compileContentForTest(default) - val loc = with(file) { - accept(LOCVisitor()) - getUserData(linesKey) - } - assertThat(loc).isEqualTo(8) + @Test + fun `defaultClass`() { + val file = compileContentForTest(default) + val loc = with(file) { + accept(LOCVisitor()) + getUserData(linesKey) } + assertThat(loc).isEqualTo(8) } } diff --git a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/MethodCountVisitorSpec.kt b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/MethodCountVisitorSpec.kt index cb473d84305..011a33e2544 100644 --- a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/MethodCountVisitorSpec.kt +++ b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/MethodCountVisitorSpec.kt @@ -3,19 +3,15 @@ package io.github.detekt.metrics.processors import io.github.detekt.test.utils.compileContentForTest import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.psi.KtFile -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class MethodCountVisitorSpec { - @Nested - inner class `Method Count Visitor` { - @Test - fun `defaultMethodCount`() { - val file = compileContentForTest(complexClass) - val count = getMethodCount(file) - assertThat(count).isEqualTo(6) - } + @Test + fun `defaultMethodCount`() { + val file = compileContentForTest(complexClass) + val count = getMethodCount(file) + assertThat(count).isEqualTo(6) } } diff --git a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/PackageCountVisitorSpec.kt b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/PackageCountVisitorSpec.kt index e26be62963d..e411c1d0c12 100644 --- a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/PackageCountVisitorSpec.kt +++ b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/PackageCountVisitorSpec.kt @@ -3,25 +3,21 @@ package io.github.detekt.metrics.processors import io.github.detekt.test.utils.compileContentForTest import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.psi.KtFile -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class PackageCountVisitorSpec { - @Nested - inner class `Package Count Visitor` { - @Test - fun `twoClassesInSeparatePackage`() { - val files = arrayOf( - compileContentForTest(default), - compileContentForTest(emptyEnum) - ) - val count = files - .map { getData(it) } - .distinct() - .count() - assertThat(count).isEqualTo(2) - } + @Test + fun `twoClassesInSeparatePackage`() { + val files = arrayOf( + compileContentForTest(default), + compileContentForTest(emptyEnum) + ) + val count = files + .map { getData(it) } + .distinct() + .count() + assertThat(count).isEqualTo(2) } } diff --git a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/SLOCVisitorSpec.kt b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/SLOCVisitorSpec.kt index dfa63799626..b0268aafb39 100644 --- a/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/SLOCVisitorSpec.kt +++ b/detekt-metrics/src/test/kotlin/io/github/detekt/metrics/processors/SLOCVisitorSpec.kt @@ -2,21 +2,17 @@ package io.github.detekt.metrics.processors import io.github.detekt.test.utils.compileContentForTest import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class SLOCVisitorSpec { - @Nested - inner class `SLOC Visitor` { - @Test - fun `defaultClass`() { - val file = compileContentForTest(default) - val loc = with(file) { - accept(SLOCVisitor()) - getUserData(sourceLinesKey) - } - assertThat(loc).isEqualTo(3) + @Test + fun `defaultClass`() { + val file = compileContentForTest(default) + val loc = with(file) { + accept(SLOCVisitor()) + getUserData(sourceLinesKey) } + assertThat(loc).isEqualTo(3) } } diff --git a/detekt-parser/src/test/kotlin/io/github/detekt/parser/KotlinEnvironmentUtilsSpec.kt b/detekt-parser/src/test/kotlin/io/github/detekt/parser/KotlinEnvironmentUtilsSpec.kt index 908658a3d55..8f56cdeb335 100644 --- a/detekt-parser/src/test/kotlin/io/github/detekt/parser/KotlinEnvironmentUtilsSpec.kt +++ b/detekt-parser/src/test/kotlin/io/github/detekt/parser/KotlinEnvironmentUtilsSpec.kt @@ -1,30 +1,26 @@ package io.github.detekt.parser import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import java.io.File class KotlinEnvironmentUtilsSpec { - @Nested - inner class `retrieved kotlin language version` { - @Test - fun `should match`() { - val expectedVersionString = System.getProperty("kotlinVersion", "") - .splitToSequence('.') - .take(2) - .joinToString(".") + @Test + fun `retrieved kotlin language version should match`() { + val expectedVersionString = System.getProperty("kotlinVersion", "") + .splitToSequence('.') + .take(2) + .joinToString(".") - val classpathFiles = System.getProperty("testClasspath", "") - .splitToSequence(';') - .map(::File) - .filter(File::exists) - .toList() + val classpathFiles = System.getProperty("testClasspath", "") + .splitToSequence(';') + .map(::File) + .filter(File::exists) + .toList() - val languageVersion = classpathFiles.getKotlinLanguageVersion() - assertThat(languageVersion).isNotNull - assertThat(languageVersion?.versionString).isEqualTo(expectedVersionString) - } + val languageVersion = classpathFiles.getKotlinLanguageVersion() + assertThat(languageVersion).isNotNull + assertThat(languageVersion?.versionString).isEqualTo(expectedVersionString) } } diff --git a/detekt-report-html/src/test/kotlin/io/github/detekt/report/html/HtmlOutputReportSpec.kt b/detekt-report-html/src/test/kotlin/io/github/detekt/report/html/HtmlOutputReportSpec.kt index dab4748d0eb..4969efc3930 100644 --- a/detekt-report-html/src/test/kotlin/io/github/detekt/report/html/HtmlOutputReportSpec.kt +++ b/detekt-report-html/src/test/kotlin/io/github/detekt/report/html/HtmlOutputReportSpec.kt @@ -21,162 +21,157 @@ import io.mockk.mockk import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.com.intellij.psi.PsiFile import org.jetbrains.kotlin.psi.KtElement -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import java.nio.file.Files import java.nio.file.Path class HtmlOutputReportSpec { - @Nested - inner class `HTML output report` { + private val htmlReport = HtmlOutputReport() - private val htmlReport = HtmlOutputReport() + @Test + fun `renders the HTML headers correctly`() { + val result = htmlReport.render(TestDetektion()) - @Test - fun `renders the HTML headers correctly`() { - val result = htmlReport.render(TestDetektion()) + assertThat(result).startsWith("\n") + assertThat(result).endsWith("\n") - assertThat(result).startsWith("\n") - assertThat(result).endsWith("\n") - - assertThat(result).contains("

Metrics

") - assertThat(result).contains("

Complexity Report

") - assertThat(result).contains("

Findings

") - } + assertThat(result).contains("

Metrics

") + assertThat(result).contains("

Complexity Report

") + assertThat(result).contains("

Findings

") + } - @Test - fun `renders the 'generated with' text correctly`() { - val version = whichDetekt() - val header = - """generated with detekt version $version on """ + @Test + fun `renders the 'generated with' text correctly`() { + val version = whichDetekt() + val header = + """generated with detekt version $version on """ - val result = htmlReport.render(TestDetektion()) + val result = htmlReport.render(TestDetektion()) - assertThat(result).contains(header) - assertThat(result).doesNotContain("@@@date@@@") - } + assertThat(result).contains(header) + assertThat(result).doesNotContain("@@@date@@@") + } - @Test - fun `contains the total number of findings`() { - val result = htmlReport.render(createTestDetektionWithMultipleSmells()) + @Test + fun `contains the total number of findings`() { + val result = htmlReport.render(createTestDetektionWithMultipleSmells()) - assertThat(result).contains("Total: 3") - } + assertThat(result).contains("Total: 3") + } - @Test - fun `contains no findings`() { - val detektion = object : TestDetektion() { - override val findings: Map> = mapOf( - "EmptyRuleset" to emptyList() - ) - } - val result = htmlReport.render(detektion) - assertThat(result).contains("Total: 0") + @Test + fun `contains no findings`() { + val detektion = object : TestDetektion() { + override val findings: Map> = mapOf( + "EmptyRuleset" to emptyList() + ) } + val result = htmlReport.render(detektion) + assertThat(result).contains("Total: 0") + } - @Test - fun `renders the right file locations`() { - val result = htmlReport.render(createTestDetektionWithMultipleSmells()) + @Test + fun `renders the right file locations`() { + val result = htmlReport.render(createTestDetektionWithMultipleSmells()) - assertThat(result).contains("src/main/com/sample/Sample1.kt:11:1") - assertThat(result).contains("src/main/com/sample/Sample2.kt:22:2") - assertThat(result).contains("src/main/com/sample/Sample3.kt:33:3") - } + assertThat(result).contains("src/main/com/sample/Sample1.kt:11:1") + assertThat(result).contains("src/main/com/sample/Sample2.kt:22:2") + assertThat(result).contains("src/main/com/sample/Sample3.kt:33:3") + } - @Test - fun `renders the right file locations for relative paths`() { - val result = htmlReport.render(createTestDetektionFromRelativePath()) + @Test + fun `renders the right file locations for relative paths`() { + val result = htmlReport.render(createTestDetektionFromRelativePath()) - assertThat(result).contains("src/main/com/sample/Sample1.kt:11:1") - assertThat(result).contains("src/main/com/sample/Sample2.kt:22:2") - assertThat(result).contains("src/main/com/sample/Sample3.kt:33:3") - } + assertThat(result).contains("src/main/com/sample/Sample1.kt:11:1") + assertThat(result).contains("src/main/com/sample/Sample2.kt:22:2") + assertThat(result).contains("src/main/com/sample/Sample3.kt:33:3") + } - @Test - fun `renders the right number of issues per rule`() { - val result = htmlReport.render(createTestDetektionWithMultipleSmells()) + @Test + fun `renders the right number of issues per rule`() { + val result = htmlReport.render(createTestDetektionWithMultipleSmells()) - assertThat(result).contains("id_a: 2 ") - assertThat(result).contains("id_b: 1 ") - } + assertThat(result).contains("id_a: 2 ") + assertThat(result).contains("id_b: 1 ") + } - @Test - fun `renders the right violation messages for the rules`() { - val result = htmlReport.render(createTestDetektionWithMultipleSmells()) + @Test + fun `renders the right violation messages for the rules`() { + val result = htmlReport.render(createTestDetektionWithMultipleSmells()) - assertThat(result).contains("Message finding 1") - assertThat(result).contains("Message finding 2") - assertThat(result).doesNotContain("") - } + assertThat(result).contains("Message finding 1") + assertThat(result).contains("Message finding 2") + assertThat(result).doesNotContain("") + } - @Test - fun `renders the right violation description for the rules`() { - val result = htmlReport.render(createTestDetektionWithMultipleSmells()) + @Test + fun `renders the right violation description for the rules`() { + val result = htmlReport.render(createTestDetektionWithMultipleSmells()) - assertThat(result).contains("Description id_a") - assertThat(result).contains("Description id_b") - } + assertThat(result).contains("Description id_a") + assertThat(result).contains("Description id_b") + } - @Test - fun `renders a metric report correctly`() { - val detektion = object : TestDetektion() { - override val metrics: Collection = listOf( - ProjectMetric("M1", 10_000), - ProjectMetric("M2", 2) - ) - } - val result = htmlReport.render(detektion) - assertThat(result).contains("
  • 10,000 M1
  • ") - assertThat(result).contains("
  • 2 M2
  • ") + @Test + fun `renders a metric report correctly`() { + val detektion = object : TestDetektion() { + override val metrics: Collection = listOf( + ProjectMetric("M1", 10_000), + ProjectMetric("M2", 2) + ) } + val result = htmlReport.render(detektion) + assertThat(result).contains("
  • 10,000 M1
  • ") + assertThat(result).contains("
  • 2 M2
  • ") + } - @Test - fun `renders the complexity report correctly`() { - val detektion = TestDetektion() - detektion.addData(complexityKey, 10) - detektion.addData(CognitiveComplexity.KEY, 10) - detektion.addData(sourceLinesKey, 20) - detektion.addData(logicalLinesKey, 10) - detektion.addData(commentLinesKey, 2) - detektion.addData(linesKey, 2222) - val result = htmlReport.render(detektion) - assertThat(result).contains("
  • 2,222 lines of code (loc)
  • ") - assertThat(result).contains("
  • 20 source lines of code (sloc)
  • ") - assertThat(result).contains("
  • 10 logical lines of code (lloc)
  • ") - } + @Test + fun `renders the complexity report correctly`() { + val detektion = TestDetektion() + detektion.addData(complexityKey, 10) + detektion.addData(CognitiveComplexity.KEY, 10) + detektion.addData(sourceLinesKey, 20) + detektion.addData(logicalLinesKey, 10) + detektion.addData(commentLinesKey, 2) + detektion.addData(linesKey, 2222) + val result = htmlReport.render(detektion) + assertThat(result).contains("
  • 2,222 lines of code (loc)
  • ") + assertThat(result).contains("
  • 20 source lines of code (sloc)
  • ") + assertThat(result).contains("
  • 10 logical lines of code (lloc)
  • ") + } - @Test - fun `renders a blank complexity report correctly`() { - val result = htmlReport.render(createTestDetektionWithMultipleSmells()) - assertThat(result).contains("

    Complexity Report

    \n\n
    \n
      \n
      ") - } + @Test + fun `renders a blank complexity report correctly`() { + val result = htmlReport.render(createTestDetektionWithMultipleSmells()) + assertThat(result).contains("

      Complexity Report

      \n\n
      \n
        \n
        ") + } - @Test - fun `asserts that the generated HTML is the same as expected`() { - val expected = resourceAsPath("HtmlOutputFormatTest.html") - var result = htmlReport.render(createTestDetektionWithMultipleSmells()) - result = generatedRegex.replace(result, replacement) + @Test + fun `asserts that the generated HTML is the same as expected`() { + val expected = resourceAsPath("HtmlOutputFormatTest.html") + var result = htmlReport.render(createTestDetektionWithMultipleSmells()) + result = generatedRegex.replace(result, replacement) - val actual = createTempFileForTest("actual-report", ".html") - Files.write(actual, result.toByteArray()) + val actual = createTempFileForTest("actual-report", ".html") + Files.write(actual, result.toByteArray()) - assertThat(actual).hasSameTextualContentAs(expected) - } + assertThat(actual).hasSameTextualContentAs(expected) + } - @Test - fun `asserts that the generated HTML is the same even if we change the order of the findings`() { - val findings = findings() - val reversedFindings = findings - .reversedArray() - .map { (section, findings) -> section to findings.asReversed() } - .toTypedArray() + @Test + fun `asserts that the generated HTML is the same even if we change the order of the findings`() { + val findings = findings() + val reversedFindings = findings + .reversedArray() + .map { (section, findings) -> section to findings.asReversed() } + .toTypedArray() - val firstReport = createReportWithFindings(findings) - val secondReport = createReportWithFindings(reversedFindings) + val firstReport = createReportWithFindings(findings) + val secondReport = createReportWithFindings(reversedFindings) - assertThat(firstReport).hasSameTextualContentAs(secondReport) - } + assertThat(firstReport).hasSameTextualContentAs(secondReport) } } diff --git a/detekt-report-html/src/test/kotlin/io/github/detekt/report/html/HtmlUtilsSpec.kt b/detekt-report-html/src/test/kotlin/io/github/detekt/report/html/HtmlUtilsSpec.kt index c476af61d7e..ffb94c1bb16 100644 --- a/detekt-report-html/src/test/kotlin/io/github/detekt/report/html/HtmlUtilsSpec.kt +++ b/detekt-report-html/src/test/kotlin/io/github/detekt/report/html/HtmlUtilsSpec.kt @@ -4,144 +4,140 @@ import io.gitlab.arturbosch.detekt.api.SourceLocation import kotlinx.html.div import kotlinx.html.stream.createHTML import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class HtmlUtilsSpec { - @Nested - inner class `HTML snippet code` { - private val code = """ - package cases - // reports 1 - line with just one space + private val code = """ + package cases + // reports 1 - line with just one space - // reports 1 - a comment with trailing space - // A comment - // reports 1 - class TrailingWhitespacePositive { - // reports 1 - line with just one tab - - // reports 1 - fun myFunction() { - // reports 1 - line with 1 trailing tab - println("A message") - // reports 1 - } - } - """.trimIndent().splitToSequence('\n') + // reports 1 - a comment with trailing space + // A comment + // reports 1 + class TrailingWhitespacePositive { + // reports 1 - line with just one tab - @Test - fun `all line`() { - val snippet = createHTML().div() { - snippetCode("ruleName", code.asSequence(), SourceLocation(7, 1), 34) + // reports 1 + fun myFunction() { + // reports 1 - line with 1 trailing tab + println("A message") + // reports 1 } + } + """.trimIndent().splitToSequence('\n') - assertThat(snippet).isEqualTo( - """ -
        -
           4 // reports 1 - a comment with trailing space
        -                   5 // A comment
        -                   6 // reports 1
        -                   7 class TrailingWhitespacePositive {
        -                   8     // reports 1 - line with just one tab
        -                   9 
        -                  10     // reports 1
        -                
        -
        - - """.trimIndent() - ) + @Test + fun `all line`() { + val snippet = createHTML().div() { + snippetCode("ruleName", code.asSequence(), SourceLocation(7, 1), 34) } - @Test - fun `part of line`() { - val snippet = createHTML().div() { - snippetCode("ruleName", code.asSequence(), SourceLocation(7, 7), 26) - } + assertThat(snippet).isEqualTo( + """ +
        +
           4 // reports 1 - a comment with trailing space
        +               5 // A comment
        +               6 // reports 1
        +               7 class TrailingWhitespacePositive {
        +               8     // reports 1 - line with just one tab
        +               9 
        +              10     // reports 1
        +            
        +
        + + """.trimIndent() + ) + } - assertThat(snippet).isEqualTo( - """ -
        -
           4 // reports 1 - a comment with trailing space
        -                   5 // A comment
        -                   6 // reports 1
        -                   7 class TrailingWhitespacePositive {
        -                   8     // reports 1 - line with just one tab
        -                   9 
        -                  10     // reports 1
        -                
        -
        - - """.trimIndent() - ) + @Test + fun `part of line`() { + val snippet = createHTML().div() { + snippetCode("ruleName", code.asSequence(), SourceLocation(7, 7), 26) } - @Test - fun `more than one line`() { - val snippet = createHTML().div() { - snippetCode("ruleName", code.asSequence(), SourceLocation(7, 7), 66) - } + assertThat(snippet).isEqualTo( + """ +
        +
           4 // reports 1 - a comment with trailing space
        +               5 // A comment
        +               6 // reports 1
        +               7 class TrailingWhitespacePositive {
        +               8     // reports 1 - line with just one tab
        +               9 
        +              10     // reports 1
        +            
        +
        + + """.trimIndent() + ) + } - assertThat(snippet).isEqualTo( - """ -
        -
           4 // reports 1 - a comment with trailing space
        -                   5 // A comment
        -                   6 // reports 1
        -                   7 class TrailingWhitespacePositive {
        -                   8     // reports 1 - line with just one tab
        -                   9 
        -                  10     // reports 1
        -                
        -
        - - """.trimIndent() - ) + @Test + fun `more than one line`() { + val snippet = createHTML().div() { + snippetCode("ruleName", code.asSequence(), SourceLocation(7, 7), 66) } - @Test - fun `first line`() { - val snippet = createHTML().div() { - snippetCode("ruleName", code.asSequence(), SourceLocation(1, 1), 1) - } + assertThat(snippet).isEqualTo( + """ +
        +
           4 // reports 1 - a comment with trailing space
        +               5 // A comment
        +               6 // reports 1
        +               7 class TrailingWhitespacePositive {
        +               8     // reports 1 - line with just one tab
        +               9 
        +              10     // reports 1
        +            
        +
        + + """.trimIndent() + ) + } - assertThat(snippet).contains((1..4).map { " $it " }) + @Test + fun `first line`() { + val snippet = createHTML().div() { + snippetCode("ruleName", code.asSequence(), SourceLocation(1, 1), 1) } - @Test - fun `second line`() { - val snippet = createHTML().div() { - snippetCode("ruleName", code.asSequence(), SourceLocation(2, 1), 1) - } + assertThat(snippet).contains((1..4).map { " $it " }) + } - assertThat(snippet).contains((1..5).map { " $it " }) + @Test + fun `second line`() { + val snippet = createHTML().div() { + snippetCode("ruleName", code.asSequence(), SourceLocation(2, 1), 1) } - @Test - fun `penultimate line`() { - val snippet = createHTML().div() { - snippetCode("ruleName", code.asSequence(), SourceLocation(15, 1), 1) - } + assertThat(snippet).contains((1..5).map { " $it " }) + } - assertThat(snippet).contains((12..16).map { " $it " }) + @Test + fun `penultimate line`() { + val snippet = createHTML().div() { + snippetCode("ruleName", code.asSequence(), SourceLocation(15, 1), 1) } - @Test - fun `last line`() { - val snippet = createHTML().div() { - snippetCode("ruleName", code.asSequence(), SourceLocation(16, 1), 1) - } + assertThat(snippet).contains((12..16).map { " $it " }) + } - assertThat(snippet).contains((13..16).map { " $it " }) + @Test + fun `last line`() { + val snippet = createHTML().div() { + snippetCode("ruleName", code.asSequence(), SourceLocation(16, 1), 1) } - @Test - fun `when we provide an invalid source location the exception div is shown`() { - val snippet = createHTML().div() { - snippetCode("ruleName", code.asSequence(), SourceLocation(7, 100), 1) - } + assertThat(snippet).contains((13..16).map { " $it " }) + } - assertThat(snippet).contains("""
        """) + @Test + fun `when we provide an invalid source location the exception div is shown`() { + val snippet = createHTML().div() { + snippetCode("ruleName", code.asSequence(), SourceLocation(7, 100), 1) } + + assertThat(snippet).contains("""
        """) } } diff --git a/detekt-report-sarif/src/test/kotlin/io/github/detekt/report/sarif/SarifOutputReportSpec.kt b/detekt-report-sarif/src/test/kotlin/io/github/detekt/report/sarif/SarifOutputReportSpec.kt index 2ce6d1ad98a..f2f1550bf9f 100644 --- a/detekt-report-sarif/src/test/kotlin/io/github/detekt/report/sarif/SarifOutputReportSpec.kt +++ b/detekt-report-sarif/src/test/kotlin/io/github/detekt/report/sarif/SarifOutputReportSpec.kt @@ -13,63 +13,58 @@ import io.gitlab.arturbosch.detekt.test.createEntity import io.gitlab.arturbosch.detekt.test.createFindingForRelativePath import io.gitlab.arturbosch.detekt.test.createIssue import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import java.nio.file.Paths @OptIn(UnstableApi::class) class SarifOutputReportSpec { - @Nested - inner class `sarif output report` { + @Test + fun `renders multiple issues`() { + val result = TestDetektion( + createFinding(ruleName = "TestSmellA", severity = SeverityLevel.ERROR), + createFinding(ruleName = "TestSmellB", severity = SeverityLevel.WARNING), + createFinding(ruleName = "TestSmellC", severity = SeverityLevel.INFO) + ) - @Test - fun `renders multiple issues`() { - val result = TestDetektion( - createFinding(ruleName = "TestSmellA", severity = SeverityLevel.ERROR), - createFinding(ruleName = "TestSmellB", severity = SeverityLevel.WARNING), - createFinding(ruleName = "TestSmellC", severity = SeverityLevel.INFO) - ) + val report = SarifOutputReport() + .apply { init(EmptySetupContext()) } + .render(result) - val report = SarifOutputReport() - .apply { init(EmptySetupContext()) } - .render(result) - - assertThat(report).isEqualToIgnoringWhitespace(readResourceContent("vanilla.sarif.json")) - } - - @Test - fun `renders multiple issues with relative path`() { - val basePath = "/Users/tester/detekt/" - val result = TestDetektion( - createFindingForRelativePath(ruleName = "TestSmellA", basePath = basePath), - createFindingForRelativePath(ruleName = "TestSmellB", basePath = basePath), - createFindingForRelativePath(ruleName = "TestSmellC", basePath = basePath) - ) - - val report = SarifOutputReport() - .apply { - init( - EmptySetupContext().apply { - register(DETEKT_OUTPUT_REPORT_BASE_PATH_KEY, Paths.get(basePath)) - } - ) - } - .render(result) - .stripWhitespace() + assertThat(report).isEqualToIgnoringWhitespace(readResourceContent("vanilla.sarif.json")) + } - val expectedReport = readResourceContent("relative_path.sarif.json") + @Test + fun `renders multiple issues with relative path`() { + val basePath = "/Users/tester/detekt/" + val result = TestDetektion( + createFindingForRelativePath(ruleName = "TestSmellA", basePath = basePath), + createFindingForRelativePath(ruleName = "TestSmellB", basePath = basePath), + createFindingForRelativePath(ruleName = "TestSmellC", basePath = basePath) + ) - // Note: Github CI uses D: drive, but it could be any drive for local development - val systemAwareExpectedReport = if (whichOS().startsWith("windows", ignoreCase = true)) { - val winRoot = Paths.get("/").toAbsolutePath().toString().replace("\\", "/") - expectedReport.replace("file:///", "file://$winRoot") - } else { - expectedReport + val report = SarifOutputReport() + .apply { + init( + EmptySetupContext().apply { + register(DETEKT_OUTPUT_REPORT_BASE_PATH_KEY, Paths.get(basePath)) + } + ) } + .render(result) + .stripWhitespace() + + val expectedReport = readResourceContent("relative_path.sarif.json") - assertThat(report).isEqualToIgnoringWhitespace(systemAwareExpectedReport) + // Note: Github CI uses D: drive, but it could be any drive for local development + val systemAwareExpectedReport = if (whichOS().startsWith("windows", ignoreCase = true)) { + val winRoot = Paths.get("/").toAbsolutePath().toString().replace("\\", "/") + expectedReport.replace("file:///", "file://$winRoot") + } else { + expectedReport } + + assertThat(report).isEqualToIgnoringWhitespace(systemAwareExpectedReport) } } diff --git a/detekt-report-txt/src/test/kotlin/io/github/detekt/report/txt/TxtOutputReportSpec.kt b/detekt-report-txt/src/test/kotlin/io/github/detekt/report/txt/TxtOutputReportSpec.kt index 5cf1f41efaf..4669738b4a9 100644 --- a/detekt-report-txt/src/test/kotlin/io/github/detekt/report/txt/TxtOutputReportSpec.kt +++ b/detekt-report-txt/src/test/kotlin/io/github/detekt/report/txt/TxtOutputReportSpec.kt @@ -3,45 +3,40 @@ package io.github.detekt.report.txt import io.gitlab.arturbosch.detekt.test.TestDetektion import io.gitlab.arturbosch.detekt.test.createFinding import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class TxtOutputReportSpec { - @Nested - inner class `TXT output report` { - - @Test - fun `renders none`() { - val report = TxtOutputReport() - val detektion = TestDetektion() - val renderedText = "" - assertThat(report.render(detektion)).isEqualTo(renderedText) - } + @Test + fun `renders none`() { + val report = TxtOutputReport() + val detektion = TestDetektion() + val renderedText = "" + assertThat(report.render(detektion)).isEqualTo(renderedText) + } - @Test - fun `renders one`() { - val report = TxtOutputReport() - val detektion = TestDetektion(createFinding()) - val renderedText = "TestSmell - [TestEntity] at TestFile.kt:1:1 - Signature=TestEntitySignature\n" - assertThat(report.render(detektion)).isEqualTo(renderedText) - } + @Test + fun `renders one`() { + val report = TxtOutputReport() + val detektion = TestDetektion(createFinding()) + val renderedText = "TestSmell - [TestEntity] at TestFile.kt:1:1 - Signature=TestEntitySignature\n" + assertThat(report.render(detektion)).isEqualTo(renderedText) + } - @Test - fun `renders multiple`() { - val report = TxtOutputReport() - val detektion = TestDetektion( - createFinding(ruleName = "TestSmellA"), - createFinding(ruleName = "TestSmellB"), - createFinding(ruleName = "TestSmellC") - ) - val renderedText = """ - TestSmellA - [TestEntity] at TestFile.kt:1:1 - Signature=TestEntitySignature - TestSmellB - [TestEntity] at TestFile.kt:1:1 - Signature=TestEntitySignature - TestSmellC - [TestEntity] at TestFile.kt:1:1 - Signature=TestEntitySignature + @Test + fun `renders multiple`() { + val report = TxtOutputReport() + val detektion = TestDetektion( + createFinding(ruleName = "TestSmellA"), + createFinding(ruleName = "TestSmellB"), + createFinding(ruleName = "TestSmellC") + ) + val renderedText = """ + TestSmellA - [TestEntity] at TestFile.kt:1:1 - Signature=TestEntitySignature + TestSmellB - [TestEntity] at TestFile.kt:1:1 - Signature=TestEntitySignature + TestSmellC - [TestEntity] at TestFile.kt:1:1 - Signature=TestEntitySignature - """.trimIndent() - assertThat(report.render(detektion)).isEqualTo(renderedText) - } + """.trimIndent() + assertThat(report.render(detektion)).isEqualTo(renderedText) } } diff --git a/detekt-report-xml/src/test/kotlin/io/github/detekt/report/xml/XmlOutputFormatSpec.kt b/detekt-report-xml/src/test/kotlin/io/github/detekt/report/xml/XmlOutputFormatSpec.kt index c328fbf78be..d88ebab00ed 100644 --- a/detekt-report-xml/src/test/kotlin/io/github/detekt/report/xml/XmlOutputFormatSpec.kt +++ b/detekt-report-xml/src/test/kotlin/io/github/detekt/report/xml/XmlOutputFormatSpec.kt @@ -35,7 +35,7 @@ class XmlOutputFormatSpec { FilePath.fromAbsolute(Paths.get("src/main/com/sample/Sample1.kt")) ) ) - val entity2 = Entity( + private val entity2 = Entity( "Sample2", "", Location( @@ -46,174 +46,170 @@ class XmlOutputFormatSpec { ) private val outputFormat = XmlOutputReport() - @Nested - inner class `XML output format` { - - @Test - fun `renders empty report`() { - val result = outputFormat.render(TestDetektion()) + @Test + fun `renders empty report`() { + val result = outputFormat.render(TestDetektion()) - assertThat(result).isEqualTo( - """ - - - - """.trimIndent() - ) - } + assertThat(result).isEqualTo( + """ + + + + """.trimIndent() + ) + } - @Test - fun `renders one reported issue in single file`() { - val smell = CodeSmell(Issue("id_a", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity1, message = "") + @Test + fun `renders one reported issue in single file`() { + val smell = CodeSmell(Issue("id_a", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity1, message = "") + + val result = outputFormat.render(TestDetektion(smell)) + + assertThat(result).isEqualTo( + """ + + + + $TAB + + + """.trimIndent() + ) + } - val result = outputFormat.render(TestDetektion(smell)) + @Test + fun `renders two reported issues in single file`() { + val smell1 = CodeSmell(Issue("id_a", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity1, message = "") + val smell2 = CodeSmell(Issue("id_b", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity1, message = "") + + val result = outputFormat.render(TestDetektion(smell1, smell2)) + + assertThat(result).isEqualTo( + """ + + + + $TAB + $TAB + + + """.trimIndent() + ) + } - assertThat(result).isEqualTo( - """ - - - - $TAB - - - """.trimIndent() - ) - } + @Test + fun `renders one reported issue across multiple files`() { + val smell1 = CodeSmell(Issue("id_a", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity1, message = "") + val smell2 = CodeSmell(Issue("id_a", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity2, message = "") + + val result = outputFormat.render(TestDetektion(smell1, smell2)) + + assertThat(result).isEqualTo( + """ + + + + $TAB + + + $TAB + + + """.trimIndent() + ) + } - @Test - fun `renders two reported issues in single file`() { - val smell1 = CodeSmell(Issue("id_a", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity1, message = "") - val smell2 = CodeSmell(Issue("id_b", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity1, message = "") + @Test + fun `renders issues with relative path`() { + val findingA = createFindingForRelativePath( + ruleName = "id_a", + basePath = "/Users/tester/detekt/", + relativePath = "Sample1.kt" + ) + val findingB = createFindingForRelativePath( + ruleName = "id_b", + basePath = "/Users/tester/detekt/", + relativePath = "Sample2.kt" + ) - val result = outputFormat.render(TestDetektion(smell1, smell2)) + val result = outputFormat.render(TestDetektion(findingA, findingB)) + + assertThat(result).isEqualTo( + """ + + + + $TAB + + + $TAB + + + """.trimIndent() + ) + } - assertThat(result).isEqualTo( - """ - - - - $TAB - $TAB - - - """.trimIndent() + @Test + fun `renders two reported issues across multiple files`() { + val smell1 = CodeSmell(Issue("id_a", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity1, message = "") + val smell2 = CodeSmell(Issue("id_b", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity1, message = "") + val smell3 = CodeSmell(Issue("id_a", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity2, message = "") + val smell4 = CodeSmell(Issue("id_b", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity2, message = "") + + val result = outputFormat.render( + TestDetektion( + smell1, + smell2, + smell3, + smell4 ) - } + ) - @Test - fun `renders one reported issue across multiple files`() { - val smell1 = CodeSmell(Issue("id_a", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity1, message = "") - val smell2 = CodeSmell(Issue("id_a", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity2, message = "") + assertThat(result).isEqualTo( + """ + + + + $TAB + $TAB + + + $TAB + $TAB + + + """.trimIndent() + ) + } - val result = outputFormat.render(TestDetektion(smell1, smell2)) + @Nested + inner class `severity level conversion` { + + @ParameterizedTest + @EnumSource(SeverityLevel::class) + fun `renders detektion with severity as XML with severity`(severity: SeverityLevel) { + val xmlSeverity = severity.name.toLowerCase(Locale.US) + val finding = object : CodeSmell( + issue = Issue("issue_id", Severity.CodeSmell, "issue description", Debt.FIVE_MINS), + entity = entity1, + message = "message" + ) { + override val severity: SeverityLevel + get() = severity + } - assertThat(result).isEqualTo( - """ + val expected = """ - $TAB - - - $TAB + $TAB - """.trimIndent() - ) - } + """ - @Test - fun `renders issues with relative path`() { - val findingA = createFindingForRelativePath( - ruleName = "id_a", - basePath = "/Users/tester/detekt/", - relativePath = "Sample1.kt" - ) - val findingB = createFindingForRelativePath( - ruleName = "id_b", - basePath = "/Users/tester/detekt/", - relativePath = "Sample2.kt" - ) + val actual = outputFormat.render(TestDetektion(finding)) - val result = outputFormat.render(TestDetektion(findingA, findingB)) - - assertThat(result).isEqualTo( - """ - - - - $TAB - - - $TAB - - - """.trimIndent() - ) - } - - @Test - fun `renders two reported issues across multiple files`() { - val smell1 = CodeSmell(Issue("id_a", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity1, message = "") - val smell2 = CodeSmell(Issue("id_b", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity1, message = "") - val smell3 = CodeSmell(Issue("id_a", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity2, message = "") - val smell4 = CodeSmell(Issue("id_b", Severity.CodeSmell, "", Debt.TWENTY_MINS), entity2, message = "") - - val result = outputFormat.render( - TestDetektion( - smell1, - smell2, - smell3, - smell4 - ) - ) - - assertThat(result).isEqualTo( - """ - - - - $TAB - $TAB - - - $TAB - $TAB - - - """.trimIndent() - ) - } - - @Nested - inner class `severity level conversion` { - - @ParameterizedTest - @EnumSource(SeverityLevel::class) - fun `renders detektion with severity as XML with severity`(severity: SeverityLevel) { - val xmlSeverity = severity.name.toLowerCase(Locale.US) - val finding = object : CodeSmell( - issue = Issue("issue_id", Severity.CodeSmell, "issue description", Debt.FIVE_MINS), - entity = entity1, - message = "message" - ) { - override val severity: SeverityLevel - get() = severity - } - - val expected = """ - - - - $TAB - - - """ - - val actual = outputFormat.render(TestDetektion(finding)) - - assertThat(actual).isEqualTo(expected.trimIndent()) - } + assertThat(actual).isEqualTo(expected.trimIndent()) } } } diff --git a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexConditionSpec.kt b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexConditionSpec.kt index c3aae0b8fe4..19a514565ac 100644 --- a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexConditionSpec.kt +++ b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexConditionSpec.kt @@ -2,26 +2,21 @@ package io.gitlab.arturbosch.detekt.rules.complexity import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ComplexConditionSpec { - @Nested - inner class `ComplexCondition rule` { + val code = """ + val a = if (5 > 4 && 4 < 6 || (3 < 5 || 2 < 5)) { 42 } else { 24 } - val code = """ - val a = if (5 > 4 && 4 < 6 || (3 < 5 || 2 < 5)) { 42 } else { 24 } - - fun complexConditions() { - while (5 > 4 && 4 < 6 || (3 < 5 || 2 < 5)) {} - do { } while (5 > 4 && 4 < 6 || (3 < 5 || 2 < 5)) - } - """ - - @Test - fun `reports some complex conditions`() { - assertThat(ComplexCondition().compileAndLint(code)).hasSize(3) + fun complexConditions() { + while (5 > 4 && 4 < 6 || (3 < 5 || 2 < 5)) {} + do { } while (5 > 4 && 4 < 6 || (3 < 5 || 2 < 5)) } + """ + + @Test + fun `reports some complex conditions`() { + assertThat(ComplexCondition().compileAndLint(code)).hasSize(3) } } diff --git a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexMethodSpec.kt b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexMethodSpec.kt index 158ebfe4e1a..e66fc783ab7 100644 --- a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexMethodSpec.kt +++ b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexMethodSpec.kt @@ -17,221 +17,217 @@ class ComplexMethodSpec { val defaultComplexity = 1 @Nested - inner class `ComplexMethod rule` { - - @Nested - inner class `different complex constructs` { - - @Test - fun `counts different loops`() { - val findings = ComplexMethod(TestConfig(defaultConfigMap)).compileAndLint( - """ - fun test() { - for (i in 1..10) {} - while (true) {} - do {} while(true) - (1..10).forEach {} - } - """ - ) + inner class `different complex constructs` { - assertThat(findings.first()).isThresholded().withValue(defaultComplexity + 4) - } + @Test + fun `counts different loops`() { + val findings = ComplexMethod(TestConfig(defaultConfigMap)).compileAndLint( + """ + fun test() { + for (i in 1..10) {} + while (true) {} + do {} while(true) + (1..10).forEach {} + } + """ + ) - @Test - fun `counts catch blocks`() { - val findings = ComplexMethod(TestConfig(defaultConfigMap)).compileAndLint( - """ - fun test() { - try {} catch(e: IllegalArgumentException) {} catch(e: Exception) {} finally {} - } - """ - ) + assertThat(findings.first()).isThresholded().withValue(defaultComplexity + 4) + } - assertThat(findings.first()).isThresholded().withValue(defaultComplexity + 2) - } + @Test + fun `counts catch blocks`() { + val findings = ComplexMethod(TestConfig(defaultConfigMap)).compileAndLint( + """ + fun test() { + try {} catch(e: IllegalArgumentException) {} catch(e: Exception) {} finally {} + } + """ + ) + + assertThat(findings.first()).isThresholded().withValue(defaultComplexity + 2) + } - @Test - fun `counts nested conditional statements`() { - val findings = ComplexMethod(TestConfig(defaultConfigMap)).compileAndLint( - """ - fun test() { - try { - while (true) { - if (true) { - when ("string") { - "" -> println() - else -> println() - } + @Test + fun `counts nested conditional statements`() { + val findings = ComplexMethod(TestConfig(defaultConfigMap)).compileAndLint( + """ + fun test() { + try { + while (true) { + if (true) { + when ("string") { + "" -> println() + else -> println() } } - } finally { - // only catches count } + } finally { + // only catches count } - """ - ) + } + """ + ) - assertThat(findings.first()).isThresholded().withValue(defaultComplexity + 4) - } + assertThat(findings.first()).isThresholded().withValue(defaultComplexity + 4) } + } - @Nested - inner class `nesting functions` { + @Nested + inner class `nesting functions` { - val code = """ - fun test() { - for (i in 1..10) {} - (1..10).forEach {} - } - """ + val code = """ + fun test() { + for (i in 1..10) {} + (1..10).forEach {} + } + """ - @Test - fun `counts three with nesting function 'forEach'`() { - val config = TestConfig(defaultConfigMap.plus("ignoreNestingFunctions" to "false")) - assertExpectedComplexityValue(code, config, expectedValue = 3) - } + @Test + fun `counts three with nesting function 'forEach'`() { + val config = TestConfig(defaultConfigMap.plus("ignoreNestingFunctions" to "false")) + assertExpectedComplexityValue(code, config, expectedValue = 3) + } - @Test - fun `can ignore nesting functions like 'forEach'`() { - val config = TestConfig(defaultConfigMap.plus("ignoreNestingFunctions" to "true")) - assertExpectedComplexityValue(code, config, expectedValue = 2) - } + @Test + fun `can ignore nesting functions like 'forEach'`() { + val config = TestConfig(defaultConfigMap.plus("ignoreNestingFunctions" to "true")) + assertExpectedComplexityValue(code, config, expectedValue = 2) + } - @Test - fun `skips all if if the nested functions is empty`() { - val config = TestConfig(defaultConfigMap.plus("nestingFunctions" to "")) - assertExpectedComplexityValue(code, config, expectedValue = 2) - } + @Test + fun `skips all if if the nested functions is empty`() { + val config = TestConfig(defaultConfigMap.plus("nestingFunctions" to "")) + assertExpectedComplexityValue(code, config, expectedValue = 2) + } - @Test - fun `skips 'forEach' as it is not specified`() { - val config = TestConfig(defaultConfigMap.plus("nestingFunctions" to "let,apply,also")) - assertExpectedComplexityValue(code, config, expectedValue = 2) - } + @Test + fun `skips 'forEach' as it is not specified`() { + val config = TestConfig(defaultConfigMap.plus("nestingFunctions" to "let,apply,also")) + assertExpectedComplexityValue(code, config, expectedValue = 2) + } - @Test - fun `skips 'forEach' as it is not specified list`() { - val config = TestConfig(defaultConfigMap.plus("nestingFunctions" to listOf("let", "apply", "also"))) - assertExpectedComplexityValue(code, config, expectedValue = 2) - } + @Test + fun `skips 'forEach' as it is not specified list`() { + val config = TestConfig(defaultConfigMap.plus("nestingFunctions" to listOf("let", "apply", "also"))) + assertExpectedComplexityValue(code, config, expectedValue = 2) } + } - @Nested - inner class `several complex methods` { + @Nested + inner class `several complex methods` { - val path = resourceAsPath("ComplexMethods.kt") + val path = resourceAsPath("ComplexMethods.kt") - @Test - fun `does not report complex methods with a single when expression`() { - val config = TestConfig( - mapOf( - "threshold" to "4", - "ignoreSingleWhenExpression" to "true" - ) + @Test + fun `does not report complex methods with a single when expression`() { + val config = TestConfig( + mapOf( + "threshold" to "4", + "ignoreSingleWhenExpression" to "true" ) - val subject = ComplexMethod(config) + ) + val subject = ComplexMethod(config) - assertThat(subject.lint(path)).hasSourceLocations(SourceLocation(43, 5)) - } + assertThat(subject.lint(path)).hasSourceLocations(SourceLocation(43, 5)) + } - @Test - fun `reports all complex methods`() { - val config = TestConfig(mapOf("threshold" to "4")) - val subject = ComplexMethod(config) - - assertThat(subject.lint(path)).hasSourceLocations( - SourceLocation(6, 5), - SourceLocation(15, 5), - SourceLocation(25, 5), - SourceLocation(35, 5), - SourceLocation(43, 5) - ) - } + @Test + fun `reports all complex methods`() { + val config = TestConfig(mapOf("threshold" to "4")) + val subject = ComplexMethod(config) + + assertThat(subject.lint(path)).hasSourceLocations( + SourceLocation(6, 5), + SourceLocation(15, 5), + SourceLocation(25, 5), + SourceLocation(35, 5), + SourceLocation(43, 5) + ) + } - @Test - fun `does not trip for a reasonable amount of simple when entries when ignoreSimpleWhenEntries is true`() { - val config = TestConfig(mapOf("ignoreSimpleWhenEntries" to "true")) - val subject = ComplexMethod(config) - val code = """ - fun f() { - val map = HashMap() - for ((key, value) in map) { - when (key) { - is Int -> print("int") - is String -> print("String") - is Float -> print("Float") - is Double -> print("Double") - is Byte -> print("Byte") - is Short -> print("Short") - is Long -> print("Long") - is Boolean -> print("Boolean") - else -> throw IllegalArgumentException("Unexpected type value") - } + @Test + fun `does not trip for a reasonable amount of simple when entries when ignoreSimpleWhenEntries is true`() { + val config = TestConfig(mapOf("ignoreSimpleWhenEntries" to "true")) + val subject = ComplexMethod(config) + val code = """ + fun f() { + val map = HashMap() + for ((key, value) in map) { + when (key) { + is Int -> print("int") + is String -> print("String") + is Float -> print("Float") + is Double -> print("Double") + is Byte -> print("Byte") + is Short -> print("Short") + is Long -> print("Long") + is Boolean -> print("Boolean") + else -> throw IllegalArgumentException("Unexpected type value") } } - """ + } + """ - val findings = subject.compileAndLint(code) - assertThat(findings).isEmpty() - } + val findings = subject.compileAndLint(code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `function containing object literal with many overridden functions` { + @Nested + inner class `function containing object literal with many overridden functions` { - val code = """ - fun f(): List { - return object : List { - override val size: Int get() = TODO("not implemented") + val code = """ + fun f(): List { + return object : List { + override val size: Int get() = TODO("not implemented") - override fun contains(element: Any): Boolean { - TODO("not implemented") - } + override fun contains(element: Any): Boolean { + TODO("not implemented") + } - override fun containsAll(elements: Collection): Boolean { - TODO("not implemented") - } + override fun containsAll(elements: Collection): Boolean { + TODO("not implemented") + } - override fun get(index: Int): Any { - TODO("not implemented") - } + override fun get(index: Int): Any { + TODO("not implemented") + } - override fun indexOf(element: Any): Int { - TODO("not implemented") - } + override fun indexOf(element: Any): Int { + TODO("not implemented") + } - override fun isEmpty(): Boolean { - TODO("not implemented") - } + override fun isEmpty(): Boolean { + TODO("not implemented") + } - override fun iterator(): Iterator { - TODO("not implemented") - } + override fun iterator(): Iterator { + TODO("not implemented") + } - override fun lastIndexOf(element: Any): Int { - TODO("not implemented") - } + override fun lastIndexOf(element: Any): Int { + TODO("not implemented") + } - override fun listIterator(): ListIterator { - TODO("not implemented") - } + override fun listIterator(): ListIterator { + TODO("not implemented") + } - override fun listIterator(index: Int): ListIterator { - TODO("not implemented") - } + override fun listIterator(index: Int): ListIterator { + TODO("not implemented") + } - override fun subList(fromIndex: Int, toIndex: Int): List { - TODO("not implemented") - } + override fun subList(fromIndex: Int, toIndex: Int): List { + TODO("not implemented") } } - """ + } + """ - @Test - fun `should not count these overridden functions to base functions complexity`() { - assertThat(ComplexMethod().compileAndLint(code)).isEmpty() - } + @Test + fun `should not count these overridden functions to base functions complexity`() { + assertThat(ComplexMethod().compileAndLint(code)).isEmpty() } } } 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 f5d10775f3a..d96a5ae791f 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 @@ -3,174 +3,169 @@ 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.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class LabeledExpressionSpec { private val subject = LabeledExpression() - @Nested - inner class `LabeledExpression rule` { - - @Test - fun `reports break and continue labels`() { - val code = """ - fun f() { - loop@ for (i in 1..3) { - for (j in 1..3) { - if (j == 4) break@loop - if (j == 5) continue@loop - } - } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(3) - } - - @Test - fun `reports implicit return label`() { - val code = """ - fun f(range: IntRange) { - range.forEach { - if (it == 5) return@forEach - println(it) + @Test + fun `reports break and continue labels`() { + val code = """ + fun f() { + loop@ for (i in 1..3) { + for (j in 1..3) { + if (j == 4) break@loop + if (j == 5) continue@loop } } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(3) + } - @Test - fun `reports explicit return label`() { - val code = """ - fun f(range: IntRange) { - range.forEach label@{ - if (it == 5) return@label - println(it) - } + @Test + fun `reports implicit return label`() { + val code = """ + fun f(range: IntRange) { + range.forEach { + if (it == 5) return@forEach + println(it) } - """ - assertThat(subject.compileAndLint(code)).hasSize(2) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports labels referencing inner and outer class`() { - val code = """ - class Outer { - inner class Inner { - fun f() { - val i = this@Inner - emptyList().forEach Outer@{ - // references forEach label and not outer class - if (it == 5) return@Outer - println(it) - } - } - } + @Test + fun `reports explicit return label`() { + val code = """ + fun f(range: IntRange) { + range.forEach label@{ + if (it == 5) return@label + println(it) } - """ - assertThat(subject.compileAndLint(code)).hasSize(3) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(2) + } - @Test - fun `does not report inner class referencing outer class`() { - val code = """ + @Test + fun `reports labels referencing inner and outer class`() { + val code = """ class Outer { inner class Inner { fun f() { - print(this@Outer) + val i = this@Inner + emptyList().forEach Outer@{ + // references forEach label and not outer class + if (it == 5) return@Outer + println(it) + } } } } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + """ + assertThat(subject.compileAndLint(code)).hasSize(3) + } - @Test - fun `does not report inner class referencing outer class in extension function`() { - val code = """ - class Outer { - inner class Inner { - fun Int.f() { - print(this@Inner) - print(this@Outer) - } + @Test + fun `does not report inner class referencing outer class`() { + val code = """ + class Outer { + inner class Inner { + fun f() { + print(this@Outer) } } - """ - assertThat(subject.compileAndLint(code)).isEmpty() } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report nested class referencing outer class in extension function`() { - val code = """ - class Outer { - class Nested { - fun Int.f() { - print(this@Nested) - } + @Test + fun `does not report inner class referencing outer class in extension function`() { + val code = """ + class Outer { + inner class Inner { + fun Int.f() { + print(this@Inner) + print(this@Outer) } } - """ - assertThat(subject.compileAndLint(code)).isEmpty() } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report inner classes referencing outer class in extension function`() { - val code = """ - class Outer { - inner class Inner { - inner class InnerInner { - fun f() { - print(this@Outer) - print(this@Inner) - } - fun Int.f() { - print(this@Inner) - print(this@InnerInner) - } - } + @Test + fun `does not report nested class referencing outer class in extension function`() { + val code = """ + class Outer { + class Nested { + fun Int.f() { + print(this@Nested) } } - """ - assertThat(subject.compileAndLint(code)).isEmpty() } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report excluded label`() { - val code = """ - fun f() { - loop@ for (i in 1..5) {} + @Test + fun `does not report inner classes referencing outer class in extension function`() { + val code = """ + class Outer { + inner class Inner { + inner class InnerInner { + fun f() { + print(this@Outer) + print(this@Inner) + } + fun Int.f() { + print(this@Inner) + print(this@InnerInner) + } } - """ - val config = TestConfig(mapOf("ignoredLabels" to listOf("loop"))) - val findings = LabeledExpression(config).compileAndLint(code) - assertThat(findings).isEmpty() + } } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report excluded label config with string`() { - val code = """ - fun f() { - loop@ for (i in 1..5) {} - } - """ - val config = TestConfig(mapOf("ignoredLabels" to "loop")) - val findings = LabeledExpression(config).compileAndLint(code) - assertThat(findings).isEmpty() - } + @Test + fun `does not report excluded label`() { + val code = """ + fun f() { + loop@ for (i in 1..5) {} + } + """ + val config = TestConfig(mapOf("ignoredLabels" to listOf("loop"))) + val findings = LabeledExpression(config).compileAndLint(code) + assertThat(findings).isEmpty() + } - @Test - fun `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() - } + @Test + fun `does not report excluded label config with string`() { + val code = """ + fun f() { + loop@ for (i in 1..5) {} + } + """ + val config = TestConfig(mapOf("ignoredLabels" to "loop")) + val findings = LabeledExpression(config).compileAndLint(code) + assertThat(findings).isEmpty() + } + + @Test + fun `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/LongMethodSpec.kt b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LongMethodSpec.kt index 17bda728070..e5e521a9350 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 @@ -4,158 +4,153 @@ 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.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class LongMethodSpec { val subject = LongMethod(TestConfig(mapOf("threshold" to 5))) - @Nested - inner class `nested functions can be long` { - - @Test - fun `should find two long methods`() { - val code = """ - fun longMethod() { // 5 lines + @Test + fun `should find two long methods`() { + val code = """ + fun longMethod() { // 5 lines + println() + println() + println() + + fun nestedLongMethod() { // 5 lines println() println() println() - - fun nestedLongMethod() { // 5 lines - println() - println() - println() - } } - """ - val findings = subject.compileAndLint(code) + } + """ + val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(2) - assertThat(findings).hasTextLocations("longMethod", "nestedLongMethod") - } + assertThat(findings).hasSize(2) + assertThat(findings).hasTextLocations("longMethod", "nestedLongMethod") + } - @Test - fun `should not find too long methods`() { - val code = """ - fun methodOk() { // 3 lines - println() - fun localMethodOk() { // 4 lines - println() - println() - } - } - """ - - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `should not find too long method with params on newlines`() { - val code = """ - fun methodWithParams( - param1: String - ) { // 4 lines + @Test + fun `should not find too long methods`() { + val code = """ + fun methodOk() { // 3 lines + println() + fun localMethodOk() { // 4 lines println() println() } - """ + } + """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `should find too long method with params on newlines`() { - val code = """ - fun longMethodWithParams( - param1: String - ) { // 5 lines - println() - println() - println() - } - """ - - val findings = subject.compileAndLint(code) - - assertThat(findings).hasSize(1) - assertThat(findings[0] as ThresholdedCodeSmell).hasValue(5) - } - - @Test - fun `should find long method with method call with params on separate lines`() { - val code = """ - fun longMethod( - x1: Int, - x2: Int, - y1: Int, - y2: Int - ) { // 8 lines - listOf( - x1, - y1, - x2, - y2 - ) - } - """ + @Test + fun `should not find too long method with params on newlines`() { + val code = """ + fun methodWithParams( + param1: String + ) { // 4 lines + println() + println() + } + """ + + assertThat(subject.compileAndLint(code)).isEmpty() + } - val findings = subject.compileAndLint(code) + @Test + fun `should find too long method with params on newlines`() { + val code = """ + fun longMethodWithParams( + param1: String + ) { // 5 lines + println() + println() + println() + } + """ + + val findings = subject.compileAndLint(code) + + assertThat(findings).hasSize(1) + assertThat(findings[0] as ThresholdedCodeSmell).hasValue(5) + } - assertThat(findings).hasSize(1) - assertThat(findings[0] as ThresholdedCodeSmell).hasValue(8) - } + @Test + fun `should find long method with method call with params on separate lines`() { + val code = """ + fun longMethod( + x1: Int, + x2: Int, + y1: Int, + y2: Int + ) { // 8 lines + listOf( + x1, + y1, + x2, + y2 + ) + } + """ + + val findings = subject.compileAndLint(code) + + assertThat(findings).hasSize(1) + assertThat(findings[0] as ThresholdedCodeSmell).hasValue(8) + } - @Test - fun `should find two long methods with params on separate lines`() { - val code = """ - fun longMethod( + @Test + fun `should find two long methods with params on separate lines`() { + val code = """ + fun longMethod( + param1: String + ) { // 5 lines + println() + println() + println() + + fun nestedLongMethod( param1: String ) { // 5 lines println() println() println() - - fun nestedLongMethod( - param1: String - ) { // 5 lines - println() - println() - println() - } } - """ + } + """ - val findings = subject.compileAndLint(code) + val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(2) - assertThat(findings).hasTextLocations("longMethod", "nestedLongMethod") - } + assertThat(findings).hasSize(2) + assertThat(findings).hasTextLocations("longMethod", "nestedLongMethod") + } - @Test - fun `should find nested long methods with params on separate lines`() { - val code = """ - fun longMethod( + @Test + fun `should find nested long methods with params on separate lines`() { + val code = """ + fun longMethod( + param1: String + ) { // 4 lines + println() + println() + + fun nestedLongMethod( param1: String - ) { // 4 lines + ) { // 5 lines + println() println() println() - - fun nestedLongMethod( - param1: String - ) { // 5 lines - println() - println() - println() - } } - """ + } + """ - val findings = subject.compileAndLint(code) + val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(1) - assertThat(findings).hasTextLocations("nestedLongMethod") - assertThat(findings[0] as ThresholdedCodeSmell).hasValue(5) - } + assertThat(findings).hasSize(1) + assertThat(findings).hasTextLocations("nestedLongMethod") + assertThat(findings[0] as ThresholdedCodeSmell).hasValue(5) } } 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 e9be5404f70..3c2222b606f 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 @@ -19,145 +19,141 @@ class LongParameterListSpec { val subject = LongParameterList(defaultConfig) - @Nested - inner class `LongParameterList rule` { + val reportMessageForFunction = "The function long(a: Int, b: Int) has too many parameters. " + + "The current threshold is set to $defaultThreshold." + val reportMessageForConstructor = "The constructor(a: Int, b: Int) has too many parameters. " + + "The current threshold is set to $defaultThreshold." + + @Test + fun `reports too long parameter list`() { + val code = "fun long(a: Int, b: Int) {}" + val findings = subject.compileAndLint(code) + assertThat(findings).hasSize(1) + assertThat(findings.first().message).isEqualTo(reportMessageForFunction) + } - val reportMessageForFunction = "The function long(a: Int, b: Int) has too many parameters. " + - "The current threshold is set to $defaultThreshold." - val reportMessageForConstructor = "The constructor(a: Int, b: Int) has too many parameters. " + - "The current threshold is set to $defaultThreshold." + @Test + fun `does not report short parameter list`() { + val code = "fun long(a: Int) {}" + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports too long parameter list`() { - val code = "fun long(a: Int, b: Int) {}" - val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(1) - assertThat(findings.first().message).isEqualTo(reportMessageForFunction) - } + @Test + fun `reports too long parameter list event for parameters with defaults`() { + val code = "fun long(a: Int, b: Int = 1) {}" + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report short parameter list`() { - val code = "fun long(a: Int) {}" - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report long parameter list if parameters with defaults should be ignored`() { + 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() + } - @Test - fun `reports too long parameter list event for parameters with defaults`() { - val code = "fun long(a: Int, b: Int = 1) {}" - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports too long parameter list for primary constructors`() { + val code = "class LongCtor(a: Int, b: Int)" + val findings = subject.compileAndLint(code) + assertThat(findings).hasSize(1) + assertThat(findings.first().message).isEqualTo(reportMessageForConstructor) + } - @Test - fun `does not report long parameter list if parameters with defaults should be ignored`() { - 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() - } + @Test + fun `does not report short parameter list for primary constructors`() { + val code = "class LongCtor(a: Int)" + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports too long parameter list for primary constructors`() { - val code = "class LongCtor(a: Int, b: Int)" - val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(1) - assertThat(findings.first().message).isEqualTo(reportMessageForConstructor) - } + @Test + fun `reports too long parameter list for secondary constructors`() { + val code = "class LongCtor() { constructor(a: Int, b: Int) : this() }" + val findings = subject.compileAndLint(code) + assertThat(findings).hasSize(1) + assertThat(findings.first().message).isEqualTo(reportMessageForConstructor) + } - @Test - fun `does not report short parameter list for primary constructors`() { - val code = "class LongCtor(a: Int)" - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report short parameter list for secondary constructors`() { + val code = "class LongCtor() { constructor(a: Int) : this() }" + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports too long parameter list for secondary constructors`() { - val code = "class LongCtor() { constructor(a: Int, b: Int) : this() }" - val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(1) - assertThat(findings.first().message).isEqualTo(reportMessageForConstructor) - } + @Test + fun `reports long parameter list if custom threshold is set`() { + val config = TestConfig(mapOf("constructorThreshold" to "1")) + val rule = LongParameterList(config) + val code = "class LongCtor(a: Int)" + assertThat(rule.compileAndLint(code)).hasSize(1) + } + + @Test + fun `does not report long parameter list for constructors of data classes if asked`() { + val config = TestConfig( + mapOf( + "ignoreDataClasses" to "true", + "constructorThreshold" to "1" + ) + ) + val rule = LongParameterList(config) + val code = "data class Data(val a: Int)" + assertThat(rule.compileAndLint(code)).isEmpty() + } + + @Nested + inner class `constructors and functions with ignored annotations` { + + val config = + TestConfig( + mapOf( + "ignoreAnnotatedParameter" to listOf( + "Generated", + "kotlin.Deprecated", + "kotlin.jvm.JvmName", + "kotlin.Suppress" + ), + "functionThreshold" to 1, + "constructorThreshold" to 1 + ) + ) + + val rule = LongParameterList(config) @Test - fun `does not report short parameter list for secondary constructors`() { - val code = "class LongCtor() { constructor(a: Int) : this() }" - assertThat(subject.compileAndLint(code)).isEmpty() + fun `reports long parameter list for constructors if constructor parameters are annotated with annotation that is not ignored`() { + val code = """ + @Target(AnnotationTarget.VALUE_PARAMETER) + annotation class CustomAnnotation + + class Data constructor(@CustomAnnotation val a: Int) + """ + assertThat(rule.compileAndLint(code)).hasSize(1) } @Test - fun `reports long parameter list if custom threshold is set`() { - val config = TestConfig(mapOf("constructorThreshold" to "1")) - val rule = LongParameterList(config) - val code = "class LongCtor(a: Int)" + fun `reports long parameter list for functions if enough function parameters are annotated with annotation that is not ignored`() { + val code = """ + @Target(AnnotationTarget.VALUE_PARAMETER) + annotation class CustomAnnotation + + class Data { fun foo(@CustomAnnotation a: Int) {} } + """ assertThat(rule.compileAndLint(code)).hasSize(1) } @Test - fun `does not report long parameter list for constructors of data classes if asked`() { - val config = TestConfig( - mapOf( - "ignoreDataClasses" to "true", - "constructorThreshold" to "1" - ) - ) - val rule = LongParameterList(config) - val code = "data class Data(val a: Int)" + fun `does not report long parameter list for constructors if enough constructor parameters are annotated with ignored annotation`() { + val code = "class Data constructor(@kotlin.Suppress(\"\") val a: Int)" assertThat(rule.compileAndLint(code)).isEmpty() } - @Nested - inner class `constructors and functions with ignored annotations` { - - val config = - TestConfig( - mapOf( - "ignoreAnnotatedParameter" to listOf( - "Generated", - "kotlin.Deprecated", - "kotlin.jvm.JvmName", - "kotlin.Suppress" - ), - "functionThreshold" to 1, - "constructorThreshold" to 1 - ) - ) - - val rule = LongParameterList(config) - - @Test - fun `reports long parameter list for constructors if constructor parameters are annotated with annotation that is not ignored`() { - val code = """ - @Target(AnnotationTarget.VALUE_PARAMETER) - annotation class CustomAnnotation - - class Data constructor(@CustomAnnotation val a: Int) - """ - assertThat(rule.compileAndLint(code)).hasSize(1) - } - - @Test - fun `reports long parameter list for functions if enough function parameters are annotated with annotation that is not ignored`() { - val code = """ - @Target(AnnotationTarget.VALUE_PARAMETER) - annotation class CustomAnnotation - - class Data { fun foo(@CustomAnnotation a: Int) {} } - """ - assertThat(rule.compileAndLint(code)).hasSize(1) - } - - @Test - fun `does not report long parameter list for constructors if enough constructor parameters are annotated with ignored annotation`() { - val code = "class Data constructor(@kotlin.Suppress(\"\") val a: Int)" - assertThat(rule.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report long parameter list for functions if enough function parameters are annotated with ignored annotation`() { - val code = """class Data { - fun foo(@kotlin.Suppress("") a: Int) {} } - """ - assertThat(rule.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report long parameter list for functions if enough function parameters are annotated with ignored annotation`() { + val code = """class Data { + fun foo(@kotlin.Suppress("") a: Int) {} } + """ + assertThat(rule.compileAndLint(code)).isEmpty() } } } 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 e92808b5e58..6473ea4b66f 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 @@ -13,266 +13,262 @@ class MethodOverloadingSpec { val subject = MethodOverloading(defaultConfig) @Nested - inner class `MethodOverloading rule` { + inner class `several overloaded methods` { - @Nested - inner class `several overloaded methods` { - - @Test - fun `reports overloaded methods which exceed the threshold`() { - val code = """ - class Test { - fun x() {} - fun x(i: Int) {} - fun x(i: Int, j: Int) {} - } - """ - val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).isEqualTo("The method 'x' is overloaded 3 times.") - } - - @Test - fun `reports overloaded top level methods which exceed the threshold`() { - val code = """ + @Test + fun `reports overloaded methods which exceed the threshold`() { + val code = """ + class Test { fun x() {} fun x(i: Int) {} fun x(i: Int, j: Int) {} - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `does not report overloaded methods which do not exceed the threshold`() { - subject.compileAndLint( - """ - class Test { - fun x() { } - fun x(i: Int) { } } - """ - ) - assertThat(subject.findings.size).isZero() - } + """ + val findings = subject.compileAndLint(code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).isEqualTo("The method 'x' is overloaded 3 times.") } - @Nested - inner class `several overloaded extensions methods` { - - @Test - fun `does not report extension methods with a different receiver`() { - subject.compileAndLint( - """ - fun Boolean.foo() {} - fun Int.foo() {} - fun Long.foo() {} - """ - ) - assertThat(subject.findings.size).isZero() - } - - @Test - fun `reports extension methods with the same receiver`() { - subject.compileAndLint( - """ - fun Int.foo() {} - fun Int.foo(i: Int) {} - fun Int.foo(i: String) {} - """ - ) - assertThat(subject.findings.size).isEqualTo(1) - } + @Test + fun `reports overloaded top level methods which exceed the threshold`() { + val code = """ + fun x() {} + fun x(i: Int) {} + fun x(i: Int, j: Int) {} + """ + assertThat(subject.compileAndLint(code)).hasSize(1) } - @Nested - inner class `several nested overloaded methods` { - - @Test - fun `reports nested overloaded methods which exceed the threshold`() { - val code = """ - class Outer { - internal class Inner { - fun f() {} - fun f(i: Int) {} - fun f(i: Int, j: Int) {} - } - } + @Test + fun `does not report overloaded methods which do not exceed the threshold`() { + subject.compileAndLint( """ - assertThat(subject.compileAndLint(code)).hasSize(1) + class Test { + fun x() { } + fun x(i: Int) { } } + """ + ) + assertThat(subject.findings.size).isZero() + } + } - @Test - fun `does not report nested overloaded methods which do not exceed the threshold`() { - val code = """ - class Outer { + @Nested + inner class `several overloaded extensions methods` { - fun f() {} + @Test + fun `does not report extension methods with a different receiver`() { + subject.compileAndLint( + """ + fun Boolean.foo() {} + fun Int.foo() {} + fun Long.foo() {} + """ + ) + assertThat(subject.findings.size).isZero() + } - internal class Inner { - fun f(i: Int) {} - fun f(i: Int, j: Int) {} - } - } + @Test + fun `reports extension methods with the same receiver`() { + subject.compileAndLint( """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + fun Int.foo() {} + fun Int.foo(i: Int) {} + fun Int.foo(i: String) {} + """ + ) + assertThat(subject.findings.size).isEqualTo(1) } + } - @Nested - inner class `several overloaded methods inside objects` { + @Nested + inner class `several nested overloaded methods` { - @Test - fun `reports overloaded methods inside an object which exceed the threshold`() { - val code = """ - object Test { + @Test + fun `reports nested overloaded methods which exceed the threshold`() { + val code = """ + class Outer { + internal class Inner { fun f() {} fun f(i: Int) {} fun f(i: Int, j: Int) {} } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report overloaded methods inside an object which do not exceed the threshold`() { - val code = """ - object Test { - fun f() {} + @Test + fun `does not report nested overloaded methods which do not exceed the threshold`() { + val code = """ + class Outer { + + fun f() {} + + internal class Inner { fun f(i: Int) {} + fun f(i: Int, j: Int) {} } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + } - @Test - fun `reports overloaded methods inside a companion object which exceed the threshold`() { - val code = """ - class Test { - companion object { - fun f() {} - fun f(i: Int) {} - fun f(i: Int, j: Int) {} - } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Nested + inner class `several overloaded methods inside objects` { - @Test - fun `does not report overloaded methods in a companion object that do not exceed the threshold`() { - val code = """ - class Test { - companion object { - fun f() {} - fun f(i: Int) {} - } - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `reports overloaded methods inside an object which exceed the threshold`() { + val code = """ + object Test { + fun f() {} + fun f(i: Int) {} + fun f(i: Int, j: Int) {} + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report overloaded methods in classes or objects that do not exceed the threshold`() { - val code = """ - class Test { + @Test + fun `does not report overloaded methods inside an object which do not exceed the threshold`() { + val code = """ + object Test { + fun f() {} + fun f(i: Int) {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + @Test + fun `reports overloaded methods inside a companion object which exceed the threshold`() { + val code = """ + class Test { + companion object { fun f() {} - - companion object { - fun f() {} - fun f(i: Int) {} - } + fun f(i: Int) {} + fun f(i: Int, j: Int) {} } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports overloaded methods inside an anonymous object expression`() { - val code = """ - class A { - - fun f() { - object : Runnable { - override fun run() {} - fun run(i: Int) {} - fun run(i: Int, j: Int) {} - } - } + @Test + fun `does not report overloaded methods in a companion object that do not exceed the threshold`() { + val code = """ + class Test { + companion object { + fun f() {} + fun f(i: Int) {} } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } - @Nested - inner class `several overloaded methods inside enum classes` { - - @Test - fun `does not report overridden methods inside enum entries`() { - val code = """ - enum class Test { - E1 { - override fun f() {} - }, - E2 { - override fun f() {} - }, - E3 { - override fun f() {} - }; + @Test + fun `does not report overloaded methods in classes or objects that do not exceed the threshold`() { + val code = """ + class Test { - abstract fun f() - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + fun f() {} - @Test - fun `reports overloaded methods in enum entry`() { - val code = """ - enum class Test { - E { - fun f(i: Int) {} - fun f(i: Int, j: Int) {} - }; + companion object { fun f() {} + fun f(i: Int) {} } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports overloaded methods in enum class`() { - val code = """ - enum class Test { - E; - - fun f() {} - fun f(i: Int) {} - fun f(i: Int, j: Int) {} + @Test + fun `reports overloaded methods inside an anonymous object expression`() { + val code = """ + class A { + + fun f() { + object : Runnable { + override fun run() {} + fun run(i: Int) {} + fun run(i: Int, j: Int) {} + } } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) } + } + + @Nested + inner class `several overloaded methods inside enum classes` { @Test - fun `does not report a class without a body`() { - val code = "class A" + fun `does not report overridden methods inside enum entries`() { + val code = """ + enum class Test { + E1 { + override fun f() {} + }, + E2 { + override fun f() {} + }, + E3 { + override fun f() {} + }; + + abstract fun f() + } + """ assertThat(subject.compileAndLint(code)).isEmpty() } @Test - fun `does not report overloaded local functions`() { + fun `reports overloaded methods in enum entry`() { val code = """ - fun top() { + enum class Test { + E { + fun f(i: Int) {} + fun f(i: Int, j: Int) {} + }; + fun f() {} + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } + + @Test + fun `reports overloaded methods in enum class`() { + val code = """ + enum class Test { + E; + fun f() {} fun f(i: Int) {} fun f(i: Int, j: Int) {} } """ - assertThat(subject.compileAndLint(code)).isEmpty() + assertThat(subject.compileAndLint(code)).hasSize(1) } } + + @Test + fun `does not report a class without a body`() { + val code = "class A" + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report overloaded local functions`() { + val code = """ + fun top() { + fun f() {} + fun f(i: Int) {} + fun f(i: Int, j: Int) {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } } 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 87d065b0f12..f3039cda62a 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 @@ -14,187 +14,244 @@ class NamedArgumentsSpec(val env: KotlinCoreEnvironment) { val defaultConfig = TestConfig(mapOf("threshold" to defaultThreshold)) val subject = NamedArguments(defaultConfig) - @Nested - inner class `NameArguments rule` { + @Test + fun `invocation with more than 2 parameters should throw error`() { + val code = """ + fun sum(a: Int, b:Int, c:Int) { + println(a + b + c) + } + fun call() { + sum(1, 2, 3) + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } - @Test - fun `invocation with more than 2 parameters should throw error`() { - val code = """ - fun sum(a: Int, b:Int, c:Int) { - println(a + b + c) - } - fun call() { - sum(1, 2, 3) - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + @Test + fun `Function invocation with more than 2 parameters should not throw error if named`() { + val code = """ + fun sum(a: Int, b:Int, c:Int) { + println(a + b + c) + } + fun call() { + sum(a = 1, b = 2, c = 3) + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(0) + } - @Test - fun `Function invocation with more than 2 parameters should not throw error if named`() { - val code = """ - fun sum(a: Int, b:Int, c:Int) { - println(a + b + c) - } - fun call() { - sum(a = 1, b = 2, c = 3) - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(0) - } + @Test + fun `invocation with more than 2 parameters should throw error if even one is not named`() { + val code = """ + fun sum(a: Int, b:Int, c:Int) { + println(a + b + c) + } + fun call() { + sum(1, b = 2, c = 3) + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } - @Test - fun `invocation with more than 2 parameters should throw error if even one is not named`() { - val code = """ - fun sum(a: Int, b:Int, c:Int) { - println(a + b + c) - } - fun call() { - sum(1, b = 2, c = 3) - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + @Test + fun `invocation with less than 3 parameters should not throw error`() { + val code = """ + fun sum(a: Int, b:Int) { + println(a + b) + } + fun call() { + sum(1, 2) + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(0) + } - @Test - fun `invocation with less than 3 parameters should not throw error`() { - val code = """ - fun sum(a: Int, b:Int) { - println(a + b) - } - fun call() { - sum(1, 2) - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(0) - } + @Test + fun `invocation with less than 3 named parameters should not throw error`() { + val code = """ + fun sum(a: Int, b:Int) { + println(a + b) + } + fun call() { + sum(a = 1, b = 2) + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(0) + } - @Test - fun `invocation with less than 3 named parameters should not throw error`() { - val code = """ - fun sum(a: Int, b:Int) { - println(a + b) - } - fun call() { - sum(a = 1, b = 2) - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(0) - } + @Test + fun `constructor invocation with more than 3 non-named parameters should throw error`() { + val code = """ + class C(val a: Int, val b:Int, val c:Int) + + val obj = C(1, 2, 3) + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } - @Test - fun `constructor invocation with more than 3 non-named parameters should throw error`() { - val code = """ - class C(val a: Int, val b:Int, val c:Int) - - val obj = C(1, 2, 3) - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + @Test + fun `constructor invocation with more than 3 named parameters should not throw error`() { + val code = """ + class C(val a: Int, val b:Int, val c:Int) + + val obj = C(a = 1, b = 2, c= 3) + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(0) + } - @Test - fun `constructor invocation with more than 3 named parameters should not throw error`() { - val code = """ - class C(val a: Int, val b:Int, val c:Int) - - val obj = C(a = 1, b = 2, c= 3) - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(0) - } + @Test + fun `constructor invocation with less than 3 non-named parameters should not throw error`() { + val code = """ + class C(val a: Int, val b:Int) + + val obj = C(1, 2) + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(0) + } - @Test - fun `constructor invocation with less than 3 non-named parameters should not throw error`() { - val code = """ - class C(val a: Int, val b:Int) - - val obj = C(1, 2) - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(0) - } + @Test + fun `java method invocation should not be flagged`() { + val code = """ + import java.time.LocalDateTime + + fun test() { + LocalDateTime.of(2020, 3, 13, 14, 0, 0) + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(0) + } + @Test + fun `invocation with varargs should not be flagged`() { + val code = """ + fun foo(vararg i: Int) {} + fun bar(a: Int, b: Int, c: Int, vararg s: String) {} + fun test() { + foo(1, 2, 3, 4, 5) + bar(1, 2, 3, "a") + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(0) + } + + @Test + fun `invocation with spread operator should be flagged`() { + val code = """ + fun bar(a: Int, b: Int, c: Int, vararg s: String) {} + fun test() { + bar(1, 2, 3, *arrayOf("a")) + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } + + @Nested + inner class `lambda argument` { @Test - fun `java method invocation should not be flagged`() { + fun `inner lambda argument`() { val code = """ - import java.time.LocalDateTime - - fun test() { - LocalDateTime.of(2020, 3, 13, 14, 0, 0) - } + fun foo(a: Int, b: Int, c: Int, block: ((Int) -> Int)) {} + + fun test() { + foo(a = 1, b = 2, c = 3, { it }) + } """ val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(0) + assertThat(findings).hasSize(1) } @Test - fun `invocation with varargs should not be flagged`() { + fun `outer lambda argument`() { val code = """ - fun foo(vararg i: Int) {} - fun bar(a: Int, b: Int, c: Int, vararg s: String) {} - fun test() { - foo(1, 2, 3, 4, 5) - bar(1, 2, 3, "a") - } + fun foo(a: Int, b: Int, c: Int, block: ((Int) -> Int)) {} + + fun test() { + foo(a = 1, b = 2, c = 3) { it } + } """ val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(0) } @Test - fun `invocation with spread operator should be flagged`() { + fun `unnamed argument and outer argument`() { val code = """ - fun bar(a: Int, b: Int, c: Int, vararg s: String) {} - fun test() { - bar(1, 2, 3, *arrayOf("a")) - } + fun foo(a: Int, b: Int, c: Int, block: ((Int) -> Int)) {} + + fun test() { + foo(a = 1, b = 2, 3) { it } + } """ val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(1) } + } + @Nested + inner class IgnoreArgumentsMatchingNames { @Nested - inner class `lambda argument` { + inner class `ignoreArgumentsMatchingNames is true` { + val subject = + NamedArguments(TestConfig(mapOf("threshold" to 2, "ignoreArgumentsMatchingNames" to true))) + @Test - fun `inner lambda argument`() { + fun `all arguments are the same as the parameter names`() { val code = """ - fun foo(a: Int, b: Int, c: Int, block: ((Int) -> Int)) {} - - fun test() { - foo(a = 1, b = 2, c = 3, { it }) - } + fun foo(a: Int, b: Int, c: Int) {} + fun bar(a: Int, b: Int, c: Int) { + foo(a, b, c) + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(0) + } + + @Test + fun `some arguments are not the same as the parameter names`() { + val code = """ + fun foo(a: Int, b: Int, c: Int) {} + fun bar(a: Int, b: Int, c: Int) { + foo(a, c, b) + } """ val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(1) } @Test - fun `outer lambda argument`() { + fun `all arguments are the same as the parameter names and have a this receiver`() { val code = """ - fun foo(a: Int, b: Int, c: Int, block: ((Int) -> Int)) {} - - fun test() { - foo(a = 1, b = 2, c = 3) { it } - } + class Baz { + private var b: Int = 42 + fun foo(a: Int, b: Int, c: Int) {} + fun bar(a: Int, c: Int) { + foo(a, this.b, c) + } + } """ val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(0) + assertThat(findings).hasSize(1) } @Test - fun `unnamed argument and outer argument`() { + fun `all arguments are the same as the parameter names and have a it receiver`() { val code = """ - fun foo(a: Int, b: Int, c: Int, block: ((Int) -> Int)) {} - - fun test() { - foo(a = 1, b = 2, 3) { it } - } + data class Baz(val b: Int) + fun foo(a: Int, b: Int, c: Int) {} + fun bar(a: Int, c: Int, baz: Baz?) { + baz?.let { foo(a, it.b, c) } + } """ val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(1) @@ -202,78 +259,17 @@ class NamedArgumentsSpec(val env: KotlinCoreEnvironment) { } @Nested - inner class IgnoreArgumentsMatchingNames { - @Nested - inner class `ignoreArgumentsMatchingNames is true` { - val subject = - NamedArguments(TestConfig(mapOf("threshold" to 2, "ignoreArgumentsMatchingNames" to true))) - - @Test - fun `all arguments are the same as the parameter names`() { - val code = """ - fun foo(a: Int, b: Int, c: Int) {} - fun bar(a: Int, b: Int, c: Int) { - foo(a, b, c) - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(0) - } - - @Test - fun `some arguments are not the same as the parameter names`() { - val code = """ - fun foo(a: Int, b: Int, c: Int) {} - fun bar(a: Int, b: Int, c: Int) { - foo(a, c, b) - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } - - @Test - fun `all arguments are the same as the parameter names and have a this receiver`() { - val code = """ - class Baz { - private var b: Int = 42 - fun foo(a: Int, b: Int, c: Int) {} - fun bar(a: Int, c: Int) { - foo(a, this.b, c) - } - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } - - @Test - fun `all arguments are the same as the parameter names and have a it receiver`() { - val code = """ - data class Baz(val b: Int) - fun foo(a: Int, b: Int, c: Int) {} - fun bar(a: Int, c: Int, baz: Baz?) { - baz?.let { foo(a, it.b, c) } - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } - } - - @Nested - inner class `ignoreArgumentsMatchingNames is false` { - @Test - fun `all arguments are the same as parameter names`() { - val code = """ - fun foo(a: Int, b: Int, c: Int) {} - fun bar(a: Int, b: Int, c: Int) { - foo(a, b, c) - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + inner class `ignoreArgumentsMatchingNames is false` { + @Test + fun `all arguments are the same as parameter names`() { + val code = """ + fun foo(a: Int, b: Int, c: Int) {} + fun bar(a: Int, b: Int, c: Int) { + foo(a, b, c) + } + """ + 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 c07304bad85..67c9a72926d 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 @@ -7,7 +7,6 @@ import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint import io.gitlab.arturbosch.detekt.test.lint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class NestedBlockDepthSpec { @@ -16,82 +15,79 @@ class NestedBlockDepthSpec { val defaultConfig = TestConfig(mapOf("threshold" to defaultThreshold)) val subject = NestedBlockDepth(defaultConfig) - @Nested - inner class `nested classes are also considered` { - @Test - fun `should detect only the nested large class`() { - subject.lint(resourceAsPath("NestedClasses.kt")) - assertThat(subject.findings).hasSize(1) - assertThat((subject.findings[0] as ThresholdedCodeSmell).value).isEqualTo(5) - } + @Test + fun `should detect only the nested large class`() { + subject.lint(resourceAsPath("NestedClasses.kt")) + assertThat(subject.findings).hasSize(1) + assertThat((subject.findings[0] as ThresholdedCodeSmell).value).isEqualTo(5) + } - @Test - fun `should detect too nested block depth`() { - val code = """ - fun f() { + @Test + fun `should detect too nested block depth`() { + val code = """ + fun f() { + if (true) { if (true) { if (true) { if (true) { - if (true) { - } } } } } - """ - val findings = subject.compileAndLint(code) + } + """ + val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(1) - assertThat(findings).hasTextLocations(4 to 5) - } + assertThat(findings).hasSize(1) + assertThat(findings).hasTextLocations(4 to 5) + } - @Test - fun `should not detect valid nested block depth`() { - val code = """ - fun f() { + @Test + fun `should not detect valid nested block depth`() { + val code = """ + fun f() { + if (true) { if (true) { if (true) { - if (true) { - } } } } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report valid nested if else branches`() { - val code = """ - fun f() { + @Test + fun `does not report valid nested if else branches`() { + val code = """ + fun f() { + if (true) { if (true) { + } else if (true) { if (true) { - } else if (true) { - if (true) { - } } } } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports deeply nested if else branches`() { - val code = """ - fun f() { + @Test + fun `reports deeply nested if else branches`() { + val code = """ + fun f() { + if (true) { if (true) { + } else if (true) { if (true) { - } else if (true) { if (true) { - if (true) { - } } } } } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) } } diff --git a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ReplaceSafeCallChainWithRunSpec.kt b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ReplaceSafeCallChainWithRunSpec.kt index 1541b5d7f84..9e52b91e6e8 100644 --- a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ReplaceSafeCallChainWithRunSpec.kt +++ b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ReplaceSafeCallChainWithRunSpec.kt @@ -4,7 +4,6 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest @@ -12,67 +11,63 @@ class ReplaceSafeCallChainWithRunSpec(val env: KotlinCoreEnvironment) { val subject = ReplaceSafeCallChainWithRun() - @Nested - inner class `ReplaceSafeChainWithRun rule` { + @Test + fun `reports long chain of unnecessary safe qualified expressions`() { + val code = """ + val x: String? = "string" - @Test - fun `reports long chain of unnecessary safe qualified expressions`() { - val code = """ - val x: String? = "string" + val y = x + ?.asSequence() + ?.map { it } + ?.distinctBy { it } + ?.iterator() + ?.forEach(::println) + """ - val y = x - ?.asSequence() - ?.map { it } - ?.distinctBy { it } - ?.iterator() - ?.forEach(::println) - """ - - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `reports short chain of unnecessary safe qualified expressions`() { - val code = """ - val x: String? = "string" + @Test + fun `reports short chain of unnecessary safe qualified expressions`() { + val code = """ + val x: String? = "string" - val y = x - ?.asSequence() - ?.map { it } - """ + val y = x + ?.asSequence() + ?.map { it } + """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `does not report a safe call chain which is too short to benefit`() { - val code = """ - val x: String? = "string" + @Test + fun `does not report a safe call chain which is too short to benefit`() { + val code = """ + val x: String? = "string" - val y = x - ?.asSequence() - """ + val y = x + ?.asSequence() + """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report a safe call chain on left side of assignment`() { - val code = """ - class Something { - var element: Element? = null - } + @Test + fun `does not report a safe call chain on left side of assignment`() { + val code = """ + class Something { + var element: Element? = null + } - class Element(var list: List?) + class Element(var list: List?) - val z: Something? = Something() + val z: Something? = Something() - fun modifyList() { - z?.element?.list = listOf("strings") - } - """ + fun modifyList() { + z?.element?.list = listOf("strings") + } + """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } } 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 5e1cbbfa75f..2f83d9403f4 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 @@ -17,143 +17,139 @@ class StringLiteralDuplicationSpec { val subject = StringLiteralDuplication() @Nested - inner class `StringLiteralDuplication rule` { - - @Nested - inner class `many hardcoded strings` { - - @Test - fun `reports 3 equal hardcoded strings`() { - val code = """ - class Duplication { - var s1 = "lorem" - fun f(s: String = "lorem") { - s1.equals("lorem") - } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + inner class `many hardcoded strings` { - @Test - fun `does not report 2 equal hardcoded strings`() { - val code = """val str = "lorem" + "lorem" + "ipsum"""" - assertThat(subject.compileAndLint(code)).isEmpty() + @Test + fun `reports 3 equal hardcoded strings`() { + val code = """ + class Duplication { + var s1 = "lorem" + fun f(s: String = "lorem") { + s1.equals("lorem") + } } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) } - @Nested - inner class `strings in annotations` { - - val code = """ - @Suppress("unused") - class A - @Suppress("unused") - class B - @Suppress("unused") - class C - """ + @Test + fun `does not report 2 equal hardcoded strings`() { + val code = """val str = "lorem" + "lorem" + "ipsum"""" + assertThat(subject.compileAndLint(code)).isEmpty() + } + } - @Test - fun `does not report strings in annotations`() { - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Nested + inner class `strings in annotations` { + + val code = """ + @Suppress("unused") + class A + @Suppress("unused") + class B + @Suppress("unused") + class C + """ + + @Test + fun `does not report strings in annotations`() { + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports strings in annotations according to config`() { - val config = TestConfig(mapOf(IGNORE_ANNOTATION to "false")) - assertFindingWithConfig(code, config, 1) - } + @Test + fun `reports strings in annotations according to config`() { + val config = TestConfig(mapOf(IGNORE_ANNOTATION to "false")) + assertFindingWithConfig(code, config, 1) } + } - @Nested - inner class `strings with less than 5 characters` { + @Nested + inner class `strings with less than 5 characters` { - val code = """val str = "amet" + "amet" + "amet"""" + val code = """val str = "amet" + "amet" + "amet"""" - @Test - fun `does not report strings with 4 characters`() { - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report strings with 4 characters`() { + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports string with 4 characters`() { - val config = TestConfig(mapOf(EXCLUDE_SHORT_STRING to "false")) - assertFindingWithConfig(code, config, 1) - } + @Test + fun `reports string with 4 characters`() { + val config = TestConfig(mapOf(EXCLUDE_SHORT_STRING to "false")) + assertFindingWithConfig(code, config, 1) } + } - @Nested - inner class `strings with values to match for the regex` { + @Nested + inner class `strings with values to match for the regex` { + + val regexTestingCode = """ + val str1 = "lorem" + "lorem" + "lorem" + val str2 = "ipsum" + "ipsum" + "ipsum" + """ - val regexTestingCode = """ + @Test + fun `does not report lorem or ipsum according to config in regex`() { + val code = """ val str1 = "lorem" + "lorem" + "lorem" val str2 = "ipsum" + "ipsum" + "ipsum" """ + val config = TestConfig(mapOf(IGNORE_STRINGS_REGEX to "(lorem|ipsum)")) + assertFindingWithConfig(code, config, 0) + } - @Test - fun `does not report lorem or ipsum according to config in regex`() { - val code = """ - val str1 = "lorem" + "lorem" + "lorem" - val str2 = "ipsum" + "ipsum" + "ipsum" - """ - val config = TestConfig(mapOf(IGNORE_STRINGS_REGEX to "(lorem|ipsum)")) - assertFindingWithConfig(code, config, 0) - } - - @Test - fun `should not fail with invalid regex when disabled`() { - val configValues = mapOf( - "active" to "false", - IGNORE_STRINGS_REGEX to "*lorem" - ) - val config = TestConfig(configValues) - assertFindingWithConfig(regexTestingCode, config, 0) - } + @Test + fun `should not fail with invalid regex when disabled`() { + val configValues = mapOf( + "active" to "false", + IGNORE_STRINGS_REGEX to "*lorem" + ) + val config = TestConfig(configValues) + assertFindingWithConfig(regexTestingCode, config, 0) + } - @Test - fun `should fail with invalid regex`() { - val config = TestConfig(mapOf(IGNORE_STRINGS_REGEX to "*lorem")) - assertThatExceptionOfType(PatternSyntaxException::class.java).isThrownBy { - StringLiteralDuplication(config).compileAndLint(regexTestingCode) - } + @Test + fun `should fail with invalid regex`() { + val config = TestConfig(mapOf(IGNORE_STRINGS_REGEX to "*lorem")) + assertThatExceptionOfType(PatternSyntaxException::class.java).isThrownBy { + StringLiteralDuplication(config).compileAndLint(regexTestingCode) } } + } - @Nested - inner class `saves string literal references` { - - @Test - fun `reports 3 locations for 'lorem'`() { - val code = """ - class Duplication { - var s1 = "lorem" - fun f(s: String = "lorem") { - s1.equals("lorem") - } + @Nested + inner class `saves string literal references` { + + @Test + fun `reports 3 locations for 'lorem'`() { + val code = """ + class Duplication { + var s1 = "lorem" + fun f(s: String = "lorem") { + s1.equals("lorem") } - """ - val finding = subject.compileAndLint(code)[0] - val locations = finding.references.map { it.location } + finding.entity.location - assertThat(locations).hasSize(3) } + """ + val finding = subject.compileAndLint(code)[0] + val locations = finding.references.map { it.location } + finding.entity.location + assertThat(locations).hasSize(3) } + } - @Nested - inner class `multiline strings with string interpolation` { - - @Test - fun `does not report duplicated parts in multiline strings`() { - val code = """ - // does not report because it treats the multiline string parts as one string - val str = ""${'"'} - | - | - | - ""${'"'} - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Nested + inner class `multiline strings with string interpolation` { + + @Test + fun `does not report duplicated parts in multiline strings`() { + val code = """ + // does not report because it treats the multiline string parts as one string + val str = ""${'"'} + | + | + | + ""${'"'} + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } } 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 d1b7c5c16bb..9cc27a8f1d9 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 @@ -16,255 +16,251 @@ private const val IGNORE_PRIVATE = "ignorePrivate" private const val IGNORE_OVERRIDDEN = "ignoreOverridden" class TooManyFunctionsSpec { - @Nested - inner class `different declarations with one function as threshold` { - - val rule = - TooManyFunctions( - TestConfig( - mapOf( - 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" - ) + val rule = + TooManyFunctions( + TestConfig( + mapOf( + 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" ) ) + ) - @Test - fun `finds one function in class`() { - val code = """ - class A { - fun a() = Unit - } - """ - - val findings = rule.compileAndLint(code) - assertThat(findings).hasSize(1) - assertThat(findings).hasTextLocations(6 to 7) - } + @Test + fun `finds one function in class`() { + val code = """ + class A { + fun a() = Unit + } + """ - @Test - fun `finds one function in object`() { - val code = """ - object O { - fun o() = Unit - } - """ + val findings = rule.compileAndLint(code) + assertThat(findings).hasSize(1) + assertThat(findings).hasTextLocations(6 to 7) + } - val findings = rule.compileAndLint(code) - assertThat(findings).hasSize(1) - assertThat(findings).hasTextLocations(7 to 8) - } + @Test + fun `finds one function in object`() { + val code = """ + object O { + fun o() = Unit + } + """ - @Test - fun `finds one function in interface`() { - val code = """ - interface I { - fun i() - } - """ + val findings = rule.compileAndLint(code) + assertThat(findings).hasSize(1) + assertThat(findings).hasTextLocations(7 to 8) + } - val findings = rule.compileAndLint(code) - assertThat(findings).hasSize(1) - assertThat(findings).hasTextLocations(10 to 11) - } + @Test + fun `finds one function in interface`() { + val code = """ + interface I { + fun i() + } + """ - @Test - fun `finds one function in enum`() { - val code = """ - enum class E { - A; - fun e() {} - } - """ + val findings = rule.compileAndLint(code) + assertThat(findings).hasSize(1) + assertThat(findings).hasTextLocations(10 to 11) + } - val findings = rule.compileAndLint(code) - assertThat(findings).hasSize(1) - assertThat(findings).hasTextLocations(11 to 12) - } + @Test + fun `finds one function in enum`() { + val code = """ + enum class E { + A; + fun e() {} + } + """ - @Test - fun `finds one function in file`() { - val code = "fun f() = Unit" + val findings = rule.compileAndLint(code) + assertThat(findings).hasSize(1) + assertThat(findings).hasTextLocations(11 to 12) + } - assertThat(rule.compileAndLint(code)).hasSize(1) - } + @Test + fun `finds one function in file`() { + val code = "fun f() = Unit" - @Test - fun `finds one function in file ignoring other declarations`() { - val code = """ - fun f1() = Unit - class C - object O - fun f2() = Unit - interface I - enum class E - fun f3() = Unit - """ + assertThat(rule.compileAndLint(code)).hasSize(1) + } - assertThat(rule.compileAndLint(code)).hasSize(1) - } + @Test + fun `finds one function in file ignoring other declarations`() { + val code = """ + fun f1() = Unit + class C + object O + fun f2() = Unit + interface I + enum class E + fun f3() = Unit + """ + + assertThat(rule.compileAndLint(code)).hasSize(1) + } - @Test - fun `finds one function in nested class`() { - val code = """ - class A { - class B { - fun a() = Unit - } + @Test + fun `finds one function in nested class`() { + val code = """ + class A { + class B { + fun a() = Unit } - """ + } + """ - val findings = rule.compileAndLint(code) - assertThat(findings).hasSize(1) - assertThat(findings).hasTextLocations(20 to 21) - } + val findings = rule.compileAndLint(code) + assertThat(findings).hasSize(1) + assertThat(findings).hasTextLocations(20 to 21) + } - @Nested - inner class `different deprecated functions` { - val code = """ + @Nested + inner class `different deprecated functions` { + val code = """ + @Deprecated("") + fun f() { + } + + class A { @Deprecated("") fun f() { } + } + """ - class A { - @Deprecated("") - fun f() { - } - } - """ + @Test + fun `finds all deprecated functions per default`() { + assertThat(rule.compileAndLint(code)).hasSize(2) + } - @Test - fun `finds all deprecated functions per default`() { - assertThat(rule.compileAndLint(code)).hasSize(2) + @Test + fun `finds no deprecated functions`() { + val configuredRule = TooManyFunctions( + TestConfig( + mapOf( + THRESHOLD_IN_CLASSES to "1", + THRESHOLD_IN_FILES to "1", + IGNORE_DEPRECATED to "true" + ) + ) + ) + assertThat(configuredRule.compileAndLint(code)).isEmpty() + } + } + + @Nested + inner class `different private functions` { + + val code = """ + class A { + private fun f() {} } + """ + + @Test + fun `finds the private function per default`() { + assertThat(rule.compileAndLint(code)).hasSize(1) + } - @Test - fun `finds no deprecated functions`() { - val configuredRule = TooManyFunctions( - TestConfig( - mapOf( - THRESHOLD_IN_CLASSES to "1", - THRESHOLD_IN_FILES to "1", - IGNORE_DEPRECATED to "true" - ) + @Test + fun `finds no private functions`() { + val configuredRule = TooManyFunctions( + TestConfig( + mapOf( + THRESHOLD_IN_CLASSES to "1", + THRESHOLD_IN_FILES to "1", + IGNORE_PRIVATE to "true" ) ) - assertThat(configuredRule.compileAndLint(code)).isEmpty() - } + ) + assertThat(configuredRule.compileAndLint(code)).isEmpty() } + } - @Nested - inner class `different private functions` { + @Nested + inner class `false negative when private and deprecated functions are ignored - #1439` { + @Test + fun `should not report when file has no public functions`() { val code = """ class A { - private fun f() {} + private fun a() = Unit + private fun b() = Unit + @Deprecated("") + private fun c() = Unit } - """ - @Test - fun `finds the private function per default`() { - assertThat(rule.compileAndLint(code)).hasSize(1) - } + interface I { + fun a() = Unit + fun b() = Unit + } - @Test - fun `finds no private functions`() { - val configuredRule = TooManyFunctions( - TestConfig( - mapOf( - THRESHOLD_IN_CLASSES to "1", - THRESHOLD_IN_FILES to "1", - IGNORE_PRIVATE to "true" - ) + class B : I { + override fun a() = Unit + override fun b() = Unit + } + """ + val configuredRule = TooManyFunctions( + TestConfig( + mapOf( + THRESHOLD_IN_CLASSES to "1", + THRESHOLD_IN_FILES to "1", + IGNORE_PRIVATE to "true", + IGNORE_DEPRECATED to "true", + IGNORE_OVERRIDDEN to "true" ) ) - assertThat(configuredRule.compileAndLint(code)).isEmpty() - } + ) + assertThat(configuredRule.compileAndLint(code)).isEmpty() } + } - @Nested - inner class `false negative when private and deprecated functions are ignored - #1439` { - - @Test - fun `should not report when file has no public functions`() { - val code = """ - class A { - private fun a() = Unit - private fun b() = Unit - @Deprecated("") - private fun c() = Unit - } - - interface I { - fun a() = Unit - fun b() = Unit - } - - class B : I { - override fun a() = Unit - override fun b() = Unit - } - """ - val configuredRule = TooManyFunctions( - TestConfig( - mapOf( - THRESHOLD_IN_CLASSES to "1", - THRESHOLD_IN_FILES to "1", - IGNORE_PRIVATE to "true", - IGNORE_DEPRECATED to "true", - IGNORE_OVERRIDDEN to "true" - ) - ) - ) - assertThat(configuredRule.compileAndLint(code)).isEmpty() - } - } + @Nested + inner class `overridden functions` { - @Nested - inner class `overridden functions` { + val code = """ + interface I1 { + fun func1() + fun func2() + } - val code = """ - interface I1 { - fun func1() - fun func2() - } - - class Foo : I1 { - override fun func1() = Unit - override fun func2() = Unit - } - """ + class Foo : I1 { + override fun func1() = Unit + override fun func2() = Unit + } + """ - @Test - fun `should not report class with overridden functions, if ignoreOverridden is enabled`() { - val configuredRule = TooManyFunctions( - TestConfig( - mapOf( - THRESHOLD_IN_CLASSES to "1", - THRESHOLD_IN_FILES to "1", - IGNORE_OVERRIDDEN to "true" - ) + @Test + fun `should not report class with overridden functions, if ignoreOverridden is enabled`() { + val configuredRule = TooManyFunctions( + TestConfig( + mapOf( + THRESHOLD_IN_CLASSES to "1", + THRESHOLD_IN_FILES to "1", + IGNORE_OVERRIDDEN to "true" ) ) - assertThat(configuredRule.compileAndLint(code)).isEmpty() - } + ) + assertThat(configuredRule.compileAndLint(code)).isEmpty() + } - @Test - fun `should count overridden functions, if ignoreOverridden is disabled`() { - val configuredRule = TooManyFunctions( - TestConfig( - mapOf( - THRESHOLD_IN_CLASSES to "1", - THRESHOLD_IN_FILES to "1", - IGNORE_OVERRIDDEN to "false" - ) + @Test + fun `should count overridden functions, if ignoreOverridden is disabled`() { + val configuredRule = TooManyFunctions( + TestConfig( + mapOf( + THRESHOLD_IN_CLASSES to "1", + THRESHOLD_IN_FILES to "1", + IGNORE_OVERRIDDEN to "false" ) ) - assertThat(configuredRule.compileAndLint(code)).hasSize(1) - } + ) + assertThat(configuredRule.compileAndLint(code)).hasSize(1) } } } diff --git a/detekt-rules-coroutines/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/GlobalCoroutineUsageSpec.kt b/detekt-rules-coroutines/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/GlobalCoroutineUsageSpec.kt index c287b9176a9..14bc4921bd0 100644 --- a/detekt-rules-coroutines/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/GlobalCoroutineUsageSpec.kt +++ b/detekt-rules-coroutines/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/GlobalCoroutineUsageSpec.kt @@ -4,74 +4,69 @@ import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class GlobalCoroutineUsageSpec { val subject = GlobalCoroutineUsage(Config.empty) - @Nested - inner class `GlobalCoroutineUsage rule` { + @Test + @DisplayName("should report GlobalScope.launch") + fun reportGlobalScopeLaunch() { + val code = """ + import kotlinx.coroutines.delay + import kotlinx.coroutines.GlobalScope + import kotlinx.coroutines.launch - @Test - @DisplayName("should report GlobalScope.launch") - fun reportGlobalScopeLaunch() { - val code = """ - import kotlinx.coroutines.delay - import kotlinx.coroutines.GlobalScope - import kotlinx.coroutines.launch - - fun foo() { - GlobalScope.launch { delay(1_000L) } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + fun foo() { + GlobalScope.launch { delay(1_000L) } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - @DisplayName("should report GlobalScope.async") - fun reportGlobalScopeAsync() { - val code = """ - import kotlinx.coroutines.async - import kotlinx.coroutines.delay - import kotlinx.coroutines.GlobalScope + @Test + @DisplayName("should report GlobalScope.async") + fun reportGlobalScopeAsync() { + val code = """ + import kotlinx.coroutines.async + import kotlinx.coroutines.delay + import kotlinx.coroutines.GlobalScope - fun foo() { - GlobalScope.async { delay(1_000L) } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + fun foo() { + GlobalScope.async { delay(1_000L) } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `should not report bar(GlobalScope)`() { - val code = """ - import kotlinx.coroutines.CoroutineScope - import kotlinx.coroutines.GlobalScope + @Test + fun `should not report bar(GlobalScope)`() { + val code = """ + import kotlinx.coroutines.CoroutineScope + import kotlinx.coroutines.GlobalScope - fun bar(scope: CoroutineScope) = Unit + fun bar(scope: CoroutineScope) = Unit - fun foo() { - bar(GlobalScope) - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + fun foo() { + bar(GlobalScope) + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `should not report 'val scope = GlobalScope'`() { - val code = """ - import kotlinx.coroutines.CoroutineScope - import kotlinx.coroutines.GlobalScope + @Test + fun `should not report 'val scope = GlobalScope'`() { + val code = """ + import kotlinx.coroutines.CoroutineScope + import kotlinx.coroutines.GlobalScope - fun bar(scope: CoroutineScope) = Unit + fun bar(scope: CoroutineScope) = Unit - fun foo() { - val scope = GlobalScope - bar(scope) - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + fun foo() { + val scope = GlobalScope + bar(scope) + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-coroutines/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/RedundantSuspendModifierSpec.kt b/detekt-rules-coroutines/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/RedundantSuspendModifierSpec.kt index 8b089f9bf87..5a32f0325a5 100644 --- a/detekt-rules-coroutines/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/RedundantSuspendModifierSpec.kt +++ b/detekt-rules-coroutines/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/RedundantSuspendModifierSpec.kt @@ -5,7 +5,6 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest @@ -13,120 +12,116 @@ class RedundantSuspendModifierSpec(val env: KotlinCoreEnvironment) { val subject = RedundantSuspendModifier(Config.empty) - @Nested - inner class `RedundantSuspendModifier` { + @Test + fun `reports when public function returns expression of platform type`() { + val code = """ + import kotlin.coroutines.Continuation + import kotlin.coroutines.resume + import kotlin.coroutines.suspendCoroutine - @Test - fun `reports when public function returns expression of platform type`() { - val code = """ - import kotlin.coroutines.Continuation - import kotlin.coroutines.resume - import kotlin.coroutines.suspendCoroutine + suspend fun suspendCoroutine() = suspendCoroutine { continuation: Continuation -> + continuation.resume("string") + } - suspend fun suspendCoroutine() = suspendCoroutine { continuation: Continuation -> - continuation.resume("string") + class RedundantSuspend { + suspend fun redundantSuspend() { + println("hello world") } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - class RedundantSuspend { - suspend fun redundantSuspend() { - println("hello world") - } - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `does not report when private`() { - val code = """ - import kotlin.coroutines.Continuation - import kotlin.coroutines.resume - import kotlin.coroutines.suspendCoroutine - - suspend fun suspendCoroutine() = suspendCoroutine { continuation: Continuation -> - continuation.resume("string") - } + @Test + fun `does not report when private`() { + val code = """ + import kotlin.coroutines.Continuation + import kotlin.coroutines.resume + import kotlin.coroutines.suspendCoroutine + + suspend fun suspendCoroutine() = suspendCoroutine { continuation: Continuation -> + continuation.resume("string") + } + + suspend fun doesSuspend() { + suspendCoroutine() + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - suspend fun doesSuspend() { - suspendCoroutine() - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `does not report when public function returns expression of platform type`() { - val code = """ - class RedundantClass { - open suspend fun redundantSuspend() { - println("hello world") - } - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `does not report suspend function without body`() { - val code = """ - interface SuspendInterface { - suspend fun empty() - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `does not report overridden suspend function`() { - val code = """ - interface SuspendInterface { - suspend fun empty() + @Test + fun `does not report when public function returns expression of platform type`() { + val code = """ + class RedundantClass { + open suspend fun redundantSuspend() { + println("hello world") } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - class SuspendClass : SuspendInterface { - override suspend fun empty() { - println("hello world") - } - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `ignores when iterator is suspending`() { - val code = """ - class SuspendingIterator { - suspend operator fun iterator(): Iterator = iterator { yield("value") } - } + @Test + fun `does not report suspend function without body`() { + val code = """ + interface SuspendInterface { + suspend fun empty() + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - suspend fun bar() { - for (x in SuspendingIterator()) { - println(x) - } + @Test + fun `does not report overridden suspend function`() { + val code = """ + interface SuspendInterface { + suspend fun empty() + } + + class SuspendClass : SuspendInterface { + override suspend fun empty() { + println("hello world") } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `ignores when suspending function used in property delegate`() { - val code = """ - class SuspendingIterator { - suspend operator fun iterator(): Iterator = iterator { yield("value") } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `ignores when iterator is suspending`() { + val code = """ + class SuspendingIterator { + suspend operator fun iterator(): Iterator = iterator { yield("value") } + } + + suspend fun bar() { + for (x in SuspendingIterator()) { + println(x) } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `ignores when suspending function used in property delegate`() { + val code = """ + class SuspendingIterator { + suspend operator fun iterator(): Iterator = iterator { yield("value") } + } - fun coroutine(block: suspend () -> Unit) {} + fun coroutine(block: suspend () -> Unit) {} - suspend fun bar() { - val lazyValue: String by lazy { - coroutine { - SuspendingIterator().iterator() - } - "Hello" + suspend fun bar() { + val lazyValue: String by lazy { + coroutine { + SuspendingIterator().iterator() } + "Hello" } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } } diff --git a/detekt-rules-coroutines/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/SleepInsteadOfDelaySpec.kt b/detekt-rules-coroutines/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/SleepInsteadOfDelaySpec.kt index 2a85d258cee..f8812d315e9 100644 --- a/detekt-rules-coroutines/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/SleepInsteadOfDelaySpec.kt +++ b/detekt-rules-coroutines/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/SleepInsteadOfDelaySpec.kt @@ -6,7 +6,6 @@ import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @Suppress("BlockingMethodInNonBlockingContext", "RedundantSuspendModifier") @@ -15,64 +14,61 @@ class SleepInsteadOfDelaySpec(val env: KotlinCoreEnvironment) { val subject = SleepInsteadOfDelay(Config.empty) - @Nested - inner class `SleepInsteadOfDelay rule` { - @Test - fun `should report no issue for delay() in suspend functions`() { - val code = """ - import kotlinx.coroutines.delay + @Test + fun `should report no issue for delay() in suspend functions`() { + val code = """ + import kotlinx.coroutines.delay - suspend fun foo() { - delay(1000L) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(0) - } + suspend fun foo() { + delay(1000L) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(0) + } - @Test - @DisplayName("should report Thread.sleep() in suspend functions") - fun reportThreadSleepInSuspendFunctions() { - val code = """ - suspend fun foo() { - Thread.sleep(1000L) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + @Test + @DisplayName("should report Thread.sleep() in suspend functions") + fun reportThreadSleepInSuspendFunctions() { + val code = """ + suspend fun foo() { + Thread.sleep(1000L) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - @DisplayName("should report Thread.sleep() in CoroutineScope.launch()") - fun reportThreadSleepInCoroutineScopeLaunch() { - val code = """ - import kotlinx.coroutines.CoroutineScope - import kotlinx.coroutines.Dispatchers - import kotlinx.coroutines.launch - - fun foo() { - CoroutineScope(Dispatchers.IO).launch { - Thread.sleep(1000L) - } + @Test + @DisplayName("should report Thread.sleep() in CoroutineScope.launch()") + fun reportThreadSleepInCoroutineScopeLaunch() { + val code = """ + import kotlinx.coroutines.CoroutineScope + import kotlinx.coroutines.Dispatchers + import kotlinx.coroutines.launch + + fun foo() { + CoroutineScope(Dispatchers.IO).launch { + Thread.sleep(1000L) } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - @DisplayName("should report Thread.sleep() in CoroutineScope.async()") - fun reportThreadSleepInCoroutineScopeAsync() { - @Suppress("DeferredResultUnused") - val code = """ - import kotlinx.coroutines.CoroutineScope - import kotlinx.coroutines.Dispatchers - import kotlinx.coroutines.async - - fun foo() { - CoroutineScope(Dispatchers.IO).async { - Thread.sleep(1000L) - } + @Test + @DisplayName("should report Thread.sleep() in CoroutineScope.async()") + fun reportThreadSleepInCoroutineScopeAsync() { + @Suppress("DeferredResultUnused") + val code = """ + import kotlinx.coroutines.CoroutineScope + import kotlinx.coroutines.Dispatchers + import kotlinx.coroutines.async + + fun foo() { + CoroutineScope(Dispatchers.IO).async { + Thread.sleep(1000L) } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) } } diff --git a/detekt-rules-coroutines/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/SuspendFunWithFlowReturnTypeSpec.kt b/detekt-rules-coroutines/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/SuspendFunWithFlowReturnTypeSpec.kt index c984c7598a5..447e17d38ce 100644 --- a/detekt-rules-coroutines/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/SuspendFunWithFlowReturnTypeSpec.kt +++ b/detekt-rules-coroutines/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/SuspendFunWithFlowReturnTypeSpec.kt @@ -5,7 +5,6 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest @@ -13,42 +12,118 @@ class SuspendFunWithFlowReturnTypeSpec(val env: KotlinCoreEnvironment) { val subject = SuspendFunWithFlowReturnType(Config.empty) - @Nested - inner class `SuspendFunWithFlowReturn` { + @Test + fun `reports when top-level suspend function has explicit Flow return type`() { + val code = """ + import kotlinx.coroutines.flow.Flow + import kotlinx.coroutines.flow.flowOf + import kotlinx.coroutines.flow.MutableStateFlow + import kotlinx.coroutines.flow.StateFlow + import kotlinx.coroutines.yield + + suspend fun flowValues(): Flow { + yield() + return flowOf(1L, 2L, 3L) + } + + suspend fun stateFlowValues(): StateFlow { + yield() + return MutableStateFlow(value = 1L) + } + + suspend fun mutableStateFlowValues(): MutableStateFlow { + yield() + return MutableStateFlow(value = 1L) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(3) + } - @Test - fun `reports when top-level suspend function has explicit Flow return type`() { - val code = """ - import kotlinx.coroutines.flow.Flow - import kotlinx.coroutines.flow.flowOf - import kotlinx.coroutines.flow.MutableStateFlow - import kotlinx.coroutines.flow.StateFlow - import kotlinx.coroutines.yield + @Test + fun `reports when top-level suspend function has explicit Flow return type and star import used`() { + val code = """ + import kotlinx.coroutines.flow.* + import kotlinx.coroutines.yield + + suspend fun flowValues(): Flow { + yield() + return flowOf(1L, 2L, 3L) + } + + suspend fun stateFlowValues(): StateFlow { + yield() + return MutableStateFlow(value = 1L) + } + + suspend fun mutableStateFlowValues(): MutableStateFlow { + yield() + return MutableStateFlow(value = 1L) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(3) + } - suspend fun flowValues(): Flow { - yield() - return flowOf(1L, 2L, 3L) - } + @Test + fun `reports when top-level suspend function has explicit FQN Flow return type`() { + val code = """ + import kotlinx.coroutines.yield + + suspend fun flowValues(): kotlinx.coroutines.flow.Flow { + yield() + return kotlinx.coroutines.flow.flowOf(1L, 2L, 3L) + } + + suspend fun stateFlowValues(): kotlinx.coroutines.flow.StateFlow { + yield() + return kotlinx.coroutines.flow.MutableStateFlow(value = 1L) + } + + suspend fun mutableStateFlowValues(): kotlinx.coroutines.flow.MutableStateFlow { + yield() + return kotlinx.coroutines.flow.MutableStateFlow(value = 1L) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(3) + } - suspend fun stateFlowValues(): StateFlow { - yield() - return MutableStateFlow(value = 1L) - } + @Test + fun `reports when top-level suspend function has implicit Flow return type`() { + val code = """ + import kotlinx.coroutines.flow.flowOf + import kotlinx.coroutines.flow.MutableStateFlow - suspend fun mutableStateFlowValues(): MutableStateFlow { - yield() - return MutableStateFlow(value = 1L) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(3) - } + suspend fun flowValues() = flowOf(1L, 2L, 3L) + suspend fun mutableStateFlowValues() = MutableStateFlow(value = 1L) + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) + } + + @Test + fun `reports when interface suspend function has explicit Flow return type`() { + val code = """ + import kotlinx.coroutines.flow.Flow + import kotlinx.coroutines.flow.MutableStateFlow + import kotlinx.coroutines.flow.StateFlow + + interface ValuesRepository { + suspend fun flowValues(): Flow + suspend fun stateFlowValues(): StateFlow + suspend fun mutableStateFlowValues(): MutableStateFlow + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(3) + } - @Test - fun `reports when top-level suspend function has explicit Flow return type and star import used`() { - val code = """ - import kotlinx.coroutines.flow.* - import kotlinx.coroutines.yield + @Test + fun `reports when class suspend function has explicit Flow return type`() { + val code = """ + import kotlinx.coroutines.flow.Flow + import kotlinx.coroutines.flow.flowOf + import kotlinx.coroutines.flow.MutableStateFlow + import kotlinx.coroutines.flow.StateFlow + import kotlinx.coroutines.yield + class ValuesRepository { suspend fun flowValues(): Flow { yield() return flowOf(1L, 2L, 3L) @@ -63,222 +138,142 @@ class SuspendFunWithFlowReturnTypeSpec(val env: KotlinCoreEnvironment) { yield() return MutableStateFlow(value = 1L) } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(3) - } - - @Test - fun `reports when top-level suspend function has explicit FQN Flow return type`() { - val code = """ - import kotlinx.coroutines.yield - - suspend fun flowValues(): kotlinx.coroutines.flow.Flow { - yield() - return kotlinx.coroutines.flow.flowOf(1L, 2L, 3L) - } - - suspend fun stateFlowValues(): kotlinx.coroutines.flow.StateFlow { - yield() - return kotlinx.coroutines.flow.MutableStateFlow(value = 1L) - } - - suspend fun mutableStateFlowValues(): kotlinx.coroutines.flow.MutableStateFlow { - yield() - return kotlinx.coroutines.flow.MutableStateFlow(value = 1L) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(3) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(3) + } - @Test - fun `reports when top-level suspend function has implicit Flow return type`() { - val code = """ - import kotlinx.coroutines.flow.flowOf - import kotlinx.coroutines.flow.MutableStateFlow + @Test + fun `reports when class suspend function has implicit Flow return type`() { + val code = """ + import kotlinx.coroutines.flow.flowOf + import kotlinx.coroutines.flow.MutableStateFlow + class ValuesRepository { suspend fun flowValues() = flowOf(1L, 2L, 3L) suspend fun mutableStateFlowValues() = MutableStateFlow(value = 1L) - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) - } - - @Test - fun `reports when interface suspend function has explicit Flow return type`() { - val code = """ - import kotlinx.coroutines.flow.Flow - import kotlinx.coroutines.flow.MutableStateFlow - import kotlinx.coroutines.flow.StateFlow - - interface ValuesRepository { - suspend fun flowValues(): Flow - suspend fun stateFlowValues(): StateFlow - suspend fun mutableStateFlowValues(): MutableStateFlow - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(3) - } - - @Test - fun `reports when class suspend function has explicit Flow return type`() { - val code = """ - import kotlinx.coroutines.flow.Flow - import kotlinx.coroutines.flow.flowOf - import kotlinx.coroutines.flow.MutableStateFlow - import kotlinx.coroutines.flow.StateFlow - import kotlinx.coroutines.yield - - class ValuesRepository { - suspend fun flowValues(): Flow { - yield() - return flowOf(1L, 2L, 3L) - } - - suspend fun stateFlowValues(): StateFlow { - yield() - return MutableStateFlow(value = 1L) - } - - suspend fun mutableStateFlowValues(): MutableStateFlow { - yield() - return MutableStateFlow(value = 1L) - } - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(3) - } - - @Test - fun `reports when class suspend function has implicit Flow return type`() { - val code = """ - import kotlinx.coroutines.flow.flowOf - import kotlinx.coroutines.flow.MutableStateFlow - - class ValuesRepository { - suspend fun flowValues() = flowOf(1L, 2L, 3L) - suspend fun mutableStateFlowValues() = MutableStateFlow(value = 1L) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) - } - - @Test - fun `reports when suspend extension function has explicit Flow return type`() { - val code = """ - import kotlinx.coroutines.flow.asFlow - import kotlinx.coroutines.flow.Flow - import kotlinx.coroutines.flow.MutableStateFlow - import kotlinx.coroutines.flow.StateFlow - import kotlinx.coroutines.yield - - suspend fun Long.flowValues(): Flow { - yield() - return (0..this).asFlow() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) + } - suspend fun Long.stateFlowValues(): StateFlow { - yield() - return MutableStateFlow(value = this) - } + @Test + fun `reports when suspend extension function has explicit Flow return type`() { + val code = """ + import kotlinx.coroutines.flow.asFlow + import kotlinx.coroutines.flow.Flow + import kotlinx.coroutines.flow.MutableStateFlow + import kotlinx.coroutines.flow.StateFlow + import kotlinx.coroutines.yield + + suspend fun Long.flowValues(): Flow { + yield() + return (0..this).asFlow() + } + + suspend fun Long.stateFlowValues(): StateFlow { + yield() + return MutableStateFlow(value = this) + } + + suspend fun Long.mutableStateFlowValues(): MutableStateFlow { + yield() + return MutableStateFlow(value = this) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(3) + } - suspend fun Long.mutableStateFlowValues(): MutableStateFlow { - yield() - return MutableStateFlow(value = this) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(3) - } - - @Test - fun `reports when suspend extension function has implicit Flow return type`() { - val code = """ - import kotlinx.coroutines.flow.asFlow - import kotlinx.coroutines.flow.MutableStateFlow - - suspend fun Long.flowValues() = (0..this).asFlow() - suspend fun Long.mutableStateFlowValues() = MutableStateFlow(value = this) - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) - } - - @Test - fun `does not report when suspend lambda has Flow return type`() { - val code = """ - import kotlinx.coroutines.flow.Flow - import kotlinx.coroutines.flow.MutableStateFlow - import kotlinx.coroutines.flow.StateFlow - - fun doSomething1(block: suspend () -> Flow) { - TODO() - } - fun doSomething2(block: suspend () -> StateFlow) { - TODO() - } + @Test + fun `reports when suspend extension function has implicit Flow return type`() { + val code = """ + import kotlinx.coroutines.flow.asFlow + import kotlinx.coroutines.flow.MutableStateFlow - fun doSomething3(block: suspend () -> MutableStateFlow) { - TODO() - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + suspend fun Long.flowValues() = (0..this).asFlow() + suspend fun Long.mutableStateFlowValues() = MutableStateFlow(value = this) + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) + } - @Test - fun `does not report when suspend functions have non-Flow return types`() { - val code = """ - import kotlinx.coroutines.delay + @Test + fun `does not report when suspend lambda has Flow return type`() { + val code = """ + import kotlinx.coroutines.flow.Flow + import kotlinx.coroutines.flow.MutableStateFlow + import kotlinx.coroutines.flow.StateFlow + + fun doSomething1(block: suspend () -> Flow) { + TODO() + } + fun doSomething2(block: suspend () -> StateFlow) { + TODO() + } + + fun doSomething3(block: suspend () -> MutableStateFlow) { + TODO() + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - suspend fun delayValue(value: Long): Long { - delay(1_000L) - return value - } + @Test + fun `does not report when suspend functions have non-Flow return types`() { + val code = """ + import kotlinx.coroutines.delay - suspend fun delayValue2(value: Long) = value.apply { delay(1_000L) } + suspend fun delayValue(value: Long): Long { + delay(1_000L) + return value + } - suspend fun Long.delayValue(): Long { - delay(1_000L) - return this - } + suspend fun delayValue2(value: Long) = value.apply { delay(1_000L) } - suspend fun Long.delayValue2() = this.apply { delay(1_000L) } + suspend fun Long.delayValue(): Long { + delay(1_000L) + return this + } - interface ValueRepository { - suspend fun getValue(): Long - } + suspend fun Long.delayValue2() = this.apply { delay(1_000L) } - class ValueRepository2 { - suspend fun getValue(): Long { - delay(1_000L) - return 5L - } - } + interface ValueRepository { + suspend fun getValue(): Long + } - class ValueRepository3 { - suspend fun getValue() = 5L.apply { delay(1_000L) } - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `does not report when non-suspend functions have Flow return types`() { - val code = """ - import kotlinx.coroutines.flow.flowOf - import kotlinx.coroutines.flow.Flow - import kotlinx.coroutines.flow.MutableStateFlow - import kotlinx.coroutines.flow.StateFlow - - fun flowValues(): Flow { - return flowOf(1L, 2L, 3L) + class ValueRepository2 { + suspend fun getValue(): Long { + delay(1_000L) + return 5L } + } - fun stateFlowValues(): StateFlow { - return MutableStateFlow(value = 1L) - } + class ValueRepository3 { + suspend fun getValue() = 5L.apply { delay(1_000L) } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - fun mutableStateFlowValues(): MutableStateFlow { - return MutableStateFlow(value = 1L) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does not report when non-suspend functions have Flow return types`() { + val code = """ + import kotlinx.coroutines.flow.flowOf + import kotlinx.coroutines.flow.Flow + import kotlinx.coroutines.flow.MutableStateFlow + import kotlinx.coroutines.flow.StateFlow + + fun flowValues(): Flow { + return flowOf(1L, 2L, 3L) + } + + fun stateFlowValues(): StateFlow { + return MutableStateFlow(value = 1L) + } + + fun mutableStateFlowValues(): MutableStateFlow { + return MutableStateFlow(value = 1L) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } } diff --git a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/AbsentOrWrongFileLicenseSpec.kt b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/AbsentOrWrongFileLicenseSpec.kt index 36b304233a2..65c05ca4d80 100644 --- a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/AbsentOrWrongFileLicenseSpec.kt +++ b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/AbsentOrWrongFileLicenseSpec.kt @@ -18,180 +18,164 @@ import java.net.URI class AbsentOrWrongFileLicenseSpec { - @Nested - inner class `AbsentOrWrongFileLicense rule` { - - @Nested - inner class `file with correct license header` { + @Test + fun `file with correct license header reports nothing`() { + val findings = checkLicence( + """ + /* LICENSE */ + package cases + """ + ) + + assertThat(findings).isEmpty() + } - @Test - fun `reports nothing`() { - val findings = checkLicence( - """ - /* LICENSE */ - package cases - """ - ) + @Test + fun `file with incorrect license header reports missed license header`() { + val findings = checkLicence( + """ + /* WRONG LICENSE */ + package cases + """ + ) - assertThat(findings).isEmpty() - } - } + assertThat(findings).hasSize(1) + } - @Nested - inner class `file with incorrect license header` { + @Test + fun `file with absent license header reports missed license header`() { + val findings = checkLicence( + """ + package cases + """ + ) - @Test - fun `reports missed license header`() { - val findings = checkLicence( - """ - /* WRONG LICENSE */ - package cases - """ - ) + assertThat(findings).hasSize(1) + } - assertThat(findings).hasSize(1) - } + @Nested + inner class `file with correct license header using regex matching` { + + @Test + fun `reports nothing for 2016`() { + val findings = checkLicence( + """ + // + // Copyright 2016 Artur Bosch & Contributors + // http://www.apache.org/licenses/LICENSE-2.0 + // See the License for the specific language governing permissions and + // limitations under the License. + // + package cases + """.trimIndent(), + isRegexLicense = true + ) + + assertThat(findings).isEmpty() } - @Nested - inner class `file with absent license header` { - - @Test - fun `reports missed license header`() { - val findings = checkLicence( - """ - package cases - """ - ) - - assertThat(findings).hasSize(1) - } + @Test + fun `reports nothing for 2021`() { + val findings = checkLicence( + """ + // + // Copyright 2021 Artur Bosch & Contributors + // http://www.apache.org/licenses/LICENSE-2.0 + // See the License for the specific language governing permissions and + // limitations under the License. + // + package cases + """.trimIndent(), + isRegexLicense = true + ) + + assertThat(findings).isEmpty() } + } - @Nested - inner class `file with correct license header using regex matching` { - - @Test - fun `reports nothing for 2016`() { - val findings = checkLicence( - """ - // - // Copyright 2016 Artur Bosch & Contributors - // http://www.apache.org/licenses/LICENSE-2.0 - // See the License for the specific language governing permissions and - // limitations under the License. - // - package cases - """.trimIndent(), - isRegexLicense = true - ) - - assertThat(findings).isEmpty() - } - - @Test - fun `reports nothing for 2021`() { - val findings = checkLicence( - """ - // - // Copyright 2021 Artur Bosch & Contributors - // http://www.apache.org/licenses/LICENSE-2.0 - // See the License for the specific language governing permissions and - // limitations under the License. - // - package cases - """.trimIndent(), - isRegexLicense = true - ) - - assertThat(findings).isEmpty() - } + @Nested + inner class `file with incorrect license header using regex matching` { + + @Test + fun `file with missing license header`() { + val findings = checkLicence( + """ + package cases + """.trimIndent(), + isRegexLicense = true + ) + + assertThat(findings).hasSize(1) } - @Nested - inner class `file with incorrect license header using regex matching` { - - @Test - fun `file with missing license header`() { - val findings = checkLicence( - """ - package cases - """.trimIndent(), - isRegexLicense = true - ) - - assertThat(findings).hasSize(1) - } - - @Test - fun `file with license header not on the first line`() { - val findings = checkLicence( - """ - package cases - // - // Copyright 2021 Artur Bosch & Contributors - // http://www.apache.org/licenses/LICENSE-2.0 - // See the License for the specific language governing permissions and - // limitations under the License. - // - """.trimIndent(), - isRegexLicense = true - ) - - assertThat(findings).hasSize(1) - } + @Test + fun `file with license header not on the first line`() { + val findings = checkLicence( + """ + package cases + // + // Copyright 2021 Artur Bosch & Contributors + // http://www.apache.org/licenses/LICENSE-2.0 + // See the License for the specific language governing permissions and + // limitations under the License. + // + """.trimIndent(), + isRegexLicense = true + ) + + assertThat(findings).hasSize(1) + } - @Test - fun `file with incomplete license header`() { - val findings = checkLicence( - """ - // - // Copyright 2021 Artur Bosch & Contributors - // - package cases - """.trimIndent(), - isRegexLicense = true - ) - - assertThat(findings).hasSize(1) - } + @Test + fun `file with incomplete license header`() { + val findings = checkLicence( + """ + // + // Copyright 2021 Artur Bosch & Contributors + // + package cases + """.trimIndent(), + isRegexLicense = true + ) + + assertThat(findings).hasSize(1) + } - @Test - fun `file with too many empty likes in license header`() { - val findings = checkLicence( - """ - // - // - // Copyright 2021 Artur Bosch & Contributors - // http://www.apache.org/licenses/LICENSE-2.0 - // See the License for the specific language governing permissions and - // limitations under the License. - // - package cases - """.trimIndent(), - isRegexLicense = true - ) - - assertThat(findings).hasSize(1) - } + @Test + fun `file with too many empty likes in license header`() { + val findings = checkLicence( + """ + // + // + // Copyright 2021 Artur Bosch & Contributors + // http://www.apache.org/licenses/LICENSE-2.0 + // See the License for the specific language governing permissions and + // limitations under the License. + // + package cases + """.trimIndent(), + isRegexLicense = true + ) + + assertThat(findings).hasSize(1) + } - @Test - fun `file with incorrect year in license header`() { - val findings = checkLicence( - """ - // - // Copyright 202 Artur Bosch & Contributors - // http://www.apache.org/licenses/LICENSE-2.0 - // See the License for the specific language governing permissions and - // limitations under the License. - // - package cases - """.trimIndent(), - isRegexLicense = true - ) - - assertThat(findings).hasSize(1) - } + @Test + fun `file with incorrect year in license header`() { + val findings = checkLicence( + """ + // + // Copyright 202 Artur Bosch & Contributors + // http://www.apache.org/licenses/LICENSE-2.0 + // See the License for the specific language governing permissions and + // limitations under the License. + // + package cases + """.trimIndent(), + isRegexLicense = true + ) + + assertThat(findings).hasSize(1) } } } diff --git a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/CommentOverPrivateMethodSpec.kt b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/CommentOverPrivateMethodSpec.kt index 3edf4b498a9..3351286f9be 100644 --- a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/CommentOverPrivateMethodSpec.kt +++ b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/CommentOverPrivateMethodSpec.kt @@ -2,50 +2,45 @@ package io.gitlab.arturbosch.detekt.rules.documentation import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class CommentOverPrivateMethodSpec { val subject = CommentOverPrivateFunction() - @Nested - inner class `CommentOverPrivateFunction rule` { + @Test + fun `reports private method with a comment`() { + val code = """ + class Test { + /** + * asdf + */ + private fun f() {} + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports private method with a comment`() { - val code = """ - class Test { - /** - * asdf - */ - private fun f() {} - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `does not report public method with a comment`() { + val code = """ + /** + * asdf + */ + fun f() {} + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report public method with a comment`() { - val code = """ + @Test + fun `does not report public method in a class with a comment`() { + val code = """ + class Test { /** * asdf */ fun f() {} - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report public method in a class with a comment`() { - val code = """ - class Test { - /** - * asdf - */ - fun f() {} - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/CommentOverPrivatePropertiesSpec.kt b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/CommentOverPrivatePropertiesSpec.kt index 2c076b55a6d..ebbe04c800d 100644 --- a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/CommentOverPrivatePropertiesSpec.kt +++ b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/CommentOverPrivatePropertiesSpec.kt @@ -2,61 +2,56 @@ package io.gitlab.arturbosch.detekt.rules.documentation import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class CommentOverPrivatePropertiesSpec { - val subject = CommentOverPrivateProperty() + private val subject = CommentOverPrivateProperty() - @Nested - inner class `CommentOverPrivateProperty rule` { + @Test + fun `reports private property with a comment`() { + val code = """ + /** + * asdf + */ + private val v = 1 + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } + + @Test + fun `does not report public property with a comment`() { + val code = """ + /** + * asdf + */ + val v = 1 + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports private property with a comment`() { - val code = """ + @Test + fun `reports private property in class with a comment`() { + val code = """ + class Test { /** * asdf */ private val v = 1 - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report public property with a comment`() { - val code = """ + @Test + fun `does not report public property in class with a comment`() { + val code = """ + class Test { /** * asdf */ val v = 1 - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `reports private property in class with a comment`() { - val code = """ - class Test { - /** - * asdf - */ - private val v = 1 - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `does not report public property in class with a comment`() { - val code = """ - class Test { - /** - * asdf - */ - val v = 1 - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/DeprecatedBlockTagSpec.kt b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/DeprecatedBlockTagSpec.kt index c5af5edf9c9..68e48e4c99c 100644 --- a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/DeprecatedBlockTagSpec.kt +++ b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/DeprecatedBlockTagSpec.kt @@ -8,151 +8,148 @@ import org.junit.jupiter.api.Test class DeprecatedBlockTagSpec { val subject = DeprecatedBlockTag() + @Test + fun `does not report regular kdoc block`() { + val code = """ + /** + * This is just a regular kdoc block. + * + * Nothing to see here... + */ + val v = 2 + """ + assertThat(subject.compileAndLint(code)).hasSize(0) + } + @Nested - inner class `DeprecatedBlockTag rule` { + inner class `reporting deprecation tag on kdoc block` { + val code = """ + /** + * I am a KDoc block + * + * @deprecated oh no, this should not be here + */ + fun ohNo() { } + """ + @Test - fun `does not report regular kdoc block`() { + fun `has found something`() { + assertThat(subject.compileAndLint(code)).hasSize(1) + } + + @Test + fun `correct message`() { + assertThat(subject.compileAndLint(code)[0]).hasMessage( + "@deprecated tag block does not properly report " + + "deprecation in Kotlin, use @Deprecated annotation instead" + ) + } + } + + @Nested + inner class `reporting deprecation tag wherever @Deprecated is available` { + + @Test + fun `report deprecation tag on class`() { val code = """ - /** - * This is just a regular kdoc block. - * - * Nothing to see here... - */ - val v = 2 + /** + * Hello there + * + * @deprecated This thing is deprecated + */ + class Thing { } """ - assertThat(subject.compileAndLint(code)).hasSize(0) + assertThat(subject.compileAndLint(code)).hasSize(1) } - @Nested - inner class `reporting deprecation tag on kdoc block` { + @Test + fun `report deprecation tag on property`() { val code = """ + class Thing { /** - * I am a KDoc block - * - * @deprecated oh no, this should not be here + * A thing you should not use + * + * @deprecated Do not use that */ - fun ohNo() { } - """ - - @Test - fun `has found something`() { - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `correct message`() { - assertThat(subject.compileAndLint(code)[0]).hasMessage( - "@deprecated tag block does not properly report " + - "deprecation in Kotlin, use @Deprecated annotation instead" - ) + val doNotUseMe = 0 } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) } - @Nested - inner class `reporting deprecation tag wherever @Deprecated is available` { - - @Test - fun `report deprecation tag on class`() { - val code = """ + @Test + fun `report deprecation tag on annotation class`() { + val code = """ /** - * Hello there + * An annotation you should not use * - * @deprecated This thing is deprecated + * @deprecated Do not use that */ - class Thing { } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + annotation class Thing() + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `report deprecation tag on property`() { - val code = """ + @Test + fun `report deprecation tag on constructor`() { + val code = """ class Thing { /** - * A thing you should not use + * A constructor you should not use * * @deprecated Do not use that */ - val doNotUseMe = 0 + constructor(something: String) } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `report deprecation tag on annotation class`() { - val code = """ - /** - * An annotation you should not use - * - * @deprecated Do not use that - */ - annotation class Thing() - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `report deprecation tag on constructor`() { - val code = """ - class Thing { + @Test + fun `report deprecation tag on property setter`() { + val code = """ + class Thing { + var someProperty: Int + get() = 10 /** - * A constructor you should not use - * - * @deprecated Do not use that + * Do not use this setter + * + * @deprecated Do not use it */ - constructor(something: String) - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `report deprecation tag on property setter`() { - val code = """ - class Thing { - var someProperty: Int - get() = 10 - /** - * Do not use this setter - * - * @deprecated Do not use it - */ - set(value) { println(value) } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + set(value) { println(value) } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `report deprecation tag on property getter`() { - val code = """ - class Thing { - var someProperty: Int - /** - * Do not use this getter - * - * @deprecated Do not use it - */ - get() = 10 - set(value) { println(value) } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `report deprecation tag on property getter`() { + val code = """ + class Thing { + var someProperty: Int + /** + * Do not use this getter + * + * @deprecated Do not use it + */ + get() = 10 + set(value) { println(value) } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `report deprecation tag on typealias`() { - val code = """ - /** - * This alias is pointless, do not use it - * - * @deprecated Do not use this typealias - */ - typealias VeryString = String - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `report deprecation tag on typealias`() { + val code = """ + /** + * This alias is pointless, do not use it + * + * @deprecated Do not use this typealias + */ + typealias VeryString = String + """ + assertThat(subject.compileAndLint(code)).hasSize(1) } } } diff --git a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/EndOfSentenceFormatSpec.kt b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/EndOfSentenceFormatSpec.kt index 228e5e49f68..8c1c6010954 100644 --- a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/EndOfSentenceFormatSpec.kt +++ b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/EndOfSentenceFormatSpec.kt @@ -2,209 +2,204 @@ package io.gitlab.arturbosch.detekt.rules.documentation import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class EndOfSentenceFormatSpec { val subject = EndOfSentenceFormat() - @Nested - inner class `KDocStyle rule` { + @Test + fun `reports invalid KDoc endings on classes`() { + val code = """ + /** Some doc */ + class Test { + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports invalid KDoc endings on classes`() { - val code = """ + @Test + fun `reports invalid KDoc endings on function with expression body`() { + val code = """ /** Some doc */ - class Test { - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + fun f(x: Int, y: Int, z: Int) = + if (x == 0) y + z else x + y + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports invalid KDoc endings on function with expression body`() { - val code = """ - /** Some doc */ - fun f(x: Int, y: Int, z: Int) = - if (x == 0) y + z else x + y - """ - assertThat(subject.compileAndLint(code)).hasSize(1) + @Test + fun `reports invalid KDoc endings on properties`() { + val code = """ + class Test { + /** Some doc */ + val test = 3 } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports invalid KDoc endings on properties`() { - val code = """ - class Test { - /** Some doc */ - val test = 3 - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports invalid KDoc endings on top-level functions`() { + val code = """ + /** Some doc */ + fun test() = 3 + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports invalid KDoc endings on top-level functions`() { - val code = """ + @Test + fun `reports invalid KDoc endings on functions`() { + val code = """ + class Test { /** Some doc */ fun test() = 3 - """ - assertThat(subject.compileAndLint(code)).hasSize(1) } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports invalid KDoc endings on functions`() { - val code = """ - class Test { - /** Some doc */ - fun test() = 3 - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) + @Test + fun `reports invalid KDoc endings`() { + val code = """ + class Test { + /** Some doc-- */ + fun test() = 3 } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports invalid KDoc endings`() { - val code = """ - class Test { - /** Some doc-- */ - fun test() = 3 - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) + @Test + fun `reports invalid KDoc endings in block`() { + val code = """ + /** + * Something off abc@@ + */ + class Test { } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports invalid KDoc endings in block`() { - val code = """ - /** - * Something off abc@@ - */ - class Test { - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `does not validate first sentence KDoc endings in a multi sentence comment`() { + val code = """ + /** + * This sentence is correct. + * + * This sentence doesn't matter + */ + class Test { + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not validate first sentence KDoc endings in a multi sentence comment`() { - val code = """ - /** - * This sentence is correct. - * - * This sentence doesn't matter - */ - class Test { - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() + @Test + fun `does not report KDoc which doesn't contain any real sentence`() { + val code = """ + /** + */ + class Test { } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report KDoc which doesn't contain any real sentence`() { - val code = """ - /** - */ - class Test { - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report KDoc which doesn't contain any real sentence but many tags`() { + val code = """ + /** + * @configuration this - just an example (default: `150`) + * + * @active since v1.0.0 + */ + class Test { + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report KDoc which doesn't contain any real sentence but many tags`() { - val code = """ - /** - * @configuration this - just an example (default: `150`) - * - * @active since v1.0.0 - */ - class Test { - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report KDoc which doesn't contain any real sentence but html tags`() { + val code = """ + /** + * + * + * fun foo(): Unit { } + * + * + * + * fun foo() { } + * + * + */ + class Test { + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report KDoc which doesn't contain any real sentence but html tags`() { - val code = """ - /** - * - * - * fun foo(): Unit { } - * - * - * - * fun foo() { } - * - * - */ - class Test { - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() + @Test + fun `does not report KDoc ending with periods`() { + val code = """ + /** + * Something correct. + */ + class Test { } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report KDoc ending with periods`() { - val code = """ - /** - * Something correct. - */ - class Test { - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() + @Test + fun `does not report KDoc ending with questionmarks`() { + val code = """ + /** + * Something correct? + */ + class Test { } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report KDoc ending with questionmarks`() { - val code = """ - /** - * Something correct? - */ - class Test { - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() + @Test + fun `does not report KDoc ending with exclamation marks`() { + val code = """ + /** + * Something correct! + */ + class Test { } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report KDoc ending with exclamation marks`() { - val code = """ - /** - * Something correct! - */ - class Test { - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() + @Test + fun `does not report KDoc ending with colon`() { + val code = """ + /** + * Something correct: + */ + class Test { } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report KDoc ending with colon`() { - val code = """ - /** - * Something correct: - */ - class Test { - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() + @Test + fun `does not report URLs in comments`() { + val code = """ + /** http://www.google.com */ + class Test1 { } - @Test - fun `does not report URLs in comments`() { - val code = """ - /** http://www.google.com */ - class Test1 { - } - - /** Look here - http://google.com */ - class Test2 { - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() + /** Look here + http://google.com */ + class Test2 { } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/KDocStyleSpec.kt b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/KDocStyleSpec.kt index 9355b5ecc70..70d7d13d33f 100644 --- a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/KDocStyleSpec.kt +++ b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/KDocStyleSpec.kt @@ -2,23 +2,18 @@ package io.gitlab.arturbosch.detekt.rules.documentation import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class KDocStyleSpec { val subject = KDocStyle() - @Nested - inner class `check referenced multi rule to only lint errors once per case` { - - @Test - fun `does only lint once`() { - val code = """ - /** Some doc */ - class Test { - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) + @Test + fun `check referenced multi rule to only lint errors once per case does only lint once`() { + val code = """ + /** Some doc */ + class Test { } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) } } diff --git a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/OutdatedDocumentationSpec.kt b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/OutdatedDocumentationSpec.kt index feb78e40e85..8a496de44e7 100644 --- a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/OutdatedDocumentationSpec.kt +++ b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/OutdatedDocumentationSpec.kt @@ -10,474 +10,470 @@ class OutdatedDocumentationSpec { val subject = OutdatedDocumentation() @Nested - inner class `OutdatedDocumentation rule` { + inner class `general` { + @Test + fun `should not report when doc is missing`() { + val withoutDoc = """ + class MyClass(someParam: String, val someProp: String) + """ + assertThat(subject.compileAndLint(withoutDoc)).isEmpty() + } - @Nested - inner class `general` { - @Test - fun `should not report when doc is missing`() { - val withoutDoc = """ - class MyClass(someParam: String, val someProp: String) - """ - assertThat(subject.compileAndLint(withoutDoc)).isEmpty() - } + @Test + fun `should not report when doc does not contain any property or param tags`() { + val docWithoutParamAndPropertyTags = """ + /** + * Some class description without referring to tags or properties + */ + class MyClass(someParam: String, val someProp: String) + """ + assertThat(subject.compileAndLint(docWithoutParamAndPropertyTags)).isEmpty() + } + } - @Test - fun `should not report when doc does not contain any property or param tags`() { - val docWithoutParamAndPropertyTags = """ - /** - * Some class description without referring to tags or properties - */ - class MyClass(someParam: String, val someProp: String) - """ - assertThat(subject.compileAndLint(docWithoutParamAndPropertyTags)).isEmpty() - } + @Nested + inner class `class` { + @Test + fun `should not report when doc match class params`() { + val correctParam = """ + /** + * @param someParam Description of param + */ + class MyClass(someParam: String) + """ + assertThat(subject.compileAndLint(correctParam)).isEmpty() } - @Nested - inner class `class` { - @Test - fun `should not report when doc match class params`() { - val correctParam = """ - /** - * @param someParam Description of param - */ - class MyClass(someParam: String) - """ - assertThat(subject.compileAndLint(correctParam)).isEmpty() - } + @Test + fun `should report when doc mismatch class param name`() { + val incorrectParamName = """ + /** + * @param someParam Description of param + */ + class MyClass(otherParam: String) + """ + assertThat(subject.compileAndLint(incorrectParamName)).hasSize(1) + } - @Test - fun `should report when doc mismatch class param name`() { - val incorrectParamName = """ - /** - * @param someParam Description of param - */ - class MyClass(otherParam: String) - """ - assertThat(subject.compileAndLint(incorrectParamName)).hasSize(1) - } + @Test + fun `should report when doc mismatch class param list`() { + val incorrectListOfParams = """ + /** + * @param someParam Description of param + * @param someSecondParam Description of param + */ + class MyClass(someParam: String) + """ + assertThat(subject.compileAndLint(incorrectListOfParams)).hasSize(1) + } - @Test - fun `should report when doc mismatch class param list`() { - val incorrectListOfParams = """ - /** - * @param someParam Description of param - * @param someSecondParam Description of param - */ - class MyClass(someParam: String) - """ - assertThat(subject.compileAndLint(incorrectListOfParams)).hasSize(1) - } + @Test + fun `should report when doc mismatch class param list order`() { + val incorrectParamOrder = """ + /** + * @param someParam Description of param + * @param otherParam Description of param + */ + class MyClass(otherParam: String, someParam: String) + """ + assertThat(subject.compileAndLint(incorrectParamOrder)).hasSize(1) + } - @Test - fun `should report when doc mismatch class param list order`() { - val incorrectParamOrder = """ - /** - * @param someParam Description of param - * @param otherParam Description of param - */ - class MyClass(otherParam: String, someParam: String) - """ - assertThat(subject.compileAndLint(incorrectParamOrder)).hasSize(1) - } + @Test + fun `should not report when doc match class params and props`() { + val correctParamAndProp = """ + /** + * @param someParam Description of param + * @property someProp Description of property + */ + class MyClass(someParam: String, val someProp: String) + """ + assertThat(subject.compileAndLint(correctParamAndProp)).isEmpty() + } - @Test - fun `should not report when doc match class params and props`() { - val correctParamAndProp = """ - /** - * @param someParam Description of param - * @property someProp Description of property - */ - class MyClass(someParam: String, val someProp: String) - """ - assertThat(subject.compileAndLint(correctParamAndProp)).isEmpty() - } + @Test + fun `should report when doc match class params but mismatch props`() { + val correctParamIncorrectProp = """ + /** + * @param someParam Description of param + * @property someProp Description of property + */ + class MyClass(someParam: String, val otherProp: String) + """ + assertThat(subject.compileAndLint(correctParamIncorrectProp)).hasSize(1) + } - @Test - fun `should report when doc match class params but mismatch props`() { - val correctParamIncorrectProp = """ - /** - * @param someParam Description of param - * @property someProp Description of property - */ - class MyClass(someParam: String, val otherProp: String) - """ - assertThat(subject.compileAndLint(correctParamIncorrectProp)).hasSize(1) - } + @Test + fun `should report when doc mismatch class params and match props`() { + val incorrectParamCorrectProp = """ + /** + * @param someParam Description of param + * @property someProp Description of property + */ + class MyClass(otherParam: String, val someProp: String) + """ + assertThat(subject.compileAndLint(incorrectParamCorrectProp)).hasSize(1) + } - @Test - fun `should report when doc mismatch class params and match props`() { - val incorrectParamCorrectProp = """ + @Test + fun `should report when doc for constructor is incorrect`() { + val incorrectConstructorDoc = """ + class MyClass { /** - * @param someParam Description of param - * @property someProp Description of property + * @param someParam */ - class MyClass(otherParam: String, val someProp: String) - """ - assertThat(subject.compileAndLint(incorrectParamCorrectProp)).hasSize(1) - } - - @Test - fun `should report when doc for constructor is incorrect`() { - val incorrectConstructorDoc = """ - class MyClass { - /** - * @param someParam - */ - constructor(otherParam: String) - } - """ - assertThat(subject.compileAndLint(incorrectConstructorDoc)).hasSize(1) - } - - @Test - fun `should report when property is documented as param`() { - val propertyAsParam = """ - /** - * @property someParam Description of param - * @param someProp Description of property - */ - class MyClass(someParam: String, val someProp: String) - """ - assertThat(subject.compileAndLint(propertyAsParam)).hasSize(1) + constructor(otherParam: String) } + """ + assertThat(subject.compileAndLint(incorrectConstructorDoc)).hasSize(1) + } - @Test - fun `should report when declarations order is incorrect`() { - val incorrectDeclarationsOrder = """ + @Test + fun `should report when property is documented as param`() { + val propertyAsParam = """ /** - * @property someProp Description of property - * @param someParam Description of param + * @property someParam Description of param + * @param someProp Description of property */ class MyClass(someParam: String, val someProp: String) - """ - assertThat(subject.compileAndLint(incorrectDeclarationsOrder)).hasSize(1) - } + """ + assertThat(subject.compileAndLint(propertyAsParam)).hasSize(1) } - @Nested - inner class `class with type params` { + @Test + fun `should report when declarations order is incorrect`() { + val incorrectDeclarationsOrder = """ + /** + * @property someProp Description of property + * @param someParam Description of param + */ + class MyClass(someParam: String, val someProp: String) + """ + assertThat(subject.compileAndLint(incorrectDeclarationsOrder)).hasSize(1) + } + } - @Test - fun `should not report when doc match class params`() { - val correctTypeParam = """ - /** - * @param T Description of type param - * @param someParam Description of param - */ - class MyClass(someParam: String) - """ - assertThat(subject.compileAndLint(correctTypeParam)).isEmpty() - } + @Nested + inner class `class with type params` { + + @Test + fun `should not report when doc match class params`() { + val correctTypeParam = """ + /** + * @param T Description of type param + * @param someParam Description of param + */ + class MyClass(someParam: String) + """ + assertThat(subject.compileAndLint(correctTypeParam)).isEmpty() + } - @Test - fun `should not report when doc match class params and no primary constructor`() { - val correctTypeParam = """ - /** - * Some description - * @param T Description of type param - */ - class MyClass - """ - assertThat(subject.compileAndLint(correctTypeParam)).isEmpty() - } + @Test + fun `should not report when doc match class params and no primary constructor`() { + val correctTypeParam = """ + /** + * Some description + * @param T Description of type param + */ + class MyClass + """ + assertThat(subject.compileAndLint(correctTypeParam)).isEmpty() + } - @Test - fun `should report when doc misses type param`() { - val missingTypeParam = """ - /** - * @param someParam Description of param - */ - class MyClass(someParam: String) - """ - assertThat(subject.compileAndLint(missingTypeParam)).hasSize(1) - } + @Test + fun `should report when doc misses type param`() { + val missingTypeParam = """ + /** + * @param someParam Description of param + */ + class MyClass(someParam: String) + """ + assertThat(subject.compileAndLint(missingTypeParam)).hasSize(1) + } - @Test - fun `should report when doc mismatch type param name`() { - val incorrectTypeParamName = """ - /** - * @param S Description of type param - * @param someParam Description of param - */ - class MyClass(someParam: String) - """ - assertThat(subject.compileAndLint(incorrectTypeParamName)).hasSize(1) - } + @Test + fun `should report when doc mismatch type param name`() { + val incorrectTypeParamName = """ + /** + * @param S Description of type param + * @param someParam Description of param + */ + class MyClass(someParam: String) + """ + assertThat(subject.compileAndLint(incorrectTypeParamName)).hasSize(1) + } - @Test - fun `should report when doc mismatch type param list`() { - val incorrectTypeParamList = """ - /** - * @param T Description of type param - * @param someParam Description of param - */ - class MyClass(someParam: String) - """ - assertThat(subject.compileAndLint(incorrectTypeParamList)).hasSize(1) - } + @Test + fun `should report when doc mismatch type param list`() { + val incorrectTypeParamList = """ + /** + * @param T Description of type param + * @param someParam Description of param + */ + class MyClass(someParam: String) + """ + assertThat(subject.compileAndLint(incorrectTypeParamList)).hasSize(1) + } + } + + @Nested + inner class `function` { + + @Test + fun `should not report when doc match function params`() { + val correctDoc = """ + /** + * @param someParam Description of param + */ + fun myFun(someParam: String) {} + """ + assertThat(subject.compileAndLint(correctDoc)).isEmpty() } - @Nested - inner class `function` { + @Test + fun `should report when doc mismatch function param name`() { + val incorrectParamName = """ + /** + * @param someParam Description of param + */ + fun myFun(otherParam: String) {} + """ + assertThat(subject.compileAndLint(incorrectParamName)).hasSize(1) + } + } - @Test - fun `should not report when doc match function params`() { - val correctDoc = """ - /** - * @param someParam Description of param - */ - fun myFun(someParam: String) {} - """ - assertThat(subject.compileAndLint(correctDoc)).isEmpty() - } + @Nested + inner class `function with type params` { + + @Test + fun `should not report when doc match function params`() { + val correctTypeParam = """ + /** + * @param T Description of type param + * @param someParam Description of param + */ + fun myFun(someParam: String) {} + """ + assertThat(subject.compileAndLint(correctTypeParam)).isEmpty() + } - @Test - fun `should report when doc mismatch function param name`() { - val incorrectParamName = """ - /** - * @param someParam Description of param - */ - fun myFun(otherParam: String) {} - """ - assertThat(subject.compileAndLint(incorrectParamName)).hasSize(1) - } + @Test + fun `should report when doc misses type param`() { + val missingTypeParam = """ + /** + * @param someParam Description of param + */ + fun myFun(someParam: String) {} + """ + assertThat(subject.compileAndLint(missingTypeParam)).hasSize(1) } - @Nested - inner class `function with type params` { + @Test + fun `should report when doc mismatch type param name`() { + val incorrectTypeParamName = """ + /** + * @param S Description of type param + * @param someParam Description of param + */ + fun myFun(someParam: String) {} + """ + assertThat(subject.compileAndLint(incorrectTypeParamName)).hasSize(1) + } + + @Test + fun `should report when doc mismatch type param list`() { + val incorrectTypeParamList = """ + /** + * @param T Description of type param + * @param someParam Description of param + */ + fun myFun(someParam: String) {} + """ + assertThat(subject.compileAndLint(incorrectTypeParamList)).hasSize(1) + } - @Test - fun `should not report when doc match function params`() { - val correctTypeParam = """ + @Test + fun `should report when not all type params are first declarations of doc`() { + val incorrectTypeParamsOrder = """ /** * @param T Description of type param * @param someParam Description of param + * @param S Description of type param */ - fun myFun(someParam: String) {} - """ - assertThat(subject.compileAndLint(correctTypeParam)).isEmpty() - } + fun myFun(someParam: String) {} + """ + assertThat(subject.compileAndLint(incorrectTypeParamsOrder)).hasSize(1) + } + } - @Test - fun `should report when doc misses type param`() { - val missingTypeParam = """ + @Nested + inner class `advanced scenarios` { + + @Test + fun `should not report when doc match all signatures`() { + val correctClassWithFunction = """ + /** + * @param someParam Description of param + */ + class MyClass(someParam: String) { /** - * @param someParam Description of param - */ - fun myFun(someParam: String) {} - """ - assertThat(subject.compileAndLint(missingTypeParam)).hasSize(1) + * @param someParam Description of param + */ + fun myFun(someParam: String) {} } + """ + assertThat(subject.compileAndLint(correctClassWithFunction)).isEmpty() + } - @Test - fun `should report when doc mismatch type param name`() { - val incorrectTypeParamName = """ + @Test + fun `should report for every class and function with incorrect doc`() { + val incorrectClassWithTwoIncorrectFunctions = """ + /** + * @param someParam Description of param + */ + class MyClass(val someProp: String) { /** - * @param S Description of type param - * @param someParam Description of param - */ - fun myFun(someParam: String) {} - """ - assertThat(subject.compileAndLint(incorrectTypeParamName)).hasSize(1) - } - - @Test - fun `should report when doc mismatch type param list`() { - val incorrectTypeParamList = """ + * @param someParam Description of param + */ + fun myFun(someParam: String, someSecondParam: String) {} /** - * @param T Description of type param - * @param someParam Description of param - */ - fun myFun(someParam: String) {} - """ - assertThat(subject.compileAndLint(incorrectTypeParamList)).hasSize(1) + * @param someParam Description of param + */ + fun myOtherFun(otherParam: String) {} + /** + * @param someParam Description of param + */ + class MyNestedClass(otherParam: String) } + """ + assertThat(subject.compileAndLint(incorrectClassWithTwoIncorrectFunctions)).hasSize(4) + } + } - @Test - fun `should report when not all type params are first declarations of doc`() { - val incorrectTypeParamsOrder = """ - /** - * @param T Description of type param - * @param someParam Description of param - * @param S Description of type param - */ - fun myFun(someParam: String) {} - """ - assertThat(subject.compileAndLint(incorrectTypeParamsOrder)).hasSize(1) - } + @Nested + inner class `configuration matchTypeParameters` { + val configuredSubject = + OutdatedDocumentation(TestConfig(mapOf("matchTypeParameters" to "false"))) + + @Test + fun `should not report when class type parameters mismatch and configuration is off`() { + val incorrectClassTypeParams = """ + /** + * @param someParam Description of param + */ + class MyClass(someParam: String) + """ + assertThat(configuredSubject.compileAndLint(incorrectClassTypeParams)).isEmpty() } - @Nested - inner class `advanced scenarios` { + @Test + fun `should not report when function type parameters mismatch and configuration is off`() { + val incorrectFunctionTypeParams = """ + /** + * @param someParam Description of param + */ + fun myFun(someParam: String) {} + """ + assertThat(configuredSubject.compileAndLint(incorrectFunctionTypeParams)).isEmpty() + } + } - @Test - fun `should not report when doc match all signatures`() { - val correctClassWithFunction = """ - /** - * @param someParam Description of param - */ - class MyClass(someParam: String) { - /** - * @param someParam Description of param - */ - fun myFun(someParam: String) {} - } - """ - assertThat(subject.compileAndLint(correctClassWithFunction)).isEmpty() - } + @Nested + inner class `configuration matchDeclarationsOrder` { + val configuredSubject = + OutdatedDocumentation(TestConfig(mapOf("matchDeclarationsOrder" to "false"))) + + @Test + fun `should not report when declarations order mismatch and configuration is off`() { + val incorrectDeclarationsOrder = """ + /** + * @param someParam Description of param + * @param otherParam Description of param + */ + class MyClass(otherParam: String, someParam: String) + """ + assertThat(configuredSubject.compileAndLint(incorrectDeclarationsOrder)).isEmpty() + } - @Test - fun `should report for every class and function with incorrect doc`() { - val incorrectClassWithTwoIncorrectFunctions = """ - /** - * @param someParam Description of param - */ - class MyClass(val someProp: String) { - /** - * @param someParam Description of param - */ - fun myFun(someParam: String, someSecondParam: String) {} - /** - * @param someParam Description of param - */ - fun myOtherFun(otherParam: String) {} - /** - * @param someParam Description of param - */ - class MyNestedClass(otherParam: String) - } - """ - assertThat(subject.compileAndLint(incorrectClassWithTwoIncorrectFunctions)).hasSize(4) - } + @Test + fun `should not report when declarations with types order mismatch and configuration is off`() { + val incorrectDeclarationsOrderWithType = """ + /** + * @param S Description of type param + * @param someParam Description of param + * @param otherParam Description of param + * @param T Description of param + */ + fun myFun(otherParam: String, someParam: String) {} + """ + assertThat(configuredSubject.compileAndLint(incorrectDeclarationsOrderWithType)).isEmpty() } + } - @Nested - inner class `configuration matchTypeParameters` { - val configuredSubject = - OutdatedDocumentation(TestConfig(mapOf("matchTypeParameters" to "false"))) + @Nested + inner class `configuration allowParamOnConstructorProperties` { + val configuredSubject = + OutdatedDocumentation(TestConfig(mapOf("allowParamOnConstructorProperties" to "true"))) - @Test - fun `should not report when class type parameters mismatch and configuration is off`() { - val incorrectClassTypeParams = """ + @Test + fun `should not report when property is documented as param`() { + val propertyAsParam = """ /** * @param someParam Description of param + * @param someProp Description of property */ - class MyClass(someParam: String) - """ - assertThat(configuredSubject.compileAndLint(incorrectClassTypeParams)).isEmpty() - } + class MyClass(someParam: String, val someProp: String) + """ + assertThat(configuredSubject.compileAndLint(propertyAsParam)).isEmpty() + } - @Test - fun `should not report when function type parameters mismatch and configuration is off`() { - val incorrectFunctionTypeParams = """ + @Test + fun `should not report when property is documented as property`() { + val propertyAsParam = """ /** * @param someParam Description of param + * @property someProp Description of property */ - fun myFun(someParam: String) {} - """ - assertThat(configuredSubject.compileAndLint(incorrectFunctionTypeParams)).isEmpty() - } + class MyClass(someParam: String, val someProp: String) + """ + assertThat(configuredSubject.compileAndLint(propertyAsParam)).isEmpty() } + } - @Nested - inner class `configuration matchDeclarationsOrder` { - val configuredSubject = - OutdatedDocumentation(TestConfig(mapOf("matchDeclarationsOrder" to "false"))) + @Nested + inner class `configuration matchDeclarationsOrder and allowParamOnConstructorProperties` { + val configuredSubject = + OutdatedDocumentation( + TestConfig( + mapOf( + "matchDeclarationsOrder" to "false", + "allowParamOnConstructorProperties" to "true" + ) + ) + ) - @Test - fun `should not report when declarations order mismatch and configuration is off`() { - val incorrectDeclarationsOrder = """ + @Test + fun `should not report when property is documented as param`() { + val propertyAsParam = """ /** * @param someParam Description of param - * @param otherParam Description of param + * @param someProp Description of property */ - class MyClass(otherParam: String, someParam: String) - """ - assertThat(configuredSubject.compileAndLint(incorrectDeclarationsOrder)).isEmpty() - } + class MyClass(someParam: String, val someProp: String) + """ + assertThat(configuredSubject.compileAndLint(propertyAsParam)).isEmpty() + } - @Test - fun `should not report when declarations with types order mismatch and configuration is off`() { - val incorrectDeclarationsOrderWithType = """ + @Test + fun `should not report when property is documented as property`() { + val propertyAsParam = """ /** - * @param S Description of type param * @param someParam Description of param - * @param otherParam Description of param - * @param T Description of param + * @property someProp Description of property */ - fun myFun(otherParam: String, someParam: String) {} - """ - assertThat(configuredSubject.compileAndLint(incorrectDeclarationsOrderWithType)).isEmpty() - } - } - - @Nested - inner class `configuration allowParamOnConstructorProperties` { - val configuredSubject = - OutdatedDocumentation(TestConfig(mapOf("allowParamOnConstructorProperties" to "true"))) - - @Test - fun `should not report when property is documented as param`() { - val propertyAsParam = """ - /** - * @param someParam Description of param - * @param someProp Description of property - */ - class MyClass(someParam: String, val someProp: String) - """ - assertThat(configuredSubject.compileAndLint(propertyAsParam)).isEmpty() - } - - @Test - fun `should not report when property is documented as property`() { - val propertyAsParam = """ - /** - * @param someParam Description of param - * @property someProp Description of property - */ - class MyClass(someParam: String, val someProp: String) - """ - assertThat(configuredSubject.compileAndLint(propertyAsParam)).isEmpty() - } - } - - @Nested - inner class `configuration matchDeclarationsOrder and allowParamOnConstructorProperties` { - val configuredSubject = - OutdatedDocumentation( - TestConfig( - mapOf( - "matchDeclarationsOrder" to "false", - "allowParamOnConstructorProperties" to "true" - ) - ) - ) - - @Test - fun `should not report when property is documented as param`() { - val propertyAsParam = """ - /** - * @param someParam Description of param - * @param someProp Description of property - */ - class MyClass(someParam: String, val someProp: String) - """ - assertThat(configuredSubject.compileAndLint(propertyAsParam)).isEmpty() - } - - @Test - fun `should not report when property is documented as property`() { - val propertyAsParam = """ - /** - * @param someParam Description of param - * @property someProp Description of property - */ - class MyClass(someParam: String, val someProp: String) - """ - assertThat(configuredSubject.compileAndLint(propertyAsParam)).isEmpty() - } + class MyClass(someParam: String, val someProp: String) + """ + assertThat(configuredSubject.compileAndLint(propertyAsParam)).isEmpty() } } } diff --git a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/UndocumentedPublicClassSpec.kt b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/UndocumentedPublicClassSpec.kt index 3f56a13cf55..894ab5ad5cc 100644 --- a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/UndocumentedPublicClassSpec.kt +++ b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/UndocumentedPublicClassSpec.kt @@ -3,7 +3,6 @@ package io.gitlab.arturbosch.detekt.rules.documentation import io.gitlab.arturbosch.detekt.test.TestConfig import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test private const val SEARCH_IN_NESTED_CLASS = "searchInNestedClass" @@ -15,227 +14,223 @@ class UndocumentedPublicClassSpec { val subject = UndocumentedPublicClass() val inner = """ - /** Some doc */ - class TestInner { - inner class Inner - } + /** Some doc */ + class TestInner { + inner class Inner + } """ val innerObject = """ - /** Some doc */ - class TestInner { - object Inner - } + /** Some doc */ + class TestInner { + object Inner + } """ val innerInterface = """ - /** Some doc */ - class TestInner { - interface Something - } + /** Some doc */ + class TestInner { + interface Something + } """ val nested = """ - /** Some doc */ - class TestNested { - class Nested - } + /** Some doc */ + class TestNested { + class Nested + } """ val nestedPublic = """ - /** Some doc */ - class TestNested { - public class Nested - } + /** Some doc */ + class TestNested { + public class Nested + } """ val nestedPrivate = """ - /** Some doc */ - class TestNested { - private class Nested - } + /** Some doc */ + class TestNested { + private class Nested + } """ val privateClass = "private class TestNested {}" val internalClass = "internal class TestNested {}" - @Nested - inner class `UndocumentedPublicClass rule` { - - @Test - fun `should report inner classes by default`() { - assertThat(subject.compileAndLint(inner)).hasSize(1) - } + @Test + fun `should report inner classes by default`() { + assertThat(subject.compileAndLint(inner)).hasSize(1) + } - @Test - fun `should report inner object by default`() { - assertThat(subject.compileAndLint(innerObject)).hasSize(1) - } + @Test + fun `should report inner object by default`() { + assertThat(subject.compileAndLint(innerObject)).hasSize(1) + } - @Test - fun `should report inner interfaces by default`() { - assertThat(subject.compileAndLint(innerInterface)).hasSize(1) - } + @Test + fun `should report inner interfaces by default`() { + assertThat(subject.compileAndLint(innerInterface)).hasSize(1) + } - @Test - fun `should report nested classes by default`() { - assertThat(subject.compileAndLint(nested)).hasSize(1) - } + @Test + fun `should report nested classes by default`() { + assertThat(subject.compileAndLint(nested)).hasSize(1) + } - @Test - fun `should report explicit public nested classes by default`() { - assertThat(subject.compileAndLint(nestedPublic)).hasSize(1) - } + @Test + fun `should report explicit public nested classes by default`() { + assertThat(subject.compileAndLint(nestedPublic)).hasSize(1) + } - @Test - fun `should not report internal classes`() { - assertThat(subject.compileAndLint(internalClass)).isEmpty() - } + @Test + fun `should not report internal classes`() { + assertThat(subject.compileAndLint(internalClass)).isEmpty() + } - @Test - fun `should not report private classes`() { - assertThat(subject.compileAndLint(privateClass)).isEmpty() - } + @Test + fun `should not report private classes`() { + assertThat(subject.compileAndLint(privateClass)).isEmpty() + } - @Test - fun `should not report nested private classes`() { - assertThat(subject.compileAndLint(nestedPrivate)).isEmpty() - } + @Test + fun `should not report nested private classes`() { + assertThat(subject.compileAndLint(nestedPrivate)).isEmpty() + } - @Test - fun `should not report inner classes when turned off`() { - val findings = - UndocumentedPublicClass(TestConfig(mapOf(SEARCH_IN_INNER_CLASS to "false"))).compileAndLint(inner) - assertThat(findings).isEmpty() - } + @Test + fun `should not report inner classes when turned off`() { + val findings = + UndocumentedPublicClass(TestConfig(mapOf(SEARCH_IN_INNER_CLASS to "false"))).compileAndLint(inner) + assertThat(findings).isEmpty() + } - @Test - fun `should not report inner objects when turned off`() { - val findings = - UndocumentedPublicClass(TestConfig(mapOf(SEARCH_IN_INNER_OBJECT to "false"))).compileAndLint(innerObject) - assertThat(findings).isEmpty() - } + @Test + fun `should not report inner objects when turned off`() { + val findings = + UndocumentedPublicClass(TestConfig(mapOf(SEARCH_IN_INNER_OBJECT to "false"))).compileAndLint(innerObject) + assertThat(findings).isEmpty() + } - @Test - fun `should not report inner interfaces when turned off`() { - val findings = - UndocumentedPublicClass(TestConfig(mapOf(SEARCH_IN_INNER_INTERFACE to "false"))).compileAndLint( - innerInterface - ) - assertThat(findings).isEmpty() - } + @Test + fun `should not report inner interfaces when turned off`() { + val findings = + UndocumentedPublicClass(TestConfig(mapOf(SEARCH_IN_INNER_INTERFACE to "false"))).compileAndLint( + innerInterface + ) + assertThat(findings).isEmpty() + } - @Test - fun `should not report nested classes when turned off`() { - val findings = - UndocumentedPublicClass(TestConfig(mapOf(SEARCH_IN_NESTED_CLASS to "false"))).compileAndLint(nested) - assertThat(findings).isEmpty() - } + @Test + fun `should not report nested classes when turned off`() { + val findings = + UndocumentedPublicClass(TestConfig(mapOf(SEARCH_IN_NESTED_CLASS to "false"))).compileAndLint(nested) + assertThat(findings).isEmpty() + } - @Test - fun `should report missing doc over object declaration`() { - assertThat(subject.compileAndLint("object o")).hasSize(1) - } + @Test + fun `should report missing doc over object declaration`() { + assertThat(subject.compileAndLint("object o")).hasSize(1) + } - @Test - fun `should not report non-public nested classes`() { - val code = """ - internal class Outer { - class Nested - inner class Inner - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() + @Test + fun `should not report non-public nested classes`() { + val code = """ + internal class Outer { + class Nested + inner class Inner } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `should not report non-public nested interfaces`() { - val code = """ - internal class Outer { - interface Inner - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() + @Test + fun `should not report non-public nested interfaces`() { + val code = """ + internal class Outer { + interface Inner } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `should not report non-public nested objects`() { - val code = """ - internal class Outer { - object Inner - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() + @Test + fun `should not report non-public nested objects`() { + val code = """ + internal class Outer { + object Inner } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `should not report for documented public object`() { - val code = """ + @Test + fun `should not report for documented public object`() { + val code = """ + /** + * Class docs not being recognized. + */ + object Main { /** - * Class docs not being recognized. + * The entry point for the application. + * + * @param args The list of process arguments. */ - object Main { - /** - * The entry point for the application. - * - * @param args The list of process arguments. - */ - @JvmStatic - fun main(args: Array) { - } + @JvmStatic + fun main(args: Array) { } - """ - assertThat(subject.compileAndLint(code)).isEmpty() } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `should not report for anonymous objects`() { - val code = """ - fun main(args: Array) { - val value = object : Iterator { - override fun hasNext() = true - override fun next() = 1 - } + @Test + fun `should not report for anonymous objects`() { + val code = """ + fun main(args: Array) { + val value = object : Iterator { + override fun hasNext() = true + override fun next() = 1 } - """ - assertThat(subject.compileAndLint(code)).isEmpty() } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `should report for enum classes`() { - val code = """ - enum class Enum { - CONSTANT - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) + @Test + fun `should report for enum classes`() { + val code = """ + enum class Enum { + CONSTANT } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `should not report for enum constants`() { - val code = """ - /** Some doc */ - enum class Enum { - CONSTANT - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() + @Test + fun `should not report for enum constants`() { + val code = """ + /** Some doc */ + enum class Enum { + CONSTANT } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `should not report for fun interfaces`() { - val code = """ + @Test + fun `should not report for fun interfaces`() { + val code = """ + /** + * This interface is an example + */ + fun interface Example { /** - * This interface is an example + * Trigger when done */ - fun interface Example { - /** - * Trigger when done - */ - fun onComplete() - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() + fun onComplete() } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/UndocumentedPublicFunctionSpec.kt b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/UndocumentedPublicFunctionSpec.kt index 50a5eb9a32c..86d255fec6d 100644 --- a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/UndocumentedPublicFunctionSpec.kt +++ b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/UndocumentedPublicFunctionSpec.kt @@ -8,116 +8,149 @@ import org.junit.jupiter.api.Test class UndocumentedPublicFunctionSpec { val subject = UndocumentedPublicFunction() - @Nested - inner class `UndocumentedPublicFunction rule` { + @Test + fun `reports undocumented public functions`() { + val code = """ + fun noComment1() {} + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports undocumented public functions`() { - val code = """ + @Test + fun `reports undocumented public function in object`() { + val code = """ + object Test { fun noComment1() {} - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports undocumented public function in object`() { - val code = """ - object Test { + @Test + fun `reports undocumented public function in nested object`() { + val code = """ + class Test { + object Test2 { fun noComment1() {} } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports undocumented public function in nested object`() { - val code = """ - class Test { - object Test2 { - fun noComment1() {} - } + @Test + fun `reports undocumented public functions in companion object`() { + val code = """ + class Test { + companion object { + fun noComment1() {} + public fun noComment2() {} } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(2) + } - @Test - fun `reports undocumented public functions in companion object`() { - val code = """ - class Test { - companion object { - fun noComment1() {} - public fun noComment2() {} - } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(2) - } + @Test + fun `reports undocumented public function in an interface`() { + val code = """ + interface Test { + fun noComment1() + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports undocumented public function in an interface`() { - val code = """ - interface Test { - fun noComment1() - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `does not report documented public function`() { + val code = """ + /** + * Comment + */ + fun commented1() {} + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report documented public function`() { - val code = """ - /** - * Comment - */ - fun commented1() {} - """ - assertThat(subject.compileAndLint(code)).isEmpty() + @Test + fun `does not report documented public function in class`() { + val code = """ + class Test { + /** + * + */ + fun commented() {} } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report documented public function in class`() { - val code = """ + @Test + fun `does not report undocumented internal and private function`() { + val code = """ class Test { - /** - * - */ - fun commented() {} + internal fun no1(){} + private fun no2(){} } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report undocumented internal and private function`() { - val code = """ - class Test { - internal fun no1(){} - private fun no2(){} - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report undocumented nested function`() { + val code = """ + /** + * Comment + */ + fun commented() { + fun iDontNeedDoc() {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report undocumented nested function`() { - val code = """ - /** - * Comment - */ - fun commented() { - fun iDontNeedDoc() {} - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report public functions in internal class`() { + val code = """ + internal class NoComments { + fun nope1() {} + public fun nope2() {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report public functions in private class`() { + val code = """ + private class NoComments { + fun nope1() {} + public fun nope2() {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report public functions in private object`() { + val code = """ + private object Test { + fun noComment1() {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + @Nested + inner class `nested class` { @Test - fun `does not report public functions in internal class`() { + fun `does not report public functions in internal interface`() { val code = """ - internal class NoComments { - fun nope1() {} - public fun nope2() {} + internal interface Foo { + interface Bar { + fun f() { + } + } } """ assertThat(subject.compileAndLint(code)).isEmpty() @@ -126,9 +159,13 @@ class UndocumentedPublicFunctionSpec { @Test fun `does not report public functions in private class`() { val code = """ - private class NoComments { - fun nope1() {} - public fun nope2() {} + class Foo { + private class Bar { + class Baz { + fun f() { + } + } + } } """ assertThat(subject.compileAndLint(code)).isEmpty() @@ -137,55 +174,14 @@ class UndocumentedPublicFunctionSpec { @Test fun `does not report public functions in private object`() { val code = """ - private object Test { - fun noComment1() {} + private object Foo { + class Bar { + fun f() { + } + } } """ assertThat(subject.compileAndLint(code)).isEmpty() } - - @Nested - inner class `nested class` { - @Test - fun `does not report public functions in internal interface`() { - val code = """ - internal interface Foo { - interface Bar { - fun f() { - } - } - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report public functions in private class`() { - val code = """ - class Foo { - private class Bar { - class Baz { - fun f() { - } - } - } - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report public functions in private object`() { - val code = """ - private object Foo { - class Bar { - fun f() { - } - } - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - } } } diff --git a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/UndocumentedPublicPropertySpec.kt b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/UndocumentedPublicPropertySpec.kt index 9dc8245f18f..053ea6c6f90 100644 --- a/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/UndocumentedPublicPropertySpec.kt +++ b/detekt-rules-documentation/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/UndocumentedPublicPropertySpec.kt @@ -8,336 +8,332 @@ import org.junit.jupiter.api.Test class UndocumentedPublicPropertySpec { val subject = UndocumentedPublicProperty() - @Nested - inner class `UndocumentedPublicProperty rule` { + @Test + fun `reports undocumented public property`() { + val code = "val a = 1" + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports undocumented public property`() { - val code = "val a = 1" - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports undocumented public property in objects`() { + val code = """ + object Test { + val a = 1 + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports undocumented public property in objects`() { - val code = """ - object Test { - val a = 1 + @Test + fun `reports undocumented public property in nested objects`() { + val code = """ + class Test { + object NestedTest { + val a = 1 } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports undocumented public property in nested objects`() { - val code = """ - class Test { - object NestedTest { - val a = 1 - } + @Test + fun `reports undocumented public properties in companion object`() { + val code = """ + class Test { + companion object { + val a = 1 + public val b = 1 } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(2) + } - @Test - fun `reports undocumented public properties in companion object`() { - val code = """ - class Test { - companion object { - val a = 1 - public val b = 1 - } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(2) - } + @Test + fun `reports undocumented public property in an interface`() { + val code = """ + interface Test { + val a: Int + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports undocumented public property in an interface`() { - val code = """ - interface Test { - val a: Int - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports undocumented public properties in a primary constructor`() { + val code = "class Test(val a: Int)" + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports undocumented public properties in a primary constructor`() { - val code = "class Test(val a: Int)" - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports undocumented public property in a primary constructor`() { + val code = "/* comment */ class Test(val a: Int)" + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports undocumented public property in a primary constructor`() { - val code = "/* comment */ class Test(val a: Int)" - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `does not report documented public property`() { + val code = """ + /** + * Comment + */ + val a = 1 + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report documented public property`() { - val code = """ + @Test + fun `does not report documented public property in class`() { + val code = """ + class Test { + /** + * Comment + */ + val a = 1 + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report undocumented, public and overridden property in class`() { + val code = """ + interface I { /** * Comment */ + val a: Int + } + + class Test : I { + override val a = 1 + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report undocumented internal and private property`() { + val code = """ + class Test { + internal val a = 1 + private val b = 1 + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report local variables`() { + val code = """ + fun commented(x: Int) { + var a = x + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report public properties in internal class`() { + val code = """ + internal class NoComments { + public val a = 1 + val b = 1 + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report public properties in private class`() { + val code = """ + private class NoComments { + public val a = 1 + val b = 1 + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report properties in a secondary constructor`() { + val code = """ + class Test() { + constructor(a: Int) : this() + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report undocumented non-public properties in a primary constructor`() { + val code = """ + class Test1(internal val a: Int) + class Test2(b: Int) + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report undocumented public properties in a primary constructor for an internal class`() { + val code = "internal class Test(val a: Int)" + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report documented public properties in a primary constructor`() { + val code = """ + /** + * @property a int1 + * [b] int2 + * @property [c] int3 + * @param d int4 + */ + class Test( + val a: Int, + val b: Int, + val c: Int, + val d: Int, + /** + * Some docs. + */ + val e: Int + ) + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report undocumented public properties in private object`() { + val code = """ + private object Test { val a = 1 - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Nested + inner class `public properties in nested classes` { @Test - fun `does not report documented public property in class`() { + fun `reports undocumented public properties in nested classes`() { val code = """ - class Test { - /** - * Comment - */ - val a = 1 + class Outer { + class Inner { + val i = 0 + + class InnerInner { + val ii = 0 + } } + } """ - assertThat(subject.compileAndLint(code)).isEmpty() + assertThat(subject.compileAndLint(code)).hasSize(2) } @Test - fun `does not report undocumented, public and overridden property in class`() { + fun `reports undocumented public properties in inner classes`() { val code = """ - interface I { - /** - * Comment - */ - val a: Int - } - - class Test : I { - override val a = 1 + class Outer { + inner class Inner { + val i = 0 } + } """ - assertThat(subject.compileAndLint(code)).isEmpty() + assertThat(subject.compileAndLint(code)).hasSize(1) } @Test - fun `does not report undocumented internal and private property`() { + fun `reports undocumented public properties in classes nested in objects`() { val code = """ - class Test { - internal val a = 1 - private val b = 1 + object Outer { + class Inner { + val i = 0 } + } """ - assertThat(subject.compileAndLint(code)).isEmpty() + assertThat(subject.compileAndLint(code)).hasSize(1) } @Test - fun `does not report local variables`() { + fun `does not report undocumented and non-public properties in nested classes`() { val code = """ - fun commented(x: Int) { - var a = x + internal class Outer { + class Inner { + val i = 0 } + } """ assertThat(subject.compileAndLint(code)).isEmpty() } @Test - fun `does not report public properties in internal class`() { + fun `does not report undocumented and non-public properties in inner classes`() { val code = """ - internal class NoComments { - public val a = 1 - val b = 1 + internal class Outer { + inner class Inner { + val i = 0 } + } """ assertThat(subject.compileAndLint(code)).isEmpty() } + } + + @Nested + inner class `public properties in primary constructors inside nested classes` { @Test - fun `does not report public properties in private class`() { + fun `reports undocumented public properties in nested classes`() { val code = """ - private class NoComments { - public val a = 1 - val b = 1 + class Outer(val a: Int) { + class Inner(val b: Int) { + class InnerInner(val c: Int) } + } """ - assertThat(subject.compileAndLint(code)).isEmpty() + assertThat(subject.compileAndLint(code)).hasSize(3) } @Test - fun `does not report properties in a secondary constructor`() { + fun `reports undocumented public properties in inner classes`() { val code = """ - class Test() { - constructor(a: Int) : this() - } + class Outer(val a: Int) { + inner class Inner(val b: Int) + } """ - assertThat(subject.compileAndLint(code)).isEmpty() + assertThat(subject.compileAndLint(code)).hasSize(2) } @Test - fun `does not report undocumented non-public properties in a primary constructor`() { + fun `reports undocumented public properties in classes nested in objects`() { val code = """ - class Test1(internal val a: Int) - class Test2(b: Int) + object Outer { + class Inner(val a: Int) + } """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report undocumented public properties in a primary constructor for an internal class`() { - val code = "internal class Test(val a: Int)" - assertThat(subject.compileAndLint(code)).isEmpty() + assertThat(subject.compileAndLint(code)).hasSize(1) } @Test - fun `does not report documented public properties in a primary constructor`() { + fun `does not report undocumented and non-public properties in nested classes`() { val code = """ - /** - * @property a int1 - * [b] int2 - * @property [c] int3 - * @param d int4 - */ - class Test( - val a: Int, - val b: Int, - val c: Int, - val d: Int, - /** - * Some docs. - */ - val e: Int - ) + internal class Outer(val a: Int) { + class Inner(val b: Int) + } """ assertThat(subject.compileAndLint(code)).isEmpty() } @Test - fun `does not report undocumented public properties in private object`() { + fun `does not report undocumented and non-public properties in inner classes`() { val code = """ - private object Test { - val a = 1 - } + internal class Outer(val a: Int) { + inner class Inner(val b: Int) + } """ assertThat(subject.compileAndLint(code)).isEmpty() } - - @Nested - inner class `public properties in nested classes` { - - @Test - fun `reports undocumented public properties in nested classes`() { - val code = """ - class Outer { - class Inner { - val i = 0 - - class InnerInner { - val ii = 0 - } - } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(2) - } - - @Test - fun `reports undocumented public properties in inner classes`() { - val code = """ - class Outer { - inner class Inner { - val i = 0 - } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `reports undocumented public properties in classes nested in objects`() { - val code = """ - object Outer { - class Inner { - val i = 0 - } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `does not report undocumented and non-public properties in nested classes`() { - val code = """ - internal class Outer { - class Inner { - val i = 0 - } - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report undocumented and non-public properties in inner classes`() { - val code = """ - internal class Outer { - inner class Inner { - val i = 0 - } - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - } - - @Nested - inner class `public properties in primary constructors inside nested classes` { - - @Test - fun `reports undocumented public properties in nested classes`() { - val code = """ - class Outer(val a: Int) { - class Inner(val b: Int) { - class InnerInner(val c: Int) - } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(3) - } - - @Test - fun `reports undocumented public properties in inner classes`() { - val code = """ - class Outer(val a: Int) { - inner class Inner(val b: Int) - } - """ - assertThat(subject.compileAndLint(code)).hasSize(2) - } - - @Test - fun `reports undocumented public properties in classes nested in objects`() { - val code = """ - object Outer { - class Inner(val a: Int) - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `does not report undocumented and non-public properties in nested classes`() { - val code = """ - internal class Outer(val a: Int) { - class Inner(val b: Int) - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report undocumented and non-public properties in inner classes`() { - val code = """ - internal class Outer(val a: Int) { - inner class Inner(val b: Int) - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - } } } diff --git a/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyBlocksMultiRuleSpec.kt b/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyBlocksMultiRuleSpec.kt index 89dabbdf03d..ee861bfc955 100644 --- a/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyBlocksMultiRuleSpec.kt +++ b/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyBlocksMultiRuleSpec.kt @@ -7,7 +7,6 @@ import io.gitlab.arturbosch.detekt.test.lint import io.gitlab.arturbosch.detekt.test.yamlConfig import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class EmptyBlocksMultiRuleSpec { @@ -21,49 +20,45 @@ class EmptyBlocksMultiRuleSpec { subject = EmptyBlocks() } - @Nested - inner class `multi rule with all empty block rules` { - - @Test - fun `should report one finding per rule`() { - val findings = subject.lint(file) - // -1 because the empty kt file rule doesn't get triggered in the 'Empty' test file - val rulesSize = subject.rules.size - 1 - assertThat(findings).hasSize(rulesSize) - } + @Test + fun `should report one finding per rule`() { + val findings = subject.lint(file) + // -1 because the empty kt file rule doesn't get triggered in the 'Empty' test file + val rulesSize = subject.rules.size - 1 + assertThat(findings).hasSize(rulesSize) + } - @Test - fun `should not report any as all empty block rules are deactivated`() { - val config = yamlConfig("deactivated-empty-blocks.yml") - val ruleSet = EmptyCodeProvider().instance(config) + @Test + fun `should not report any as all empty block rules are deactivated`() { + val config = yamlConfig("deactivated-empty-blocks.yml") + val ruleSet = EmptyCodeProvider().instance(config) - @Suppress("DEPRECATION") - val findings = ruleSet.accept(file) + @Suppress("DEPRECATION") + val findings = ruleSet.accept(file) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `reports an empty kt file`() { - assertThat(subject.compileAndLint("")).hasSize(1) - } + @Test + fun `reports an empty kt file`() { + assertThat(subject.compileAndLint("")).hasSize(1) + } - @Test - fun `reports no duplicated findings - issue #1605`() { - val findings = subject.compileAndLint( - """ - class EmptyBlocks { - class EmptyClass {} - fun exceptionHandling() { - try { - println() - } finally { - } + @Test + fun `reports no duplicated findings - issue #1605`() { + val findings = subject.compileAndLint( + """ + class EmptyBlocks { + class EmptyClass {} + fun exceptionHandling() { + try { + println() + } finally { } } - """ - ) - assertThat(findings).hasSize(2) - } + } + """ + ) + assertThat(findings).hasSize(2) } } diff --git a/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyClassBlockSpec.kt b/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyClassBlockSpec.kt index b7a0997ebc9..68c2ff8427d 100644 --- a/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyClassBlockSpec.kt +++ b/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyClassBlockSpec.kt @@ -3,72 +3,67 @@ package io.gitlab.arturbosch.detekt.rules.empty import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class EmptyClassBlockSpec { private val subject = EmptyClassBlock(Config.empty) - @Nested - inner class `EmptyClassBlock rule` { - - @Test - fun `reports the empty class body`() { - val code = "class SomeClass {}" - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports the empty class body`() { + val code = "class SomeClass {}" + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report class with comments in the body`() { - val code = """ - class SomeClass { - // Some comment to explain what this class is supposed to do - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report class with comments in the body`() { + val code = """ + class SomeClass { + // Some comment to explain what this class is supposed to do + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report class with multiline comments in the body`() { - val code = """ - class SomeClass { - /* - Some comment to explain what this class is supposed to do - */ - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report class with multiline comments in the body`() { + val code = """ + class SomeClass { + /* + Some comment to explain what this class is supposed to do + */ + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports the empty nested class body`() { - val code = """ - class SomeClass { - class EmptyClass {} - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports the empty nested class body`() { + val code = """ + class SomeClass { + class EmptyClass {} + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports the empty object body`() { - val code = "object SomeObject {}" - val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(1) - assertThat(findings).hasTextLocations(18 to 20) - } + @Test + fun `reports the empty object body`() { + val code = "object SomeObject {}" + val findings = subject.compileAndLint(code) + assertThat(findings).hasSize(1) + assertThat(findings).hasTextLocations(18 to 20) + } - @Test - fun `does not report the object if it is of an anonymous class`() { - val code = """ - open class Open + @Test + fun `does not report the object if it is of an anonymous class`() { + val code = """ + open class Open - fun f() { - object : Open() {} - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + fun f() { + object : Open() {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyCodeSpec.kt b/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyCodeSpec.kt index ecba3462936..8cd9654493f 100644 --- a/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyCodeSpec.kt +++ b/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyCodeSpec.kt @@ -9,7 +9,6 @@ import io.gitlab.arturbosch.detekt.test.compileAndLint import io.gitlab.arturbosch.detekt.test.lint import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatExceptionOfType -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import java.util.regex.PatternSyntaxException @@ -25,132 +24,128 @@ class EmptyCodeSpec { } """ - @Nested - inner class `EmptyCatchBlock rule` { - - @Test - fun `findsEmptyCatch`() { - test { EmptyCatchBlock(Config.empty) } - } + @Test + fun `findsEmptyCatch`() { + test { EmptyCatchBlock(Config.empty) } + } - @Test - fun `findsEmptyNestedCatch`() { - val code = """ - fun f() { + @Test + fun `findsEmptyNestedCatch`() { + val code = """ + fun f() { + try { + } catch (ignore: Exception) { try { - } catch (ignore: Exception) { - try { - } catch (e: Exception) { - } + } catch (e: Exception) { } } - """ - assertThat(EmptyCatchBlock(Config.empty).compileAndLint(code)).hasSize(1) } + """ + assertThat(EmptyCatchBlock(Config.empty).compileAndLint(code)).hasSize(1) + } - @Test - fun `doesNotReportIgnoredOrExpectedException`() { - val code = """ - fun f() { - try { - } catch (ignore: IllegalArgumentException) { - } catch (expected: Exception) { - } + @Test + fun `doesNotReportIgnoredOrExpectedException`() { + val code = """ + fun f() { + try { + } catch (ignore: IllegalArgumentException) { + } catch (expected: Exception) { } - """ - assertThat(EmptyCatchBlock(Config.empty).compileAndLint(code)).isEmpty() } + """ + assertThat(EmptyCatchBlock(Config.empty).compileAndLint(code)).isEmpty() + } - @Test - fun `doesNotReportEmptyCatchWithConfig`() { - val code = """ - fun f() { - try { - } catch (foo: Exception) { - } + @Test + fun `doesNotReportEmptyCatchWithConfig`() { + val code = """ + fun f() { + try { + } catch (foo: Exception) { } - """ - val config = TestConfig(mapOf(ALLOWED_EXCEPTION_NAME_REGEX to "foo")) - assertThat(EmptyCatchBlock(config).compileAndLint(code)).isEmpty() } + """ + val config = TestConfig(mapOf(ALLOWED_EXCEPTION_NAME_REGEX to "foo")) + assertThat(EmptyCatchBlock(config).compileAndLint(code)).isEmpty() + } - @Test - fun `findsEmptyFinally`() { - test { EmptyFinallyBlock(Config.empty) } - } + @Test + fun `findsEmptyFinally`() { + test { EmptyFinallyBlock(Config.empty) } + } - @Test - fun `findsEmptyIf`() { - test { EmptyIfBlock(Config.empty) } - } + @Test + fun `findsEmptyIf`() { + test { EmptyIfBlock(Config.empty) } + } - @Test - fun `findsEmptyElse`() { - test { EmptyElseBlock(Config.empty) } - } + @Test + fun `findsEmptyElse`() { + test { EmptyElseBlock(Config.empty) } + } - @Test - fun `findsEmptyFor`() { - test { EmptyForBlock(Config.empty) } - } + @Test + fun `findsEmptyFor`() { + test { EmptyForBlock(Config.empty) } + } - @Test - fun `findsEmptyWhile`() { - test { EmptyWhileBlock(Config.empty) } - } + @Test + fun `findsEmptyWhile`() { + test { EmptyWhileBlock(Config.empty) } + } - @Test - fun `findsEmptyDoWhile`() { - test { EmptyDoWhileBlock(Config.empty) } - } + @Test + fun `findsEmptyDoWhile`() { + test { EmptyDoWhileBlock(Config.empty) } + } - @Test - fun `findsEmptyFun`() { - test { EmptyFunctionBlock(Config.empty) } - } + @Test + fun `findsEmptyFun`() { + test { EmptyFunctionBlock(Config.empty) } + } - @Test - fun `findsEmptyClass`() { - test { EmptyClassBlock(Config.empty) } - } + @Test + fun `findsEmptyClass`() { + test { EmptyClassBlock(Config.empty) } + } - @Test - fun `findsEmptyTry`() { - test { EmptyTryBlock(Config.empty) } - } + @Test + fun `findsEmptyTry`() { + test { EmptyTryBlock(Config.empty) } + } - @Test - fun `findsEmptyWhen`() { - test { EmptyWhenBlock(Config.empty) } - } + @Test + fun `findsEmptyWhen`() { + test { EmptyWhenBlock(Config.empty) } + } - @Test - fun `findsEmptyInit`() { - test { EmptyInitBlock(Config.empty) } - } + @Test + fun `findsEmptyInit`() { + test { EmptyInitBlock(Config.empty) } + } - @Test - fun `findsOneEmptySecondaryConstructor`() { - test { EmptySecondaryConstructor(Config.empty) } - } + @Test + fun `findsOneEmptySecondaryConstructor`() { + test { EmptySecondaryConstructor(Config.empty) } + } - @Test - fun `doesNotFailWithInvalidRegexWhenDisabled`() { - val configValues = mapOf( - "active" to "false", - ALLOWED_EXCEPTION_NAME_REGEX to "*foo" - ) - val config = TestConfig(configValues) - assertThat(EmptyCatchBlock(config).compileAndLint(regexTestingCode)).isEmpty() - } + @Test + fun `doesNotFailWithInvalidRegexWhenDisabled`() { + val configValues = mapOf( + "active" to "false", + ALLOWED_EXCEPTION_NAME_REGEX to "*foo" + ) + val config = TestConfig(configValues) + assertThat(EmptyCatchBlock(config).compileAndLint(regexTestingCode)).isEmpty() + } - @Test - fun `doesFailWithInvalidRegex`() { - val configValues = mapOf(ALLOWED_EXCEPTION_NAME_REGEX to "*foo") - val config = TestConfig(configValues) - assertThatExceptionOfType(PatternSyntaxException::class.java).isThrownBy { - EmptyCatchBlock(config).compileAndLint(regexTestingCode) - } + @Test + fun `doesFailWithInvalidRegex`() { + val configValues = mapOf(ALLOWED_EXCEPTION_NAME_REGEX to "*foo") + val config = TestConfig(configValues) + assertThatExceptionOfType(PatternSyntaxException::class.java).isThrownBy { + EmptyCatchBlock(config).compileAndLint(regexTestingCode) } } } diff --git a/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyDefaultConstructorSpec.kt b/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyDefaultConstructorSpec.kt index 1d76cea43db..353e3df55cd 100644 --- a/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyDefaultConstructorSpec.kt +++ b/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyDefaultConstructorSpec.kt @@ -4,103 +4,98 @@ import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.test.compileAndLint import io.gitlab.arturbosch.detekt.test.lint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test internal class EmptyDefaultConstructorSpec { - @Nested - inner class `EmptyDefaultConstructor rule` { - - @Test - fun `EmptyConstructor`() { - val code = """ - class EmptyConstructor() - """ - assertThat(EmptyDefaultConstructor(Config.empty).compileAndLint(code)).hasSize(1) - } + @Test + fun `EmptyConstructor`() { + val code = """ + class EmptyConstructor() + """ + assertThat(EmptyDefaultConstructor(Config.empty).compileAndLint(code)).hasSize(1) + } - @Test - fun `EmptyPrimaryConstructor`() { - val code = """ - class EmptyPrimaryConstructor constructor() - """ - assertThat(EmptyDefaultConstructor(Config.empty).compileAndLint(code)).hasSize(1) - } + @Test + fun `EmptyPrimaryConstructor`() { + val code = """ + class EmptyPrimaryConstructor constructor() + """ + assertThat(EmptyDefaultConstructor(Config.empty).compileAndLint(code)).hasSize(1) + } - @Test - fun `EmptyPublicPrimaryConstructor`() { - val code = """ - class EmptyPublicPrimaryConstructor public constructor() - """ - assertThat(EmptyDefaultConstructor(Config.empty).compileAndLint(code)).hasSize(1) - } + @Test + fun `EmptyPublicPrimaryConstructor`() { + val code = """ + class EmptyPublicPrimaryConstructor public constructor() + """ + assertThat(EmptyDefaultConstructor(Config.empty).compileAndLint(code)).hasSize(1) + } - @Test - fun `PrimaryConstructorWithParameter`() { - val code = """ - class PrimaryConstructorWithParameter constructor(x: Int) - """ - assertThat(EmptyDefaultConstructor(Config.empty).compileAndLint(code)).isEmpty() - } + @Test + fun `PrimaryConstructorWithParameter`() { + val code = """ + class PrimaryConstructorWithParameter constructor(x: Int) + """ + assertThat(EmptyDefaultConstructor(Config.empty).compileAndLint(code)).isEmpty() + } - @Test - fun `PrimaryConstructorWithAnnotation`() { - val code = """ - class PrimaryConstructorWithAnnotation @SafeVarargs constructor() - """ - assertThat(EmptyDefaultConstructor(Config.empty).compileAndLint(code)).isEmpty() - } + @Test + fun `PrimaryConstructorWithAnnotation`() { + val code = """ + class PrimaryConstructorWithAnnotation @SafeVarargs constructor() + """ + assertThat(EmptyDefaultConstructor(Config.empty).compileAndLint(code)).isEmpty() + } - @Test - fun `PrivatePrimaryConstructor`() { - val code = """ - class PrivatePrimaryConstructor private constructor() - """ - assertThat(EmptyDefaultConstructor(Config.empty).compileAndLint(code)).isEmpty() - } + @Test + fun `PrivatePrimaryConstructor`() { + val code = """ + class PrivatePrimaryConstructor private constructor() + """ + assertThat(EmptyDefaultConstructor(Config.empty).compileAndLint(code)).isEmpty() + } - @Test - fun `EmptyConstructorIsCalled`() { - val code = """ - class EmptyConstructorIsCalled() { + @Test + fun `EmptyConstructorIsCalled`() { + val code = """ + class EmptyConstructorIsCalled() { - constructor(i: Int) : this() - } - """ - assertThat(EmptyDefaultConstructor(Config.empty).compileAndLint(code)).isEmpty() - } + constructor(i: Int) : this() + } + """ + assertThat(EmptyDefaultConstructor(Config.empty).compileAndLint(code)).isEmpty() + } - @Test - fun `should not report empty constructors for classes with expect keyword - #1362`() { - val code = """ - expect class NeedsConstructor() - """ - assertThat(EmptyDefaultConstructor(Config.empty).lint(code)).isEmpty() - } + @Test + fun `should not report empty constructors for classes with expect keyword - #1362`() { + val code = """ + expect class NeedsConstructor() + """ + assertThat(EmptyDefaultConstructor(Config.empty).lint(code)).isEmpty() + } - @Test - fun `should not report empty constructors for classes with actual - #1362`() { - val code = """ - actual class NeedsConstructor actual constructor() - """ - assertThat(EmptyDefaultConstructor(Config.empty).lint(code)).isEmpty() - } + @Test + fun `should not report empty constructors for classes with actual - #1362`() { + val code = """ + actual class NeedsConstructor actual constructor() + """ + assertThat(EmptyDefaultConstructor(Config.empty).lint(code)).isEmpty() + } - @Test - fun `should not report empty constructors for annotation classes with expect keyword - #1362`() { - val code = """ - expect annotation class NeedsConstructor() - """ - assertThat(EmptyDefaultConstructor(Config.empty).lint(code)).isEmpty() - } + @Test + fun `should not report empty constructors for annotation classes with expect keyword - #1362`() { + val code = """ + expect annotation class NeedsConstructor() + """ + assertThat(EmptyDefaultConstructor(Config.empty).lint(code)).isEmpty() + } - @Test - fun `should not report empty constructors for annotation classes with actual - #1362`() { - val code = """ - actual annotation class NeedsConstructor actual constructor() - """ - assertThat(EmptyDefaultConstructor(Config.empty).lint(code)).isEmpty() - } + @Test + fun `should not report empty constructors for annotation classes with actual - #1362`() { + val code = """ + actual annotation class NeedsConstructor actual constructor() + """ + assertThat(EmptyDefaultConstructor(Config.empty).lint(code)).isEmpty() } } diff --git a/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyElseBlockSpec.kt b/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyElseBlockSpec.kt index ee2549c5919..cd201e1926e 100644 --- a/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyElseBlockSpec.kt +++ b/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyElseBlockSpec.kt @@ -3,112 +3,108 @@ package io.gitlab.arturbosch.detekt.rules.empty import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class EmptyElseBlockSpec { private val subject = EmptyElseBlock(Config.empty) - @Nested - inner class `EmptyElseBlock rule` { - @Test - fun `reports empty else block`() { - val code = """ - fun f() { - val i = 0 - if (i == 0) { - println(i) - } else { - - } + @Test + fun `reports empty else block`() { + val code = """ + fun f() { + val i = 0 + if (i == 0) { + println(i) + } else { + } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports empty else blocks with trailing semicolon`() { - val code = """ - fun f() { - val i = 0 - if (i == 0) { - println(i) - } else ; - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports empty else blocks with trailing semicolon`() { + val code = """ + fun f() { + val i = 0 + if (i == 0) { + println(i) + } else ; + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports empty else with trailing semicolon on new line`() { - val code = """ - fun f() { - var i = 0 - if (i == 0) { - println(i) - } else - ; - i++ - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports empty else with trailing semicolon on new line`() { + val code = """ + fun f() { + var i = 0 + if (i == 0) { + println(i) + } else + ; + i++ + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports empty else with trailing semicolon and braces`() { - val code = """ - fun f() { - var i = 0 - if (i == 0) { - println() - } else; { - } - i++ + @Test + fun `reports empty else with trailing semicolon and braces`() { + val code = """ + fun f() { + var i = 0 + if (i == 0) { + println() + } else; { } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + i++ + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report nonempty else with braces`() { - val code = """ - fun f() { - var i = 0 - if (i == 0) { - println(i) - } else { - i++ - } + @Test + fun `does not report nonempty else with braces`() { + val code = """ + fun f() { + var i = 0 + if (i == 0) { + println(i) + } else { + i++ } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report nonempty else without braces`() { - val code = """ - fun f() { - var i = 0 - if (i == 0) { - println(i) - } else i++ - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report nonempty else without braces`() { + val code = """ + fun f() { + var i = 0 + if (i == 0) { + println(i) + } else i++ + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report nonempty else without braces but semicolon`() { - val code = """ - fun f() { - var i = 0 - if (i == 0) { - println(i) - } else i++; - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report nonempty else without braces but semicolon`() { + val code = """ + fun f() { + var i = 0 + if (i == 0) { + println(i) + } else i++; + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyFunctionBlockSpec.kt b/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyFunctionBlockSpec.kt index 77a55cb557e..1c1ad463f84 100644 --- a/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyFunctionBlockSpec.kt +++ b/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyFunctionBlockSpec.kt @@ -14,118 +14,114 @@ class EmptyFunctionBlockSpec { private val subject = EmptyFunctionBlock(Config.empty) - @Nested - inner class `EmptyFunctionBlock rule` { - - @Test - fun `should flag function with protected modifier`() { - val code = """ - class A { - protected fun stuff() {} - } - """ - assertThat(subject.compileAndLint(code)).hasSourceLocation(2, 27) - } + @Test + fun `should flag function with protected modifier`() { + val code = """ + class A { + protected fun stuff() {} + } + """ + assertThat(subject.compileAndLint(code)).hasSourceLocation(2, 27) + } - @Test - fun `should not flag function with open modifier`() { - val code = """ - open class A { - open fun stuff() {} - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `should not flag function with open modifier`() { + val code = """ + open class A { + open fun stuff() {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `should not flag a default function in an interface`() { - val code = """ - interface I { - fun stuff() {} - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `should not flag a default function in an interface`() { + val code = """ + interface I { + fun stuff() {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `should flag the nested empty function`() { - val code = """ - fun a() { - fun b() {} - } - """ - assertThat(subject.compileAndLint(code)).hasSourceLocation(2, 13) - } + @Test + fun `should flag the nested empty function`() { + val code = """ + fun a() { + fun b() {} + } + """ + assertThat(subject.compileAndLint(code)).hasSourceLocation(2, 13) + } - @Nested - inner class `some overridden functions` { + @Nested + inner class `some overridden functions` { - val code = """ - fun empty() {} + val code = """ + fun empty() {} - open class Base { - open fun stuff() {} - } + open class Base { + open fun stuff() {} + } - class A : Base() { - override fun stuff() {} - } + class A : Base() { + override fun stuff() {} + } - class B : Base() { - override fun stuff() { - TODO("Implement this") - } + class B : Base() { + override fun stuff() { + TODO("Implement this") } + } - class C : Base() { - override fun stuff() { - // this is necessary... - } + class C : Base() { + override fun stuff() { + // this is necessary... } - """ - - @Test - fun `should flag empty block in overridden function`() { - assertThat(subject.compileAndLint(code)).hasSize(2) } + """ - @Test - fun `should not flag overridden functions`() { - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN_FUNCTIONS to "true")) - assertThat(EmptyFunctionBlock(config).compileAndLint(code)).hasSourceLocation(1, 13) - } + @Test + fun `should flag empty block in overridden function`() { + assertThat(subject.compileAndLint(code)).hasSize(2) } - @Nested - inner class `some overridden functions when implementing interfaces` { - val code = """ - private interface Listener { - fun listenThis() - - fun listenThat() - } + @Test + fun `should not flag overridden functions`() { + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN_FUNCTIONS to "true")) + assertThat(EmptyFunctionBlock(config).compileAndLint(code)).hasSourceLocation(1, 13) + } + } - private class AnimationEndListener : Listener { - override fun listenThis() { - // no-op - } + @Nested + inner class `some overridden functions when implementing interfaces` { + val code = """ + private interface Listener { + fun listenThis() - override fun listenThat() { + fun listenThat() + } - } + private class AnimationEndListener : Listener { + override fun listenThis() { + // no-op } - """ - @Test - fun `should not flag overridden functions with commented body`() { - assertThat(subject.compileAndLint(code)).hasSourceLocation(12, 31) - } + override fun listenThat() { - @Test - fun `should not flag overridden functions with ignoreOverridden`() { - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to "true")) - assertThat(EmptyFunctionBlock(config).compileAndLint(code)).isEmpty() + } } + """ + + @Test + fun `should not flag overridden functions with commented body`() { + assertThat(subject.compileAndLint(code)).hasSourceLocation(12, 31) + } + + @Test + fun `should not flag overridden functions with ignoreOverridden`() { + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to "true")) + assertThat(EmptyFunctionBlock(config).compileAndLint(code)).isEmpty() } } } diff --git a/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyIfBlockSpec.kt b/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyIfBlockSpec.kt index 368087dcd23..6e482dd0d93 100644 --- a/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyIfBlockSpec.kt +++ b/detekt-rules-empty/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/empty/EmptyIfBlockSpec.kt @@ -3,112 +3,107 @@ package io.gitlab.arturbosch.detekt.rules.empty import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class EmptyIfBlockSpec { private val subject = EmptyIfBlock(Config.empty) - @Nested - inner class `EmptyIfBlock rule` { + @Test + fun `reports empty if with trailing semicolon`() { + val code = """ + fun f() { + var i = 0 + if (i == 0); + i++ + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports empty if with trailing semicolon`() { - val code = """ - fun f() { - var i = 0 - if (i == 0); - i++ - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports empty if with trailing semicolon on new line`() { + val code = """ + fun f() { + var i = 0 + if (i == 0) + ; + i++ + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports empty if with trailing semicolon on new line`() { - val code = """ - fun f() { - var i = 0 - if (i == 0) - ; - i++ + @Test + fun `reports empty if with trailing semicolon and braces`() { + val code = """ + fun f() { + var i = 0 + if (i == 0); { } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + i++ + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports empty if with trailing semicolon and braces`() { - val code = """ - fun f() { - var i = 0 - if (i == 0); { - } + @Test + fun `does not report nonempty if with braces`() { + val code = """ + fun f() { + var i = 0 + if (i == 0) { i++ } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `does not report nonempty if with braces`() { - val code = """ - fun f() { - var i = 0 - if (i == 0) { - i++ - } - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report nonempty if without braces`() { - val code = """ - fun f() { - var i = 0 - if (i == 0) i++ - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report nonempty if without braces`() { + val code = """ + fun f() { + var i = 0 + if (i == 0) i++ + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report nonempty if without braces but semicolon`() { - val code = """ - fun f() { - var i = 0 - if (i == 0) i++; - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report nonempty if without braces but semicolon`() { + val code = """ + fun f() { + var i = 0 + if (i == 0) i++; + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report empty if but nonempty else`() { - val code = """ - fun f() { - var i = 0 - if (i == 0) ; - else i++ - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report empty if but nonempty else`() { + val code = """ + fun f() { + var i = 0 + if (i == 0) ; + else i++ + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report empty if and else-if but nonempty else`() { - val code = """ - fun f() { - var i = 0 - if (i == 0) ; - else if (i == 1) ; - else i++ - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report empty if and else-if but nonempty else`() { + val code = """ + fun f() { + var i = 0 + if (i == 0) ; + else if (i == 1) ; + else i++ + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/CastToNullableTypeSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/CastToNullableTypeSpec.kt index 276cf28ffdb..5c78098ce18 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/CastToNullableTypeSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/CastToNullableTypeSpec.kt @@ -2,47 +2,43 @@ package io.gitlab.arturbosch.detekt.rules.bugs import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class CastToNullableTypeSpec { private val subject = CastToNullableType() - @Nested - inner class `CastToNullableTypeSpec rule` { - @Test - fun `casting to nullable types`() { - val code = """ - fun foo(a: Any?) { - val x: String? = a as String? - } - """ - val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(1) - assertThat(findings).hasSourceLocation(2, 22) - assertThat(findings[0]).hasMessage("Use the safe cast ('as? String') instead of 'as String?'.") - } + @Test + fun `casting to nullable types`() { + val code = """ + fun foo(a: Any?) { + val x: String? = a as String? + } + """ + val findings = subject.compileAndLint(code) + assertThat(findings).hasSize(1) + assertThat(findings).hasSourceLocation(2, 22) + assertThat(findings[0]).hasMessage("Use the safe cast ('as? String') instead of 'as String?'.") + } - @Test - fun `safe casting`() { - val code = """ - fun foo(a: Any?) { - val x: String? = a as? String - } - """ - val findings = subject.compileAndLint(code) - assertThat(findings).isEmpty() - } + @Test + fun `safe casting`() { + val code = """ + fun foo(a: Any?) { + val x: String? = a as? String + } + """ + val findings = subject.compileAndLint(code) + assertThat(findings).isEmpty() + } - @Test - fun `type checking`() { - val code = """ - fun foo(a: Any?) { - val x = a is String? - } - """ - val findings = subject.compileAndLint(code) - assertThat(findings).isEmpty() - } + @Test + fun `type checking`() { + val code = """ + fun foo(a: Any?) { + val x = a is String? + } + """ + val findings = subject.compileAndLint(code) + assertThat(findings).isEmpty() } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DeprecationSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DeprecationSpec.kt index f7727835b91..c1ac16e9dc0 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DeprecationSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DeprecationSpec.kt @@ -5,52 +5,47 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class DeprecationSpec(private val env: KotlinCoreEnvironment) { private val subject = Deprecation(Config.empty) - @Nested - inner class `Deprecation detection` { + @Test + fun `reports when supertype is deprecated`() { + val code = """ + @Deprecated("deprecation message") + abstract class Foo { + abstract fun bar() : Int - @Test - fun `reports when supertype is deprecated`() { - val code = """ - @Deprecated("deprecation message") - abstract class Foo { - abstract fun bar() : Int - - fun baz() { - } + fun baz() { } + } - abstract class Oof : Foo() { - fun spam() { - } + abstract class Oof : Foo() { + fun spam() { } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings.first().message).isEqualTo("Foo is deprecated.") - } + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings.first().message).isEqualTo("Foo is deprecated.") + } - @Test - fun `does not report when supertype is not deprecated`() { - val code = """ - abstract class Oof : Foo() { - fun spam() { - } + @Test + fun `does not report when supertype is not deprecated`() { + val code = """ + abstract class Oof : Foo() { + fun spam() { } - abstract class Foo { - abstract fun bar() : Int + } + abstract class Foo { + abstract fun bar() : Int - fun baz() { - } + fun baz() { } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DontDowncastCollectionTypesSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DontDowncastCollectionTypesSpec.kt index b45c9a4f9c9..e626491f70c 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DontDowncastCollectionTypesSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DontDowncastCollectionTypesSpec.kt @@ -14,441 +14,437 @@ class DontDowncastCollectionTypesSpec(private val env: KotlinCoreEnvironment) { private val subject = DontDowncastCollectionTypes(Config.empty) @Nested - inner class `DontDowncastCollectionTypes rule` { - - @Nested - inner class `valid cases` { - @Test - fun `detects List type casts`() { - val code = """ - fun main() { - val myList = listOf(1,2,3) - val mutList = myList as MutableList - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type List to MutableList is risky. Use `toMutableList()` instead." - ) + inner class `valid cases` { + @Test + fun `detects List type casts`() { + val code = """ + fun main() { + val myList = listOf(1,2,3) + val mutList = myList as MutableList } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type List to MutableList is risky. Use `toMutableList()` instead." + ) + } - @Test - fun `detects List type safe casts`() { - val code = """ - fun main() { - val myList : List? = null - val mutList = myList as? MutableList - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type List to MutableList is risky. Use `toMutableList()` instead." - ) + @Test + fun `detects List type safe casts`() { + val code = """ + fun main() { + val myList : List? = null + val mutList = myList as? MutableList } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type List to MutableList is risky. Use `toMutableList()` instead." + ) + } - @Test - fun `detects List type checks`() { - val code = """ - fun main() { - val myList = listOf(1,2,3) - if (myList is MutableList) { - myList.add(4) - } + @Test + fun `detects List type checks`() { + val code = """ + fun main() { + val myList = listOf(1,2,3) + if (myList is MutableList) { + myList.add(4) } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type List to MutableList is risky. Use `toMutableList()` instead." - ) } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type List to MutableList is risky. Use `toMutableList()` instead." + ) + } - @Test - fun `detects Set type casts`() { - val code = """ - fun main() { - val mySet = setOf(1,2,3) - val mutSet = mySet as MutableSet - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Set to MutableSet is risky. Use `toMutableSet()` instead." - ) + @Test + fun `detects Set type casts`() { + val code = """ + fun main() { + val mySet = setOf(1,2,3) + val mutSet = mySet as MutableSet } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Set to MutableSet is risky. Use `toMutableSet()` instead." + ) + } - @Test - fun `detects Set type safe casts`() { - val code = """ - fun main() { - val mySet : Set? = null - val mutSet = mySet as? MutableSet - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Set to MutableSet is risky. Use `toMutableSet()` instead." - ) + @Test + fun `detects Set type safe casts`() { + val code = """ + fun main() { + val mySet : Set? = null + val mutSet = mySet as? MutableSet } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Set to MutableSet is risky. Use `toMutableSet()` instead." + ) + } - @Test - fun `detects Set type checks`() { - val code = """ - fun main() { - val mySet = setOf(1,2,3) - if (mySet is MutableSet) { - mySet.add(4) - } + @Test + fun `detects Set type checks`() { + val code = """ + fun main() { + val mySet = setOf(1,2,3) + if (mySet is MutableSet) { + mySet.add(4) } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Set to MutableSet is risky. Use `toMutableSet()` instead." - ) } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Set to MutableSet is risky. Use `toMutableSet()` instead." + ) + } - @Test - fun `detects Map type casts`() { - val code = """ - fun main() { - val myMap = mapOf(1 to 2) - val mutMap = myMap as MutableMap - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Map to MutableMap is risky. Use `toMutableMap()` instead." - ) + @Test + fun `detects Map type casts`() { + val code = """ + fun main() { + val myMap = mapOf(1 to 2) + val mutMap = myMap as MutableMap } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Map to MutableMap is risky. Use `toMutableMap()` instead." + ) + } - @Test - fun `detects Map type safe casts`() { - val code = """ - fun main() { - val myMap : Map? = null - val mutMap = myMap as? MutableMap - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Map to MutableMap is risky. Use `toMutableMap()` instead." - ) + @Test + fun `detects Map type safe casts`() { + val code = """ + fun main() { + val myMap : Map? = null + val mutMap = myMap as? MutableMap } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Map to MutableMap is risky. Use `toMutableMap()` instead." + ) + } - @Test - fun `detects Map type checks`() { - val code = """ - fun main() { - val myMap = mapOf(1 to 2) - if (myMap is MutableMap) { - myMap[3] = 4 - } + @Test + fun `detects Map type checks`() { + val code = """ + fun main() { + val myMap = mapOf(1 to 2) + if (myMap is MutableMap) { + myMap[3] = 4 } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Map to MutableMap is risky. Use `toMutableMap()` instead." - ) } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Map to MutableMap is risky. Use `toMutableMap()` instead." + ) } + } - @Nested - inner class `ignores valid casts` { - - @Test - fun `ignores MutableList casts`() { - val code = """ - fun main() { - val myList = mutableListOf(1,2,3) - val mutList = myList as MutableList - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() + @Nested + inner class `ignores valid casts` { + + @Test + fun `ignores MutableList casts`() { + val code = """ + fun main() { + val myList = mutableListOf(1,2,3) + val mutList = myList as MutableList } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } - @Test - fun `ignores MutableSet casts`() { - val code = """ - fun main() { - val mySet = mutableSetOf(1,2,3) - val mutSet = mySet as MutableSet - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() + @Test + fun `ignores MutableSet casts`() { + val code = """ + fun main() { + val mySet = mutableSetOf(1,2,3) + val mutSet = mySet as MutableSet } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } - @Test - fun `ignores Map type casts`() { - val code = """ - fun main() { - val myMap = mutableMapOf(1 to 2) - val mutMap = myMap as MutableMap - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() + @Test + fun `ignores Map type casts`() { + val code = """ + fun main() { + val myMap = mutableMapOf(1 to 2) + val mutMap = myMap as MutableMap } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } - @Test - fun `ignores Synthetic types`() { - val code = """ - import kotlinx.android.synthetic.main.tooltip_progress_bar.view.* - fun main() { - val params = tooltip_guide.layoutParams as LayoutParams - } - """ - val result = subject.lintWithContext(env, code) - assertThat(result).isEmpty() + @Test + fun `ignores Synthetic types`() { + val code = """ + import kotlinx.android.synthetic.main.tooltip_progress_bar.view.* + fun main() { + val params = tooltip_guide.layoutParams as LayoutParams } + """ + val result = subject.lintWithContext(env, code) + assertThat(result).isEmpty() } + } - @Nested - inner class `type-aliases` { - - @Test - fun `detects ArrayList type casts`() { - val code = """ - fun main() { - val myList = listOf(1,2,3) - val mutList = myList as ArrayList - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type List to ArrayList is risky." - ) + @Nested + inner class `type-aliases` { + + @Test + fun `detects ArrayList type casts`() { + val code = """ + fun main() { + val myList = listOf(1,2,3) + val mutList = myList as ArrayList } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type List to ArrayList is risky." + ) + } - @Test - fun `detects ArrayList type safe casts`() { - val code = """ - fun main() { - val myList : List? = null - val mutList = myList as? ArrayList - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type List to ArrayList is risky." - ) + @Test + fun `detects ArrayList type safe casts`() { + val code = """ + fun main() { + val myList : List? = null + val mutList = myList as? ArrayList } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type List to ArrayList is risky." + ) + } - @Test - fun `detects ArrayList type checks`() { - val code = """ - fun main() { - val myList = listOf(1,2,3) - if (myList is ArrayList) { - myList.add(4) - } + @Test + fun `detects ArrayList type checks`() { + val code = """ + fun main() { + val myList = listOf(1,2,3) + if (myList is ArrayList) { + myList.add(4) } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type List to ArrayList is risky." - ) } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type List to ArrayList is risky." + ) + } - @Test - fun `detects LinkedHashSet type casts`() { - val code = """ - fun main() { - val mySet = setOf(1,2,3) - val mutSet = mySet as LinkedHashSet - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Set to LinkedHashSet is risky." - ) + @Test + fun `detects LinkedHashSet type casts`() { + val code = """ + fun main() { + val mySet = setOf(1,2,3) + val mutSet = mySet as LinkedHashSet } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Set to LinkedHashSet is risky." + ) + } - @Test - fun `detects LinkedHashSet type safe casts`() { - val code = """ - fun main() { - val mySet : Set? = null - val mutSet = mySet as? LinkedHashSet - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Set to LinkedHashSet is risky." - ) + @Test + fun `detects LinkedHashSet type safe casts`() { + val code = """ + fun main() { + val mySet : Set? = null + val mutSet = mySet as? LinkedHashSet } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Set to LinkedHashSet is risky." + ) + } - @Test - fun `detects LinkedHashSet type checks`() { - val code = """ - fun main() { - val mySet = setOf(1,2,3) - if (mySet is LinkedHashSet) { - mySet.add(4) - } + @Test + fun `detects LinkedHashSet type checks`() { + val code = """ + fun main() { + val mySet = setOf(1,2,3) + if (mySet is LinkedHashSet) { + mySet.add(4) } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Set to LinkedHashSet is risky." - ) } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Set to LinkedHashSet is risky." + ) + } - @Test - fun `detects HashSet type casts`() { - val code = """ - fun main() { - val mySet = setOf(1,2,3) - val mutSet = mySet as HashSet - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Set to HashSet is risky." - ) + @Test + fun `detects HashSet type casts`() { + val code = """ + fun main() { + val mySet = setOf(1,2,3) + val mutSet = mySet as HashSet } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Set to HashSet is risky." + ) + } - @Test - fun `detects HashSet type safe casts`() { - val code = """ - fun main() { - val mySet : Set? = null - val mutSet = mySet as? HashSet - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Set to HashSet is risky." - ) + @Test + fun `detects HashSet type safe casts`() { + val code = """ + fun main() { + val mySet : Set? = null + val mutSet = mySet as? HashSet } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Set to HashSet is risky." + ) + } - @Test - fun `detects HashSet type checks`() { - val code = """ - fun main() { - val mySet = setOf(1,2,3) - if (mySet is HashSet) { - mySet.add(4) - } + @Test + fun `detects HashSet type checks`() { + val code = """ + fun main() { + val mySet = setOf(1,2,3) + if (mySet is HashSet) { + mySet.add(4) } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Set to HashSet is risky." - ) } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Set to HashSet is risky." + ) + } - @Test - fun `detects HashMap type casts`() { - val code = """ - fun main() { - val myMap = mapOf(1 to 2) - val mutMap = myMap as HashMap - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Map to HashMap is risky." - ) + @Test + fun `detects HashMap type casts`() { + val code = """ + fun main() { + val myMap = mapOf(1 to 2) + val mutMap = myMap as HashMap } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Map to HashMap is risky." + ) + } - @Test - fun `detects HashMap type safe casts`() { - val code = """ - fun main() { - val myMap : Map? = null - val mutMap = myMap as? HashMap - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Map to HashMap is risky." - ) + @Test + fun `detects HashMap type safe casts`() { + val code = """ + fun main() { + val myMap : Map? = null + val mutMap = myMap as? HashMap } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Map to HashMap is risky." + ) + } - @Test - fun `detects HashMap type checks`() { - val code = """ - fun main() { - val myMap = mapOf(1 to 2) - if (myMap is HashMap) { - myMap[3] = 4 - } + @Test + fun `detects HashMap type checks`() { + val code = """ + fun main() { + val myMap = mapOf(1 to 2) + if (myMap is HashMap) { + myMap[3] = 4 } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Map to HashMap is risky." - ) } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Map to HashMap is risky." + ) + } - @Test - fun `detects LinkedHashMap type casts`() { - val code = """ - fun main() { - val myMap = mapOf(1 to 2) - val mutMap = myMap as LinkedHashMap - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Map to LinkedHashMap is risky." - ) + @Test + fun `detects LinkedHashMap type casts`() { + val code = """ + fun main() { + val myMap = mapOf(1 to 2) + val mutMap = myMap as LinkedHashMap } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Map to LinkedHashMap is risky." + ) + } - @Test - fun `detects LinkedHashMap type safe casts`() { - val code = """ - fun main() { - val myMap : Map? = null - val mutMap = myMap as? LinkedHashMap - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Map to LinkedHashMap is risky." - ) + @Test + fun `detects LinkedHashMap type safe casts`() { + val code = """ + fun main() { + val myMap : Map? = null + val mutMap = myMap as? LinkedHashMap } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Map to LinkedHashMap is risky." + ) + } - @Test - fun `detects LinkedHashMap type checks`() { - val code = """ - fun main() { - val myMap = mapOf(1 to 2) - if (myMap is LinkedHashMap) { - myMap[3] = 4 - } + @Test + fun `detects LinkedHashMap type checks`() { + val code = """ + fun main() { + val myMap = mapOf(1 to 2) + if (myMap is LinkedHashMap) { + myMap[3] = 4 } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo( - "Down-casting from type Map to LinkedHashMap is risky." - ) } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo( + "Down-casting from type Map to LinkedHashMap is risky." + ) } } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DoubleMutabilityForCollectionSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DoubleMutabilityForCollectionSpec.kt index 00f5aa90cc0..40dace89da9 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DoubleMutabilityForCollectionSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DoubleMutabilityForCollectionSpec.kt @@ -16,946 +16,942 @@ class DoubleMutabilityForCollectionSpec(private val env: KotlinCoreEnvironment) private val subject = DoubleMutabilityForCollection(Config.empty) @Nested - inner class `DoubleMutabilityForCollection rule` { + inner class `local variables` { @Nested - inner class `local variables` { - - @Nested - inner class `valid cases` { - - @Test - fun `detects var declaration with mutable list`() { - val code = """ - fun main() { - var myList = mutableListOf(1,2,3) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(2, 5) - } - - @Test - fun `detects var declaration with mutable set`() { - val code = """ - fun main() { - var mySet = mutableSetOf(1,2,3) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(2, 5) - } - - @Test - fun `detects var declaration with mutable map`() { - val code = """ - fun main() { - var myMap = mutableMapOf("answer" to 42) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(2, 5) - } - - @Test - fun `detects var declaration with ArrayList`() { - val code = """ - fun main() { - var myArrayList = ArrayList() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(2, 5) - } - - @Test - fun `detects var declaration with LinkedHashSet`() { - val code = """ - fun main() { - var myLinkedHashSet = LinkedHashSet() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(2, 5) - } - - @Test - fun `detects var declaration with HashSet`() { - val code = """ - fun main() { - var myHashSet = HashSet() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(2, 5) - } - - @Test - fun `detects var declaration with LinkedHashMap`() { - val code = """ - fun main() { - var myLinkedHashMap = LinkedHashMap() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(2, 5) - } - - @Test - fun `detects var declaration with HashMap`() { - val code = """ - fun main() { - var myHashMap = HashMap() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(2, 5) - } - - @Test - fun `detects var declaration with MutableState, when configured`() { - val rule = DoubleMutabilityForCollection( - TestConfig( - mapOf( - MUTABLE_TYPES to listOf("MutableState") - ) - ) - ) - - val code = """ - data class MutableState(var state: T) - fun main() { - var myState = MutableState("foo") - } - """ - val result = rule.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(3, 5) - } - - @Test - fun `detects var declaration with MutableState via factory function, when configured`() { - val rule = DoubleMutabilityForCollection( - TestConfig( - mapOf( - MUTABLE_TYPES to listOf("MutableState") - ) - ) - ) - - val code = """ - data class MutableState(var state: T) - fun mutableStateOf(value: T): MutableState = MutableState(value) - fun main() { - var myState = mutableStateOf("foo") - } - """ - val result = rule.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(4, 5) - } - - @Test - fun `detects var declaration with MutableState via calculation lambda, when configured`() { - val rule = DoubleMutabilityForCollection( - TestConfig( - mapOf( - MUTABLE_TYPES to listOf("MutableState") - ) - ) - ) - - val code = """ - data class MutableState(var state: T) - fun mutableStateOf(value: T): MutableState = MutableState(value) - fun remember(calculation: () -> T): T = calculation() - fun main() { - var myState = remember { mutableStateOf("foo") } - } - """ - val result = rule.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(5, 5) - } - } - - @Nested - inner class `ignores declaration with val` { - - @Test - fun `does not detect val declaration with mutable list`() { - val code = """ - fun main() { - val myList = mutableListOf(1,2,3) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect val declaration with mutable set`() { - val code = """ - fun main() { - val mySet = mutableSetOf(1,2,3) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect val declaration with mutable map`() { - val code = """ - fun main() { - val myMap = mutableMapOf("answer" to 42) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect val declaration with ArrayList`() { - val code = """ - fun main() { - val myArrayList = ArrayList() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect val declaration with LinkedHashSet`() { - val code = """ - fun main() { - val myLinkedHashSet = LinkedHashSet() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect val declaration with HashSet`() { - val code = """ - fun main() { - val myHashSet = HashSet() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect val declaration with LinkedHashMap`() { - val code = """ - fun main() { - val myLinkedHashMap = LinkedHashMap() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect val declaration with HashMap`() { - val code = """ - fun main() { - val myHashMap = HashMap() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - } - - @Nested - inner class `ignores declaration with var and immutable types` { - - @Test - fun `does not detect var declaration with immutable list`() { - val code = """ - fun main() { - val myList = listOf(1,2,3) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect var declaration with immutable set`() { - val code = """ - fun main() { - val mySet = setOf(1,2,3) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect var declaration with immutable map`() { - val code = """ - fun main() { - val myMap = mapOf("answer" to 42) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - } - - @Nested - inner class `ignores declaration with var and property delegation` { - - @Test - fun `does not detect var declaration with property delegate`() { - val rule = DoubleMutabilityForCollection( - TestConfig( - mapOf( - MUTABLE_TYPES to listOf("MutableState") - ) - ) - ) + inner class `valid cases` { - val code = """ - data class MutableState(var state: T) - fun mutableStateOf(value: T): MutableState = MutableState(value) - fun remember(calculation: () -> T): T = calculation() - inline operator fun MutableState.getValue(thisObj: Any?, property: kotlin.reflect.KProperty<*>): T = state - inline operator fun MutableState.setValue(thisObj: Any?, property: kotlin.reflect.KProperty<*>, value: T) { - this.state = value - } - fun main() { - var myState by remember { mutableStateOf("foo") } - } - """ - val result = rule.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - } - } - - @Nested - inner class `top level variables` { - - @Nested - inner class `valid cases` { - - @Test - fun `detects var declaration with mutable list`() { - val code = """ + @Test + fun `detects var declaration with mutable list`() { + val code = """ + fun main() { var myList = mutableListOf(1,2,3) - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(1, 1) } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(2, 5) + } - @Test - fun `detects var declaration with mutable set`() { - val code = """ + @Test + fun `detects var declaration with mutable set`() { + val code = """ + fun main() { var mySet = mutableSetOf(1,2,3) - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(1, 1) } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(2, 5) + } - @Test - fun `detects var declaration with mutable map`() { - val code = """ + @Test + fun `detects var declaration with mutable map`() { + val code = """ + fun main() { var myMap = mutableMapOf("answer" to 42) - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(1, 1) } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(2, 5) + } - @Test - fun `detects var declaration with ArrayList`() { - val code = """ + @Test + fun `detects var declaration with ArrayList`() { + val code = """ + fun main() { var myArrayList = ArrayList() - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(1, 1) } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(2, 5) + } - @Test - fun `detects var declaration with LinkedHashSet`() { - val code = """ + @Test + fun `detects var declaration with LinkedHashSet`() { + val code = """ + fun main() { var myLinkedHashSet = LinkedHashSet() - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(1, 1) } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(2, 5) + } - @Test - fun `detects var declaration with HashSet`() { - val code = """ + @Test + fun `detects var declaration with HashSet`() { + val code = """ + fun main() { var myHashSet = HashSet() - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(1, 1) } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(2, 5) + } - @Test - fun `detects var declaration with LinkedHashMap`() { - val code = """ + @Test + fun `detects var declaration with LinkedHashMap`() { + val code = """ + fun main() { var myLinkedHashMap = LinkedHashMap() - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(1, 1) } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(2, 5) + } - @Test - fun `detects var declaration with HashMap`() { - val code = """ + @Test + fun `detects var declaration with HashMap`() { + val code = """ + fun main() { var myHashMap = HashMap() - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(1, 1) - } - - @Test - fun `detects var declaration with MutableState, when configured`() { - val rule = DoubleMutabilityForCollection( - TestConfig( - mapOf( - MUTABLE_TYPES to listOf("MutableState") - ) + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(2, 5) + } + + @Test + fun `detects var declaration with MutableState, when configured`() { + val rule = DoubleMutabilityForCollection( + TestConfig( + mapOf( + MUTABLE_TYPES to listOf("MutableState") ) ) + ) - val code = """ - data class MutableState(var state: T) + val code = """ + data class MutableState(var state: T) + fun main() { var myState = MutableState("foo") - """ - val result = rule.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(2, 1) - } - - @Test - fun `detects var declaration with MutableState via factory function, when configured`() { - val rule = DoubleMutabilityForCollection( - TestConfig( - mapOf( - MUTABLE_TYPES to listOf("MutableState") - ) + } + """ + val result = rule.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(3, 5) + } + + @Test + fun `detects var declaration with MutableState via factory function, when configured`() { + val rule = DoubleMutabilityForCollection( + TestConfig( + mapOf( + MUTABLE_TYPES to listOf("MutableState") ) ) + ) - val code = """ - data class MutableState(var state: T) - fun mutableStateOf(value: T): MutableState = MutableState(value) + val code = """ + data class MutableState(var state: T) + fun mutableStateOf(value: T): MutableState = MutableState(value) + fun main() { var myState = mutableStateOf("foo") - """ - val result = rule.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(3, 1) - } - - @Test - fun `detects var declaration with MutableState via calculation lambda, when configured`() { - val rule = DoubleMutabilityForCollection( - TestConfig( - mapOf( - MUTABLE_TYPES to listOf("MutableState") - ) + } + """ + val result = rule.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(4, 5) + } + + @Test + fun `detects var declaration with MutableState via calculation lambda, when configured`() { + val rule = DoubleMutabilityForCollection( + TestConfig( + mapOf( + MUTABLE_TYPES to listOf("MutableState") ) ) + ) - val code = """ - data class MutableState(var state: T) - fun mutableStateOf(value: T): MutableState = MutableState(value) - fun remember(calculation: () -> T): T = calculation() + val code = """ + data class MutableState(var state: T) + fun mutableStateOf(value: T): MutableState = MutableState(value) + fun remember(calculation: () -> T): T = calculation() + fun main() { var myState = remember { mutableStateOf("foo") } - """ - val result = rule.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(4, 1) } + """ + val result = rule.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(5, 5) } + } - @Nested - inner class `ignores declaration with val` { + @Nested + inner class `ignores declaration with val` { - @Test - fun `does not detect val declaration with mutable list`() { - val code = """ + @Test + fun `does not detect val declaration with mutable list`() { + val code = """ + fun main() { val myList = mutableListOf(1,2,3) - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } - @Test - fun `does not detect val declaration with mutable set`() { - val code = """ + @Test + fun `does not detect val declaration with mutable set`() { + val code = """ + fun main() { val mySet = mutableSetOf(1,2,3) - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } - @Test - fun `does not detect val declaration with mutable map`() { - val code = """ + @Test + fun `does not detect val declaration with mutable map`() { + val code = """ + fun main() { val myMap = mutableMapOf("answer" to 42) - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } - @Test - fun `does not detect val declaration with ArrayList`() { - val code = """ + @Test + fun `does not detect val declaration with ArrayList`() { + val code = """ + fun main() { val myArrayList = ArrayList() - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } - @Test - fun `does not detect val declaration with LinkedHashSet`() { - val code = """ + @Test + fun `does not detect val declaration with LinkedHashSet`() { + val code = """ + fun main() { val myLinkedHashSet = LinkedHashSet() - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } - @Test - fun `does not detect val declaration with HashSet`() { - val code = """ + @Test + fun `does not detect val declaration with HashSet`() { + val code = """ + fun main() { val myHashSet = HashSet() - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } - @Test - fun `does not detect val declaration with LinkedHashMap`() { - val code = """ + @Test + fun `does not detect val declaration with LinkedHashMap`() { + val code = """ + fun main() { val myLinkedHashMap = LinkedHashMap() - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } - @Test - fun `does not detect val declaration with HashMap`() { - val code = """ + @Test + fun `does not detect val declaration with HashMap`() { + val code = """ + fun main() { val myHashMap = HashMap() - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() } + } - @Nested - inner class `ignores declaration with var and immutable types` { + @Nested + inner class `ignores declaration with var and immutable types` { - @Test - fun `does not detect var declaration with immutable list`() { - val code = """ + @Test + fun `does not detect var declaration with immutable list`() { + val code = """ + fun main() { val myList = listOf(1,2,3) - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } - @Test - fun `does not detect var declaration with immutable set`() { - val code = """ + @Test + fun `does not detect var declaration with immutable set`() { + val code = """ + fun main() { val mySet = setOf(1,2,3) - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } - @Test - fun `does not detect var declaration with immutable map`() { - val code = """ + @Test + fun `does not detect var declaration with immutable map`() { + val code = """ + fun main() { val myMap = mapOf("answer" to 42) - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() } + } - @Nested - inner class `ignores declaration with var and property delegation` { - - @Test - fun `does not detect var declaration with property delegate`() { - val rule = DoubleMutabilityForCollection( - TestConfig( - mapOf( - MUTABLE_TYPES to listOf("MutableState") - ) + @Nested + inner class `ignores declaration with var and property delegation` { + + @Test + fun `does not detect var declaration with property delegate`() { + val rule = DoubleMutabilityForCollection( + TestConfig( + mapOf( + MUTABLE_TYPES to listOf("MutableState") ) ) + ) - val code = """ - data class MutableState(var state: T) - fun mutableStateOf(value: T): MutableState = MutableState(value) - fun remember(calculation: () -> T): T = calculation() - inline operator fun MutableState.getValue(thisObj: Any?, property: kotlin.reflect.KProperty<*>): T = state - inline operator fun MutableState.setValue(thisObj: Any?, property: kotlin.reflect.KProperty<*>, value: T) { - this.state = value - } + val code = """ + data class MutableState(var state: T) + fun mutableStateOf(value: T): MutableState = MutableState(value) + fun remember(calculation: () -> T): T = calculation() + inline operator fun MutableState.getValue(thisObj: Any?, property: kotlin.reflect.KProperty<*>): T = state + inline operator fun MutableState.setValue(thisObj: Any?, property: kotlin.reflect.KProperty<*>, value: T) { + this.state = value + } + fun main() { var myState by remember { mutableStateOf("foo") } - """ - val result = rule.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() } + """ + val result = rule.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() } } + } + + @Nested + inner class `top level variables` { @Nested - inner class `class properties` { - - @Nested - inner class `valid cases` { - - @Test - fun `detects var declaration with mutable list`() { - val code = """ - class MyClass { - var myOtherList = mutableListOf(1,2,3) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(2, 5) - } - - @Test - fun `detects var declaration with mutable set`() { - val code = """ - class MyClass { - var mySet = mutableSetOf(1,2,3) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(2, 5) - } - - @Test - fun `detects var declaration with mutable map`() { - val code = """ - class MyClass { - var myMap = mutableMapOf("answer" to 42) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(2, 5) - } - - @Test - fun `detects var declaration with ArrayList`() { - val code = """ - class MyClass { - var myArrayList = ArrayList() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(2, 5) - } - - @Test - fun `detects var declaration with LinkedHashSet`() { - val code = """ - class MyClass { - var myLinkedHashSet = LinkedHashSet() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(2, 5) - } - - @Test - fun `detects var declaration with HashSet`() { - val code = """ - class MyClass { - var myHashSet = HashSet() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(2, 5) - } - - @Test - fun `detects var declaration with LinkedHashMap`() { - val code = """ - class MyClass { - var myLinkedHashMap = LinkedHashMap() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(2, 5) - } - - @Test - fun `detects var declaration with HashMap`() { - val code = """ - class MyClass { - var myHashMap = HashMap() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(2, 5) - } - - @Test - fun `detects var declaration with MutableState, when configured`() { - val rule = DoubleMutabilityForCollection( - TestConfig( - mapOf( - MUTABLE_TYPES to listOf("MutableState") - ) + inner class `valid cases` { + + @Test + fun `detects var declaration with mutable list`() { + val code = """ + var myList = mutableListOf(1,2,3) + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(1, 1) + } + + @Test + fun `detects var declaration with mutable set`() { + val code = """ + var mySet = mutableSetOf(1,2,3) + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(1, 1) + } + + @Test + fun `detects var declaration with mutable map`() { + val code = """ + var myMap = mutableMapOf("answer" to 42) + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(1, 1) + } + + @Test + fun `detects var declaration with ArrayList`() { + val code = """ + var myArrayList = ArrayList() + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(1, 1) + } + + @Test + fun `detects var declaration with LinkedHashSet`() { + val code = """ + var myLinkedHashSet = LinkedHashSet() + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(1, 1) + } + + @Test + fun `detects var declaration with HashSet`() { + val code = """ + var myHashSet = HashSet() + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(1, 1) + } + + @Test + fun `detects var declaration with LinkedHashMap`() { + val code = """ + var myLinkedHashMap = LinkedHashMap() + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(1, 1) + } + + @Test + fun `detects var declaration with HashMap`() { + val code = """ + var myHashMap = HashMap() + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(1, 1) + } + + @Test + fun `detects var declaration with MutableState, when configured`() { + val rule = DoubleMutabilityForCollection( + TestConfig( + mapOf( + MUTABLE_TYPES to listOf("MutableState") ) ) + ) + + val code = """ + data class MutableState(var state: T) + var myState = MutableState("foo") + """ + val result = rule.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(2, 1) + } - val code = """ - data class MutableState(var state: T) - class MyClass { - var myState = MutableState("foo") - } - """ - val result = rule.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(3, 5) - } - - @Test - fun `detects var declaration with MutableState via factory function, when configured`() { - val rule = DoubleMutabilityForCollection( - TestConfig( - mapOf( - MUTABLE_TYPES to listOf("MutableState") - ) + @Test + fun `detects var declaration with MutableState via factory function, when configured`() { + val rule = DoubleMutabilityForCollection( + TestConfig( + mapOf( + MUTABLE_TYPES to listOf("MutableState") ) ) + ) + + val code = """ + data class MutableState(var state: T) + fun mutableStateOf(value: T): MutableState = MutableState(value) + var myState = mutableStateOf("foo") + """ + val result = rule.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(3, 1) + } - val code = """ - data class MutableState(var state: T) - fun mutableStateOf(value: T): MutableState = MutableState(value) - class MyClass { - var myState = mutableStateOf("foo") - } - """ - val result = rule.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(4, 5) - } - - @Test - fun `detects var declaration with MutableState via calculation lambda, when configured`() { - val rule = DoubleMutabilityForCollection( - TestConfig( - mapOf( - MUTABLE_TYPES to listOf("MutableState") - ) + @Test + fun `detects var declaration with MutableState via calculation lambda, when configured`() { + val rule = DoubleMutabilityForCollection( + TestConfig( + mapOf( + MUTABLE_TYPES to listOf("MutableState") ) ) + ) + + val code = """ + data class MutableState(var state: T) + fun mutableStateOf(value: T): MutableState = MutableState(value) + fun remember(calculation: () -> T): T = calculation() + var myState = remember { mutableStateOf("foo") } + """ + val result = rule.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(4, 1) + } + } + + @Nested + inner class `ignores declaration with val` { + + @Test + fun `does not detect val declaration with mutable list`() { + val code = """ + val myList = mutableListOf(1,2,3) + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + + @Test + fun `does not detect val declaration with mutable set`() { + val code = """ + val mySet = mutableSetOf(1,2,3) + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + + @Test + fun `does not detect val declaration with mutable map`() { + val code = """ + val myMap = mutableMapOf("answer" to 42) + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } - val code = """ - data class MutableState(var state: T) - fun mutableStateOf(value: T): MutableState = MutableState(value) - fun remember(calculation: () -> T): T = calculation() - class MyClass { - var myState = remember { mutableStateOf("foo") } - } - """ - val result = rule.compileAndLintWithContext(env, code) - assertThat(result).hasSize(1) - assertThat(result).hasSourceLocation(5, 5) - } - } - - @Nested - inner class `ignores declaration with val` { - - @Test - fun `does not detect val declaration with mutable list`() { - val code = """ - class MyClass { - val myList = mutableListOf(1,2,3) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect val declaration with mutable set`() { - val code = """ - class MyClass { - val mySet = mutableSetOf(1,2,3) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect val declaration with mutable map`() { - val code = """ - class MyClass { - val myMap = mutableMapOf("answer" to 42) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect val declaration with ArrayList`() { - val code = """ - class MyClass { - val myArrayList = ArrayList() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect val declaration with LinkedHashSet`() { - val code = """ - class MyClass { - val myLinkedHashSet = LinkedHashSet() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect val declaration with HashSet`() { - val code = """ - class MyClass { - val myHashSet = HashSet() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect val declaration with LinkedHashMap`() { - val code = """ - class MyClass { - val myLinkedHashMap = LinkedHashMap() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect val declaration with HashMap`() { - val code = """ - class MyClass { - val myHashMap = HashMap() - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - } - - @Nested - inner class `ignores declaration with var and immutable types` { - - @Test - fun `does not detect var declaration with immutable list`() { - val code = """ - class MyClass { - val myList = listOf(1,2,3) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect var declaration with immutable set`() { - val code = """ - class MyClass { - val mySet = setOf(1,2,3) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - - @Test - fun `does not detect var declaration with immutable map`() { - val code = """ - class MyClass { - val myMap = mapOf("answer" to 42) - } - """ - val result = subject.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() - } - } - - @Nested - inner class `ignores declaration with var and property delegation` { - - @Test - fun `does not detect var declaration with property delegate`() { - val rule = DoubleMutabilityForCollection( - TestConfig( - mapOf( - MUTABLE_TYPES to listOf("MutableState") - ) + @Test + fun `does not detect val declaration with ArrayList`() { + val code = """ + val myArrayList = ArrayList() + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + + @Test + fun `does not detect val declaration with LinkedHashSet`() { + val code = """ + val myLinkedHashSet = LinkedHashSet() + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + + @Test + fun `does not detect val declaration with HashSet`() { + val code = """ + val myHashSet = HashSet() + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + + @Test + fun `does not detect val declaration with LinkedHashMap`() { + val code = """ + val myLinkedHashMap = LinkedHashMap() + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + + @Test + fun `does not detect val declaration with HashMap`() { + val code = """ + val myHashMap = HashMap() + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + } + + @Nested + inner class `ignores declaration with var and immutable types` { + + @Test + fun `does not detect var declaration with immutable list`() { + val code = """ + val myList = listOf(1,2,3) + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + + @Test + fun `does not detect var declaration with immutable set`() { + val code = """ + val mySet = setOf(1,2,3) + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + + @Test + fun `does not detect var declaration with immutable map`() { + val code = """ + val myMap = mapOf("answer" to 42) + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + } + + @Nested + inner class `ignores declaration with var and property delegation` { + + @Test + fun `does not detect var declaration with property delegate`() { + val rule = DoubleMutabilityForCollection( + TestConfig( + mapOf( + MUTABLE_TYPES to listOf("MutableState") ) ) + ) + + val code = """ + data class MutableState(var state: T) + fun mutableStateOf(value: T): MutableState = MutableState(value) + fun remember(calculation: () -> T): T = calculation() + inline operator fun MutableState.getValue(thisObj: Any?, property: kotlin.reflect.KProperty<*>): T = state + inline operator fun MutableState.setValue(thisObj: Any?, property: kotlin.reflect.KProperty<*>, value: T) { + this.state = value + } + var myState by remember { mutableStateOf("foo") } + """ + val result = rule.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + } + } + + @Nested + inner class `class properties` { - val code = """ - data class MutableState(var state: T) - fun mutableStateOf(value: T): MutableState = MutableState(value) - fun remember(calculation: () -> T): T = calculation() - inline operator fun MutableState.getValue(thisObj: Any?, property: kotlin.reflect.KProperty<*>): T = state - inline operator fun MutableState.setValue(thisObj: Any?, property: kotlin.reflect.KProperty<*>, value: T) { - this.state = value - } - class MyClass { - var myState by remember { mutableStateOf("foo") } - } - """ - val result = rule.compileAndLintWithContext(env, code) - assertThat(result).isEmpty() + @Nested + inner class `valid cases` { + + @Test + fun `detects var declaration with mutable list`() { + val code = """ + class MyClass { + var myOtherList = mutableListOf(1,2,3) + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(2, 5) + } + + @Test + fun `detects var declaration with mutable set`() { + val code = """ + class MyClass { + var mySet = mutableSetOf(1,2,3) + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(2, 5) + } + + @Test + fun `detects var declaration with mutable map`() { + val code = """ + class MyClass { + var myMap = mutableMapOf("answer" to 42) + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(2, 5) + } + + @Test + fun `detects var declaration with ArrayList`() { + val code = """ + class MyClass { + var myArrayList = ArrayList() + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(2, 5) + } + + @Test + fun `detects var declaration with LinkedHashSet`() { + val code = """ + class MyClass { + var myLinkedHashSet = LinkedHashSet() + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(2, 5) + } + + @Test + fun `detects var declaration with HashSet`() { + val code = """ + class MyClass { + var myHashSet = HashSet() + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(2, 5) + } + + @Test + fun `detects var declaration with LinkedHashMap`() { + val code = """ + class MyClass { + var myLinkedHashMap = LinkedHashMap() + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(2, 5) + } + + @Test + fun `detects var declaration with HashMap`() { + val code = """ + class MyClass { + var myHashMap = HashMap() + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(2, 5) + } + + @Test + fun `detects var declaration with MutableState, when configured`() { + val rule = DoubleMutabilityForCollection( + TestConfig( + mapOf( + MUTABLE_TYPES to listOf("MutableState") + ) + ) + ) + + val code = """ + data class MutableState(var state: T) + class MyClass { + var myState = MutableState("foo") + } + """ + val result = rule.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(3, 5) + } + + @Test + fun `detects var declaration with MutableState via factory function, when configured`() { + val rule = DoubleMutabilityForCollection( + TestConfig( + mapOf( + MUTABLE_TYPES to listOf("MutableState") + ) + ) + ) + + val code = """ + data class MutableState(var state: T) + fun mutableStateOf(value: T): MutableState = MutableState(value) + class MyClass { + var myState = mutableStateOf("foo") + } + """ + val result = rule.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(4, 5) + } + + @Test + fun `detects var declaration with MutableState via calculation lambda, when configured`() { + val rule = DoubleMutabilityForCollection( + TestConfig( + mapOf( + MUTABLE_TYPES to listOf("MutableState") + ) + ) + ) + + val code = """ + data class MutableState(var state: T) + fun mutableStateOf(value: T): MutableState = MutableState(value) + fun remember(calculation: () -> T): T = calculation() + class MyClass { + var myState = remember { mutableStateOf("foo") } + } + """ + val result = rule.compileAndLintWithContext(env, code) + assertThat(result).hasSize(1) + assertThat(result).hasSourceLocation(5, 5) + } + } + + @Nested + inner class `ignores declaration with val` { + + @Test + fun `does not detect val declaration with mutable list`() { + val code = """ + class MyClass { + val myList = mutableListOf(1,2,3) + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + + @Test + fun `does not detect val declaration with mutable set`() { + val code = """ + class MyClass { + val mySet = mutableSetOf(1,2,3) + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + + @Test + fun `does not detect val declaration with mutable map`() { + val code = """ + class MyClass { + val myMap = mutableMapOf("answer" to 42) + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + + @Test + fun `does not detect val declaration with ArrayList`() { + val code = """ + class MyClass { + val myArrayList = ArrayList() + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + + @Test + fun `does not detect val declaration with LinkedHashSet`() { + val code = """ + class MyClass { + val myLinkedHashSet = LinkedHashSet() + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + + @Test + fun `does not detect val declaration with HashSet`() { + val code = """ + class MyClass { + val myHashSet = HashSet() + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + + @Test + fun `does not detect val declaration with LinkedHashMap`() { + val code = """ + class MyClass { + val myLinkedHashMap = LinkedHashMap() + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + + @Test + fun `does not detect val declaration with HashMap`() { + val code = """ + class MyClass { + val myHashMap = HashMap() + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + } + + @Nested + inner class `ignores declaration with var and immutable types` { + + @Test + fun `does not detect var declaration with immutable list`() { + val code = """ + class MyClass { + val myList = listOf(1,2,3) + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + + @Test + fun `does not detect var declaration with immutable set`() { + val code = """ + class MyClass { + val mySet = setOf(1,2,3) + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + + @Test + fun `does not detect var declaration with immutable map`() { + val code = """ + class MyClass { + val myMap = mapOf("answer" to 42) + } + """ + val result = subject.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() + } + } + + @Nested + inner class `ignores declaration with var and property delegation` { + + @Test + fun `does not detect var declaration with property delegate`() { + val rule = DoubleMutabilityForCollection( + TestConfig( + mapOf( + MUTABLE_TYPES to listOf("MutableState") + ) + ) + ) + + val code = """ + data class MutableState(var state: T) + fun mutableStateOf(value: T): MutableState = MutableState(value) + fun remember(calculation: () -> T): T = calculation() + inline operator fun MutableState.getValue(thisObj: Any?, property: kotlin.reflect.KProperty<*>): T = state + inline operator fun MutableState.setValue(thisObj: Any?, property: kotlin.reflect.KProperty<*>, value: T) { + this.state = value + } + class MyClass { + var myState by remember { mutableStateOf("foo") } } + """ + val result = rule.compileAndLintWithContext(env, code) + assertThat(result).isEmpty() } } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DuplicateCaseInWhenExpressionSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DuplicateCaseInWhenExpressionSpec.kt index d91e394ed3a..14dc5ad18ed 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DuplicateCaseInWhenExpressionSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DuplicateCaseInWhenExpressionSpec.kt @@ -3,44 +3,39 @@ package io.gitlab.arturbosch.detekt.rules.bugs import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class DuplicateCaseInWhenExpressionSpec { private val subject = DuplicateCaseInWhenExpression(Config.empty) - @Nested - inner class `Duplicate Case In When Expression rule` { - - @Test - fun `reports duplicated label in when`() { - val code = """ - fun f() { - when (1) { - 1 -> println() - 1 -> kotlin.io.println() - 1, 2 -> println() - 1, 2 -> kotlin.io.println() - else -> println() - } + @Test + fun `reports duplicated label in when`() { + val code = """ + fun f() { + when (1) { + 1 -> println() + 1 -> kotlin.io.println() + 1, 2 -> println() + 1, 2 -> kotlin.io.println() + else -> println() } - """ - val result = subject.compileAndLint(code) - assertThat(result).hasSize(1) - assertThat(result.first().message).isEqualTo("When expression has multiple case statements for 1; 1, 2.") - } + } + """ + val result = subject.compileAndLint(code) + assertThat(result).hasSize(1) + assertThat(result.first().message).isEqualTo("When expression has multiple case statements for 1; 1, 2.") + } - @Test - fun `does not report duplicated label in when`() { - val code = """ - fun f() { - when (1) { - 1 -> println() - else -> println() - } + @Test + fun `does not report duplicated label in when`() { + val code = """ + fun f() { + when (1) { + 1 -> println() + else -> println() } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ElseCaseInsteadOfExhaustiveWhenSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ElseCaseInsteadOfExhaustiveWhenSpec.kt index 72f084e24c3..e28c2b8abb6 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ElseCaseInsteadOfExhaustiveWhenSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ElseCaseInsteadOfExhaustiveWhenSpec.kt @@ -13,299 +13,296 @@ class ElseCaseInsteadOfExhaustiveWhenSpec(private val env: KotlinCoreEnvironment private val subject = ElseCaseInsteadOfExhaustiveWhen() @Nested - inner class `ElseCaseInsteadOfExhaustiveWhen rule` { - @Nested - inner class Enum { - @Test - fun `reports when enum _when_ expression used as statement contains _else_ case`() { - val code = """ - enum class Color { - RED, - GREEN, - BLUE + inner class Enum { + @Test + fun `reports when enum _when_ expression used as statement contains _else_ case`() { + val code = """ + enum class Color { + RED, + GREEN, + BLUE + } + + fun whenOnEnumFail(c: Color) { + when (c) { + Color.BLUE -> {} + Color.GREEN -> {} + else -> {} } + } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + } - fun whenOnEnumFail(c: Color) { - when (c) { - Color.BLUE -> {} - Color.GREEN -> {} - else -> {} - } + @Test + fun `reports when enum _when_ expression contains _else_ case`() { + val code = """ + enum class Color { + RED, + GREEN, + BLUE + } + + fun whenOnEnumFail(c: Color) { + val x = when (c) { + Color.BLUE -> 1 + Color.GREEN -> 2 + else -> 100 } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + } - @Test - fun `reports when enum _when_ expression contains _else_ case`() { - val code = """ - enum class Color { - RED, - GREEN, - BLUE + @Test + fun `does not report when enum _when_ expression does not contain _else_ case`() { + val code = """ + enum class Color { + RED, + GREEN, + BLUE + } + + fun whenOnEnumPassA(c: Color) { + when (c) { + Color.BLUE -> {} + Color.GREEN -> {} + Color.RED -> {} } - fun whenOnEnumFail(c: Color) { - val x = when (c) { - Color.BLUE -> 1 - Color.GREEN -> 2 - else -> 100 - } + val x = when (c) { + Color.BLUE -> 1 + Color.GREEN -> 2 + Color.RED -> 3 } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) } - @Test - fun `does not report when enum _when_ expression does not contain _else_ case`() { - val code = """ - enum class Color { - RED, - GREEN, - BLUE + fun whenOnEnumPassB(c: Color) { + when (c) { + Color.BLUE -> {} + Color.GREEN -> {} } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + } - fun whenOnEnumPassA(c: Color) { - when (c) { - Color.BLUE -> {} - Color.GREEN -> {} - Color.RED -> {} - } + @Nested + inner class `Sealed class` { + @Test + fun `reports when sealed _when_ expression used as statement contains _else_ case`() { + val code = """ + sealed class Variant { + object VariantA : Variant() + class VariantB : Variant() + object VariantC : Variant() + } - val x = when (c) { - Color.BLUE -> 1 - Color.GREEN -> 2 - Color.RED -> 3 + fun whenOnSealedFail(v: Variant) { + when (v) { + is Variant.VariantA -> {} + is Variant.VariantB -> {} + else -> {} } } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } + + @Test + fun `reports when sealed _when_ expression contains _else_ case`() { + val code = """ + sealed class Variant { + object VariantA : Variant() + class VariantB : Variant() + object VariantC : Variant() + } - fun whenOnEnumPassB(c: Color) { - when (c) { - Color.BLUE -> {} - Color.GREEN -> {} + fun whenOnSealedFail(v: Variant) { + val x = when (v) { + is Variant.VariantA -> "a" + is Variant.VariantB -> "b" + else -> "other" } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) } - @Nested - inner class `Sealed class` { - @Test - fun `reports when sealed _when_ expression used as statement contains _else_ case`() { - val code = """ - sealed class Variant { - object VariantA : Variant() - class VariantB : Variant() - object VariantC : Variant() - } + @Test + fun `does not report when sealed _when_ expression does not contain _else_ case`() { + val code = """ + sealed class Variant { + object VariantA : Variant() + class VariantB : Variant() + object VariantC : Variant() + } - fun whenOnSealedFail(v: Variant) { - when (v) { - is Variant.VariantA -> {} - is Variant.VariantB -> {} - else -> {} - } + fun whenOnSealedPass(v: Variant) { + when (v) { + is Variant.VariantA -> {} + is Variant.VariantB -> {} } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + } - @Test - fun `reports when sealed _when_ expression contains _else_ case`() { - val code = """ - sealed class Variant { - object VariantA : Variant() - class VariantB : Variant() - object VariantC : Variant() - } + @Nested + inner class `Expected sealed class` { + @Test + fun `does not report when _expect_ sealed _when_ expression used as statement contains _else_ case`() { + val code = """ + expect sealed class Variant { + class VariantA : Variant + class VariantB : Variant + class VariantC : Variant + } - fun whenOnSealedFail(v: Variant) { - val x = when (v) { - is Variant.VariantA -> "a" - is Variant.VariantB -> "b" - else -> "other" - } + fun whenOnSealedFail(v: Variant) { + when (v) { + is Variant.VariantA -> {} + is Variant.VariantB -> {} + else -> {} } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + } + """ + assertThat(subject.lintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report when sealed _when_ expression does not contain _else_ case`() { - val code = """ - sealed class Variant { - object VariantA : Variant() - class VariantB : Variant() - object VariantC : Variant() - } + @Test + fun `does not report when _expect_ sealed _when_ expression contains _else_ case`() { + val code = """ + expect sealed class Variant { + class VariantA : Variant + class VariantB : Variant + class VariantC : Variant + } - fun whenOnSealedPass(v: Variant) { - when (v) { - is Variant.VariantA -> {} - is Variant.VariantB -> {} - } + fun whenOnSealedFail(v: Variant) { + val x = when (v) { + is Variant.VariantA -> "a" + is Variant.VariantB -> "b" + else -> "other" } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.lintWithContext(env, code)).isEmpty() } + } - @Nested - inner class `Expected sealed class` { - @Test - fun `does not report when _expect_ sealed _when_ expression used as statement contains _else_ case`() { - val code = """ - expect sealed class Variant { - class VariantA : Variant - class VariantB : Variant - class VariantC : Variant - } + @Nested + inner class Boolean { + @Test + fun `reports when boolean _when_ expression used as statement contains _else_ case`() { + val code = """ + fun whenOnBooleanFail(b: Boolean) { + when (b) { + true -> {} + else -> {} + } + } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + } - fun whenOnSealedFail(v: Variant) { - when (v) { - is Variant.VariantA -> {} - is Variant.VariantB -> {} - else -> {} - } - } - """ - assertThat(subject.lintWithContext(env, code)).isEmpty() + @Test + fun `reports when nullable boolean _when_ expression contains _else_ case`() { + val code = """ + fun whenOnNullableBooleanFail(b: Boolean?) { + val x = when (b) { + true -> 1 + false -> 2 + else -> 100 + } } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + } - @Test - fun `does not report when _expect_ sealed _when_ expression contains _else_ case`() { - val code = """ - expect sealed class Variant { - class VariantA : Variant - class VariantB : Variant - class VariantC : Variant - } + @Test + fun `does not report when boolean _when_ expression does not contain _else_ case`() { + val code = """ + fun whenOnBooleanPassA(b: Boolean) { + when (b) { + true -> {} + false -> {} + } - fun whenOnSealedFail(v: Variant) { - val x = when (v) { - is Variant.VariantA -> "a" - is Variant.VariantB -> "b" - else -> "other" - } - } - """ - assertThat(subject.lintWithContext(env, code)).isEmpty() + val x = when (b) { + true -> 1 + false -> 2 + } } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } - @Nested - inner class Boolean { - @Test - fun `reports when boolean _when_ expression used as statement contains _else_ case`() { - val code = """ - fun whenOnBooleanFail(b: Boolean) { - when (b) { - true -> {} - else -> {} - } + @Test + fun `does not report when nullable boolean _when_ expression does not contain _else_ case`() { + val code = """ + fun whenOnNullableBooleanPassA(b: Boolean?) { + when (b) { + true -> {} + false -> {} + null -> {} } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - } - @Test - fun `reports when nullable boolean _when_ expression contains _else_ case`() { - val code = """ - fun whenOnNullableBooleanFail(b: Boolean?) { - val x = when (b) { - true -> 1 - false -> 2 - else -> 100 - } + val x = when (b) { + true -> 1 + false -> 2 + null -> 100 } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + } - @Test - fun `does not report when boolean _when_ expression does not contain _else_ case`() { - val code = """ - fun whenOnBooleanPassA(b: Boolean) { - when (b) { - true -> {} - false -> {} + @Nested + inner class `Standard when` { + @Test + fun `does not report when _else_ case is used for non enum or sealed _when_ expression`() { + val code = """ + fun whenChecks() { + val x = 3 + val s = "3" + + when (x) { + 0, 1 -> print("x == 0 or x == 1") + else -> print("otherwise") } - val x = when (b) { - true -> 1 - false -> 2 + when (x) { + Integer.parseInt(s) -> print("s encodes x") + else -> print("s does not encode x") } - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - @Test - fun `does not report when nullable boolean _when_ expression does not contain _else_ case`() { - val code = """ - fun whenOnNullableBooleanPassA(b: Boolean?) { - when (b) { - true -> {} - false -> {} - null -> {} + when (x) { + in 1..10 -> print("x is in the range") + !in 10..20 -> print("x is outside the range") + else -> print("none of the above") } - val x = when (b) { - true -> 1 - false -> 2 - null -> 100 + val y = when(s) { + is String -> s.startsWith("prefix") + else -> false } - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - } - @Nested - inner class `Standard when` { - @Test - fun `does not report when _else_ case is used for non enum or sealed _when_ expression`() { - val code = """ - fun whenChecks() { - val x = 3 - val s = "3" - - when (x) { - 0, 1 -> print("x == 0 or x == 1") - else -> print("otherwise") - } - - when (x) { - Integer.parseInt(s) -> print("s encodes x") - else -> print("s does not encode x") - } - - when (x) { - in 1..10 -> print("x is in the range") - !in 10..20 -> print("x is outside the range") - else -> print("none of the above") - } - - val y = when(s) { - is String -> s.startsWith("prefix") - else -> false - } - - when { - x.equals(s) -> print("x equals s") - x.plus(3) == 4 -> print("x is 1") - else -> print("x is funny") - } + when { + x.equals(s) -> print("x equals s") + x.plus(3) == 4 -> print("x is 1") + else -> print("x is funny") } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/EqualsAlwaysReturnsTrueOrFalseSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/EqualsAlwaysReturnsTrueOrFalseSpec.kt index f818573ec47..8c03ab170f3 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/EqualsAlwaysReturnsTrueOrFalseSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/EqualsAlwaysReturnsTrueOrFalseSpec.kt @@ -5,49 +5,44 @@ import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.test.compileAndLint import io.gitlab.arturbosch.detekt.test.lint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class EqualsAlwaysReturnsTrueOrFalseSpec { private val subject = EqualsAlwaysReturnsTrueOrFalse(Config.empty) - @Nested - inner class `Equals Always Returns True Or False rule` { - - @Test - fun `reports equals() methods`() { - assertThat(subject.lint(resourceAsPath("EqualsAlwaysReturnsTrueOrFalsePositive.kt"))).hasSize(6) - } + @Test + fun `reports equals() methods`() { + assertThat(subject.lint(resourceAsPath("EqualsAlwaysReturnsTrueOrFalsePositive.kt"))).hasSize(6) + } - @Test - fun `does not report equals() methods`() { - assertThat(subject.lint(resourceAsPath("EqualsAlwaysReturnsTrueOrFalseNegative.kt"))).isEmpty() - } + @Test + fun `does not report equals() methods`() { + assertThat(subject.lint(resourceAsPath("EqualsAlwaysReturnsTrueOrFalseNegative.kt"))).isEmpty() + } - @Test - fun `detects and doesn't crash when return expression is annotated - #2021`() { - val code = """ - class C { - override fun equals(other: Any?): Boolean { - @Suppress("UnsafeCallOnNullableType") - return true - } + @Test + fun `detects and doesn't crash when return expression is annotated - #2021`() { + val code = """ + class C { + override fun equals(other: Any?): Boolean { + @Suppress("UnsafeCallOnNullableType") + return true } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `detects and doesn't crash when the equals method contains no return expression - #2103`() { - val code = """ - open class SuperClass - - data class Item(val text: String) : SuperClass() { - override fun equals(other: Any?): Boolean = (other as? Item)?.text == this.text - override fun hashCode(): Int = text.hashCode() - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `detects and doesn't crash when the equals method contains no return expression - #2103`() { + val code = """ + open class SuperClass + + data class Item(val text: String) : SuperClass() { + override fun equals(other: Any?): Boolean = (other as? Item)?.text == this.text + override fun hashCode(): Int = text.hashCode() + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/EqualsWithHashCodeExistSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/EqualsWithHashCodeExistSpec.kt index 047f82a7088..b423c6c6520 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/EqualsWithHashCodeExistSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/EqualsWithHashCodeExistSpec.kt @@ -10,120 +10,116 @@ class EqualsWithHashCodeExistSpec { private val subject = EqualsWithHashCodeExist(Config.empty) @Nested - inner class `Equals With Hash Code Exist rule` { + inner class `some classes with equals() and hashCode() functions` { - @Nested - inner class `some classes with equals() and hashCode() functions` { - - @Test - fun `reports hashCode() without equals() function`() { - val code = """ - class A { - override fun hashCode(): Int { return super.hashCode() } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) + @Test + fun `reports hashCode() without equals() function`() { + val code = """ + class A { + override fun hashCode(): Int { return super.hashCode() } } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports equals() without hashCode() function`() { - val code = """ - class A { - override fun equals(other: Any?): Boolean { return super.equals(other) } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) + @Test + fun `reports equals() without hashCode() function`() { + val code = """ + class A { + override fun equals(other: Any?): Boolean { return super.equals(other) } } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports a different equals() function signature`() { - val code = """ - class A { - fun equals(other: Any?, i: Int): Boolean { return super.equals(other) } - override fun hashCode(): Int { return super.hashCode() } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) + @Test + fun `reports a different equals() function signature`() { + val code = """ + class A { + fun equals(other: Any?, i: Int): Boolean { return super.equals(other) } + override fun hashCode(): Int { return super.hashCode() } } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports a different hashcode() function signature`() { - val code = """ - class A { - override fun equals(other: Any?): Boolean { return super.equals(other) } - fun hashCode(i: Int): Int { return super.hashCode() } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) + @Test + fun `reports a different hashcode() function signature`() { + val code = """ + class A { + override fun equals(other: Any?): Boolean { return super.equals(other) } + fun hashCode(i: Int): Int { return super.hashCode() } } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports a different overridden equals() function signature`() { - val code = """ - interface I { - fun equals(other: Any?, i: Int): Boolean - } + @Test + fun `reports a different overridden equals() function signature`() { + val code = """ + interface I { + fun equals(other: Any?, i: Int): Boolean + } - class A : I { - override fun equals(other: Any?, i: Int): Boolean { return super.equals(other) } - override fun hashCode(): Int { return super.hashCode() } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) + class A : I { + override fun equals(other: Any?, i: Int): Boolean { return super.equals(other) } + override fun hashCode(): Int { return super.hashCode() } } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports a different overridden hashCode() function signature`() { - val code = """ - interface I { - fun hashCode(i: Int): Int - } + @Test + fun `reports a different overridden hashCode() function signature`() { + val code = """ + interface I { + fun hashCode(i: Int): Int + } - class A : I { - override fun equals(other: Any?): Boolean { return super.equals(other) } - override fun hashCode(i: Int): Int { return super.hashCode() } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) + class A : I { + override fun equals(other: Any?): Boolean { return super.equals(other) } + override fun hashCode(i: Int): Int { return super.hashCode() } } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report equals() with hashCode() function`() { - val code = """ - class A { - override fun equals(other: Any?): Boolean { return super.equals(other) } - override fun hashCode(): Int { return super.hashCode() } - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() + @Test + fun `does not report equals() with hashCode() function`() { + val code = """ + class A { + override fun equals(other: Any?): Boolean { return super.equals(other) } + override fun hashCode(): Int { return super.hashCode() } } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report when using nullable Any`() { - val code = """ - class A { - override fun equals(other: kotlin.Any?): Boolean { return super.equals(other) } - override fun hashCode(): Int { return super.hashCode() } - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() + @Test + fun `does not report when using nullable Any`() { + val code = """ + class A { + override fun equals(other: kotlin.Any?): Boolean { return super.equals(other) } + override fun hashCode(): Int { return super.hashCode() } } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } + } - @Nested - inner class `a data class` { - - @Test - fun `does not report equals() or hashcode() violation on data class`() { - val code = """ - data class EqualsData(val i: Int) { - override fun equals(other: Any?): Boolean { - return super.equals(other) - } + @Nested + inner class `a data class` { + + @Test + fun `does not report equals() or hashcode() violation on data class`() { + val code = """ + data class EqualsData(val i: Int) { + override fun equals(other: Any?): Boolean { + return super.equals(other) } - """ - assertThat(subject.compileAndLint(code)).isEmpty() } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ExitOutsideMainSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ExitOutsideMainSpec.kt index 6f8fbb386a8..7ce15c8c363 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ExitOutsideMainSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ExitOutsideMainSpec.kt @@ -4,81 +4,76 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class ExitOutsideMainSpec(private val env: KotlinCoreEnvironment) { private val subject = ExitOutsideMain() - @Nested - inner class `ExitOutsideMainSpec rule` { + @Test + fun `reports exitProcess used outside main()`() { + val code = """ + import kotlin.system.exitProcess + fun f() { + exitProcess(0) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `reports exitProcess used outside main()`() { - val code = """ - import kotlin.system.exitProcess - fun f() { - exitProcess(0) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + @Test + fun `reports System_exit used outside main()`() { + val code = """ + fun f() { + System.exit(0) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `reports System_exit used outside main()`() { - val code = """ - fun f() { - System.exit(0) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + @Test + fun `does not report exitProcess used in main()`() { + val code = """ + import kotlin.system.exitProcess + fun main() { + exitProcess(0) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report exitProcess used in main()`() { - val code = """ - import kotlin.system.exitProcess - fun main() { + @Test + fun `does not report System_exit used in main()`() { + val code = """ + fun main() { + System.exit(0) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `reports exitProcess used in nested function in main()`() { + val code = """ + import kotlin.system.exitProcess + fun main() { + fun exit() { exitProcess(0) } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `does not report System_exit used in main()`() { - val code = """ - fun main() { + @Test + fun `reports System_exit used in nested function in main()`() { + val code = """ + fun main() { + fun exit() { System.exit(0) } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `reports exitProcess used in nested function in main()`() { - val code = """ - import kotlin.system.exitProcess - fun main() { - fun exit() { - exitProcess(0) - } - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `reports System_exit used in nested function in main()`() { - val code = """ - fun main() { - fun exit() { - System.exit(0) - } - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ExplicitGarbageCollectionCallSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ExplicitGarbageCollectionCallSpec.kt index f5d16084360..13b93625d79 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ExplicitGarbageCollectionCallSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ExplicitGarbageCollectionCallSpec.kt @@ -3,25 +3,20 @@ package io.gitlab.arturbosch.detekt.rules.bugs import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ExplicitGarbageCollectionCallSpec { private val subject = ExplicitGarbageCollectionCall(Config.empty) - @Nested - inner class `ExplicitGarbageCollectionCall rule` { - - @Test - fun `reports garbage collector calls`() { - val code = """ - fun f() { - System.gc() - Runtime.getRuntime().gc() - System.runFinalization() - } - """ - assertThat(subject.compileAndLint(code)).hasSize(3) - } + @Test + fun `reports garbage collector calls`() { + val code = """ + fun f() { + System.gc() + Runtime.getRuntime().gc() + System.runFinalization() + } + """ + assertThat(subject.compileAndLint(code)).hasSize(3) } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/HasPlatformTypeSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/HasPlatformTypeSpec.kt index 11b97e83fa2..81bcb8590be 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/HasPlatformTypeSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/HasPlatformTypeSpec.kt @@ -5,74 +5,69 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class HasPlatformTypeSpec(private val env: KotlinCoreEnvironment) { private val subject = HasPlatformType(Config.empty) - @Nested - inner class `Deprecation detection` { - - @Test - fun `reports when public function returns expression of platform type`() { - val code = """ - class Person { - fun apiCall() = System.getProperty("propertyName") - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + @Test + fun `reports when public function returns expression of platform type`() { + val code = """ + class Person { + fun apiCall() = System.getProperty("propertyName") + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `does not report function when private`() { - val code = """ - class Person { - private fun apiCall() = System.getProperty("propertyName") - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does not report function when private`() { + val code = """ + class Person { + private fun apiCall() = System.getProperty("propertyName") + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report when public function returns expression of platform type and type explicitly declared`() { - val code = """ - class Person { - fun apiCall(): String = System.getProperty("propertyName") - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does not report when public function returns expression of platform type and type explicitly declared`() { + val code = """ + class Person { + fun apiCall(): String = System.getProperty("propertyName") + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `reports when property initiated with platform type`() { - val code = """ - class Person { - val name = System.getProperty("name") - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + @Test + fun `reports when property initiated with platform type`() { + val code = """ + class Person { + val name = System.getProperty("name") + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `does not report property when private`() { - val code = """ - class Person { - private val name = System.getProperty("name") - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does not report property when private`() { + val code = """ + class Person { + private val name = System.getProperty("name") + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report when property initiated with platform type and type explicitly declared`() { - val code = """ - class Person { - val name: String = System.getProperty("name") - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does not report when property initiated with platform type and type explicitly declared`() { + val code = """ + class Person { + val name: String = System.getProperty("name") + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ImplicitDefaultLocaleSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ImplicitDefaultLocaleSpec.kt index 773c81b02e2..2c4d6864423 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ImplicitDefaultLocaleSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ImplicitDefaultLocaleSpec.kt @@ -5,103 +5,98 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class ImplicitDefaultLocaleSpec(private val env: KotlinCoreEnvironment) { private val subject = ImplicitDefaultLocale(Config.empty) - @Nested - inner class `ImplicitDefault rule` { - - @Test - fun `reports String_format call with template but without explicit locale`() { - val code = """ - fun x() { - String.format("%d", 1) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + @Test + fun `reports String_format call with template but without explicit locale`() { + val code = """ + fun x() { + String.format("%d", 1) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `does not report String_format call with explicit locale`() { - val code = """ - import java.util.Locale - fun x() { - String.format(Locale.US, "%d", 1) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does not report String_format call with explicit locale`() { + val code = """ + import java.util.Locale + fun x() { + String.format(Locale.US, "%d", 1) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `reports String_toUpperCase() call without explicit locale`() { - val code = """ - fun x() { - val s = "deadbeef" - s.toUpperCase() - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + @Test + fun `reports String_toUpperCase() call without explicit locale`() { + val code = """ + fun x() { + val s = "deadbeef" + s.toUpperCase() + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `does not report String_toUpperCase() call with explicit locale`() { - val code = """ - import java.util.Locale - fun x() { - val s = "deadbeef" - s.toUpperCase(Locale.US) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does not report String_toUpperCase() call with explicit locale`() { + val code = """ + import java.util.Locale + fun x() { + val s = "deadbeef" + s.toUpperCase(Locale.US) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `reports String_toLowerCase() call without explicit locale`() { - val code = """ - fun x() { - val s = "deadbeef" - s.toLowerCase() - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + @Test + fun `reports String_toLowerCase() call without explicit locale`() { + val code = """ + fun x() { + val s = "deadbeef" + s.toLowerCase() + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `does not report String_toLowerCase() call with explicit locale`() { - val code = """ - import java.util.Locale - fun x() { - val s = "deadbeef" - s.toLowerCase(Locale.US) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does not report String_toLowerCase() call with explicit locale`() { + val code = """ + import java.util.Locale + fun x() { + val s = "deadbeef" + s.toLowerCase(Locale.US) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `reports nullable String_toUpperCase call without explicit locale`() { - val code = """ - fun x() { - val s: String? = "deadbeef" - s?.toUpperCase() - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + @Test + fun `reports nullable String_toUpperCase call without explicit locale`() { + val code = """ + fun x() { + val s: String? = "deadbeef" + s?.toUpperCase() + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `reports nullable String_toLowerCase call without explicit locale`() { - val code = """ - fun x() { - val s: String? = "deadbeef" - s?.toLowerCase() - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + @Test + fun `reports nullable String_toLowerCase call without explicit locale`() { + val code = """ + fun x() { + val s: String? = "deadbeef" + s?.toLowerCase() + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ImplicitUnitReturnTypeSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ImplicitUnitReturnTypeSpec.kt index 3505fe9559a..e033f226190 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ImplicitUnitReturnTypeSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/ImplicitUnitReturnTypeSpec.kt @@ -6,68 +6,63 @@ import io.gitlab.arturbosch.detekt.test.TestConfig import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class ImplicitUnitReturnTypeSpec(private val env: KotlinCoreEnvironment) { private val subject = ImplicitUnitReturnType(Config.empty) - @Nested - inner class `Functions returning Unit via expression statements` { + @Test + fun `reports implicit Unit return types`() { + val code = """ + fun errorProneUnit() = println("Hello Unit") + fun errorProneUnitWithParam(param: String) = param.run { println(this) } + fun String.errorProneUnitWithReceiver() = run { println(this) } + """ - @Test - fun `reports implicit Unit return types`() { - val code = """ - fun errorProneUnit() = println("Hello Unit") - fun errorProneUnitWithParam(param: String) = param.run { println(this) } - fun String.errorProneUnitWithReceiver() = run { println(this) } - """ + val findings = subject.compileAndLintWithContext(env, code) - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(3) - } + assertThat(findings).hasSize(3) + } - @Test - fun `does not report explicit Unit return type by default`() { - val code = """fun safeUnitReturn(): Unit = println("Hello Unit")""" + @Test + fun `does not report explicit Unit return type by default`() { + val code = """fun safeUnitReturn(): Unit = println("Hello Unit")""" - val findings = subject.compileAndLintWithContext(env, code) + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `reports explicit Unit return type if configured`() { - val code = """fun safeButStillReported(): Unit = println("Hello Unit")""" + @Test + fun `reports explicit Unit return type if configured`() { + val code = """fun safeButStillReported(): Unit = println("Hello Unit")""" - val findings = ImplicitUnitReturnType(TestConfig("allowExplicitReturnType" to "false")) - .compileAndLintWithContext(env, code) + val findings = ImplicitUnitReturnType(TestConfig("allowExplicitReturnType" to "false")) + .compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + assertThat(findings).hasSize(1) + } - @Test - fun `does not report for block statements`() { - val code = """ - fun blockUnitReturn() { - println("Hello Unit") - } - """ + @Test + fun `does not report for block statements`() { + val code = """ + fun blockUnitReturn() { + println("Hello Unit") + } + """ - val findings = subject.compileAndLintWithContext(env, code) + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `does not report for Unit expression`() { - val code = """ - fun foo() = Unit - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + @Test + fun `does not report for Unit expression`() { + val code = """ + fun foo() = Unit + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/IteratorHasNextCallsNextMethodSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/IteratorHasNextCallsNextMethodSpec.kt index e2db73aca33..b54324f9136 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/IteratorHasNextCallsNextMethodSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/IteratorHasNextCallsNextMethodSpec.kt @@ -3,25 +3,20 @@ package io.gitlab.arturbosch.detekt.rules.bugs import io.github.detekt.test.utils.resourceAsPath import io.gitlab.arturbosch.detekt.test.lint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class IteratorHasNextCallsNextMethodSpec { private val subject = IteratorHasNextCallsNextMethod() - @Nested - inner class `IteratorHasNextCallsNextMethod rule` { - - @Test - fun `reports wrong iterator implementation`() { - val path = resourceAsPath("IteratorImplPositive.kt") - assertThat(subject.lint(path)).hasSize(4) - } + @Test + fun `reports wrong iterator implementation`() { + val path = resourceAsPath("IteratorImplPositive.kt") + assertThat(subject.lint(path)).hasSize(4) + } - @Test - fun `does not report correct iterator implementations`() { - val path = resourceAsPath("IteratorImplNegative.kt") - assertThat(subject.lint(path)).isEmpty() - } + @Test + fun `does not report correct iterator implementations`() { + val path = resourceAsPath("IteratorImplNegative.kt") + assertThat(subject.lint(path)).isEmpty() } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/IteratorNotThrowingNoSuchElementExceptionSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/IteratorNotThrowingNoSuchElementExceptionSpec.kt index 3e7220acf86..9c4f0f36f0c 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/IteratorNotThrowingNoSuchElementExceptionSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/IteratorNotThrowingNoSuchElementExceptionSpec.kt @@ -3,25 +3,20 @@ package io.gitlab.arturbosch.detekt.rules.bugs import io.github.detekt.test.utils.resourceAsPath import io.gitlab.arturbosch.detekt.test.lint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class IteratorNotThrowingNoSuchElementExceptionSpec { private val subject = IteratorNotThrowingNoSuchElementException() - @Nested - inner class `IteratorNotThrowingNoSuchElementException rule` { - - @Test - fun `reports invalid next() implementations`() { - val path = resourceAsPath("IteratorImplPositive.kt") - assertThat(subject.lint(path)).hasSize(4) - } + @Test + fun `reports invalid next() implementations`() { + val path = resourceAsPath("IteratorImplPositive.kt") + assertThat(subject.lint(path)).hasSize(4) + } - @Test - fun `does not report correct next() implemenations`() { - val path = resourceAsPath("IteratorImplNegative.kt") - assertThat(subject.lint(path)).isEmpty() - } + @Test + fun `does not report correct next() implemenations`() { + val path = resourceAsPath("IteratorImplNegative.kt") + assertThat(subject.lint(path)).isEmpty() } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/LateinitUsageSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/LateinitUsageSpec.kt index e78bbaea02f..851b0983b43 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/LateinitUsageSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/LateinitUsageSpec.kt @@ -5,103 +5,99 @@ import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatExceptionOfType import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import java.util.regex.PatternSyntaxException class LateinitUsageSpec { - @Nested - inner class `LateinitUsage rule` { - val code = """ - import kotlin.SinceKotlin - - class SomeRandomTest { - lateinit var v1: String - @SinceKotlin("1.0.0") lateinit var v2: String - } - """ - - @Test - fun `should report lateinit usages`() { - val findings = LateinitUsage().compileAndLint(code) - assertThat(findings).hasSize(2) - } + val code = """ + import kotlin.SinceKotlin - @Test - @DisplayName("should only report lateinit property with no @SinceKotlin annotation") - fun `should only report lateinit property with no SinceKotlin annotation`() { - val findings = - LateinitUsage(TestConfig(mapOf(EXCLUDE_ANNOTATED_PROPERTIES to listOf("SinceKotlin")))).compileAndLint( - code - ) - assertThat(findings).hasSize(1) + class SomeRandomTest { + lateinit var v1: String + @SinceKotlin("1.0.0") lateinit var v2: String } + """ - @Test - @DisplayName("should only report lateinit properties not matching kotlin.*") - fun `should only report lateinit properties not matching any kotlin annotation`() { - val findings = - LateinitUsage(TestConfig(mapOf(EXCLUDE_ANNOTATED_PROPERTIES to listOf("kotlin.*")))).compileAndLint(code) - assertThat(findings).hasSize(1) - } + @Test + fun `should report lateinit usages`() { + val findings = LateinitUsage().compileAndLint(code) + assertThat(findings).hasSize(2) + } - @Test - fun `should only report lateinit properties matching kotlin_SinceKotlin`() { - val config = TestConfig(mapOf(EXCLUDE_ANNOTATED_PROPERTIES to listOf("kotlin.SinceKotlin"))) - val findings = LateinitUsage(config).compileAndLint(code) - assertThat(findings).hasSize(1) - } + @Test + @DisplayName("should only report lateinit property with no @SinceKotlin annotation") + fun `should only report lateinit property with no SinceKotlin annotation`() { + val findings = + LateinitUsage(TestConfig(mapOf(EXCLUDE_ANNOTATED_PROPERTIES to listOf("SinceKotlin")))).compileAndLint( + code + ) + assertThat(findings).hasSize(1) + } - @Test - fun `should only report lateinit property with no @SinceKotlin annotation with config string`() { - val findings = - LateinitUsage(TestConfig(mapOf(EXCLUDE_ANNOTATED_PROPERTIES to "SinceKotlin"))).compileAndLint(code) - assertThat(findings).hasSize(1) - } + @Test + @DisplayName("should only report lateinit properties not matching kotlin.*") + fun `should only report lateinit properties not matching any kotlin annotation`() { + val findings = + LateinitUsage(TestConfig(mapOf(EXCLUDE_ANNOTATED_PROPERTIES to listOf("kotlin.*")))).compileAndLint(code) + assertThat(findings).hasSize(1) + } - @Test - fun `should only report lateinit property with no @SinceKotlin annotation containing whitespaces with config string`() { - val findings = - LateinitUsage(TestConfig(mapOf(EXCLUDE_ANNOTATED_PROPERTIES to " SinceKotlin "))).compileAndLint(code) - assertThat(findings).hasSize(1) - } + @Test + fun `should only report lateinit properties matching kotlin_SinceKotlin`() { + val config = TestConfig(mapOf(EXCLUDE_ANNOTATED_PROPERTIES to listOf("kotlin.SinceKotlin"))) + val findings = LateinitUsage(config).compileAndLint(code) + assertThat(findings).hasSize(1) + } - @Test - fun `should report lateinit properties not matching the exclude pattern`() { - val findings = - LateinitUsage(TestConfig(mapOf(EXCLUDE_ANNOTATED_PROPERTIES to "IgnoreThis"))).compileAndLint(code) - assertThat(findings).hasSize(2) - } + @Test + fun `should only report lateinit property with no @SinceKotlin annotation with config string`() { + val findings = + LateinitUsage(TestConfig(mapOf(EXCLUDE_ANNOTATED_PROPERTIES to "SinceKotlin"))).compileAndLint(code) + assertThat(findings).hasSize(1) + } - @Test - fun `should report lateinit properties when ignoreOnClassesPattern does not match`() { - val findings = - LateinitUsage(TestConfig(mapOf(IGNORE_ON_CLASSES_PATTERN to "[\\w]+Test1234"))).compileAndLint(code) - assertThat(findings).hasSize(2) - } + @Test + fun `should only report lateinit property with no @SinceKotlin annotation containing whitespaces with config string`() { + val findings = + LateinitUsage(TestConfig(mapOf(EXCLUDE_ANNOTATED_PROPERTIES to " SinceKotlin "))).compileAndLint(code) + assertThat(findings).hasSize(1) + } - @Test - fun `should not report lateinit properties when ignoreOnClassesPattern does match`() { - val findings = - LateinitUsage(TestConfig(mapOf(IGNORE_ON_CLASSES_PATTERN to "[\\w]+Test"))).compileAndLint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should report lateinit properties not matching the exclude pattern`() { + val findings = + LateinitUsage(TestConfig(mapOf(EXCLUDE_ANNOTATED_PROPERTIES to "IgnoreThis"))).compileAndLint(code) + assertThat(findings).hasSize(2) + } - @Test - fun `should fail when enabled with faulty regex pattern`() { - assertThatExceptionOfType(PatternSyntaxException::class.java).isThrownBy { - LateinitUsage(TestConfig(mapOf(IGNORE_ON_CLASSES_PATTERN to "*Test"))).compileAndLint(code) - } - } + @Test + fun `should report lateinit properties when ignoreOnClassesPattern does not match`() { + val findings = + LateinitUsage(TestConfig(mapOf(IGNORE_ON_CLASSES_PATTERN to "[\\w]+Test1234"))).compileAndLint(code) + assertThat(findings).hasSize(2) + } + + @Test + fun `should not report lateinit properties when ignoreOnClassesPattern does match`() { + val findings = + LateinitUsage(TestConfig(mapOf(IGNORE_ON_CLASSES_PATTERN to "[\\w]+Test"))).compileAndLint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should not fail when disabled with faulty regex pattern`() { - val configValues = mapOf("active" to "false", IGNORE_ON_CLASSES_PATTERN to "*Test") - val findings = LateinitUsage(TestConfig(configValues)).compileAndLint(code) - assertThat(findings).isEmpty() + @Test + fun `should fail when enabled with faulty regex pattern`() { + assertThatExceptionOfType(PatternSyntaxException::class.java).isThrownBy { + LateinitUsage(TestConfig(mapOf(IGNORE_ON_CLASSES_PATTERN to "*Test"))).compileAndLint(code) } } + + @Test + fun `should not fail when disabled with faulty regex pattern`() { + val configValues = mapOf("active" to "false", IGNORE_ON_CLASSES_PATTERN to "*Test") + val findings = LateinitUsage(TestConfig(configValues)).compileAndLint(code) + assertThat(findings).isEmpty() + } } private const val EXCLUDE_ANNOTATED_PROPERTIES = "excludeAnnotatedProperties" diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/MissingPackageDeclarationSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/MissingPackageDeclarationSpec.kt index c774d4e0906..9055f94e66d 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/MissingPackageDeclarationSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/MissingPackageDeclarationSpec.kt @@ -2,33 +2,28 @@ package io.gitlab.arturbosch.detekt.rules.bugs import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test internal class MissingPackageDeclarationSpec { - @Nested - inner class `MissingPackageDeclaration rule` { + @Test + fun `should pass if package declaration is declared`() { + val code = """ + package foo.bar - @Test - fun `should pass if package declaration is declared`() { - val code = """ - package foo.bar + class C + """ + val findings = MissingPackageDeclaration().compileAndLint(code) - class C - """ - val findings = MissingPackageDeclaration().compileAndLint(code) - - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `should report if package declaration is missing`() { - val code = "class C" + @Test + fun `should report if package declaration is missing`() { + val code = "class C" - val findings = MissingPackageDeclaration().compileAndLint(code) + val findings = MissingPackageDeclaration().compileAndLint(code) - assertThat(findings).hasSize(1) - } + assertThat(findings).hasSize(1) } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/NullCheckOnMutablePropertySpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/NullCheckOnMutablePropertySpec.kt index fcca9160834..5f8cd740627 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/NullCheckOnMutablePropertySpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/NullCheckOnMutablePropertySpec.kt @@ -6,311 +6,307 @@ import io.gitlab.arturbosch.detekt.test.compileAndLint import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class NullCheckOnMutablePropertySpec(private val env: KotlinCoreEnvironment) { private val subject = NullCheckOnMutableProperty(Config.empty) - @Nested - inner class `NullCheckOnMutableProperty Rule` { - @Test - fun `should report a null-check on a mutable constructor property`() { - val code = """ - class A(private var a: Int?) { - fun foo() { - if (a != null) { - println(2 + a!!) - } - } + @Test + fun `should report a null-check on a mutable constructor property`() { + val code = """ + class A(private var a: Int?) { + fun foo() { + if (a != null) { + println(2 + a!!) + } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `should report a null-check on a mutable property in non-initial clauses in an if-statement`() { - val code = """ - class A(private var a: Int?, private val b: Int) { - fun foo() { - if (b == 5 && a != null) { - println(2 + a!!) - } - } + @Test + fun `should report a null-check on a mutable property in non-initial clauses in an if-statement`() { + val code = """ + class A(private var a: Int?, private val b: Int) { + fun foo() { + if (b == 5 && a != null) { + println(2 + a!!) + } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `should report a null-check on a mutable property used in the same if-statement`() { - val code = """ - class A(private var a: Int?) { - fun foo() { - if (a != null && a == 2) { - println("a is 2") - } - } + @Test + fun `should report a null-check on a mutable property used in the same if-statement`() { + val code = """ + class A(private var a: Int?) { + fun foo() { + if (a != null && a == 2) { + println("a is 2") + } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `should report on a mutable property that is not subject to a double-bang`() { - val code = """ - class A(private var a: Int?) { - fun foo() { - if (a != null) { - println(a) - } - } + @Test + fun `should report on a mutable property that is not subject to a double-bang`() { + val code = """ + class A(private var a: Int?) { + fun foo() { + if (a != null) { + println(a) + } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `should report on a mutable property even if it is checked multiple times`() { - val code = """ - class A(private var a: Int?) { - fun foo() { - if (a != null) { - if (a == null) { - return - } - println(2 + a!!) - } - } + @Test + fun `should report on a mutable property even if it is checked multiple times`() { + val code = """ + class A(private var a: Int?) { + fun foo() { + if (a != null) { + if (a == null) { + return + } + println(2 + a!!) + } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `should not report when the checked property is not used afterwards`() { - val code = """ - class A(private var a: Int?) { - fun foo() { - if (a != null) { - println("'a' is not null") - } - } + @Test + fun `should not report when the checked property is not used afterwards`() { + val code = """ + class A(private var a: Int?) { + fun foo() { + if (a != null) { + println("'a' is not null") + } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `should not report a null-check on a shadowed property`() { - val code = """ - class A(private var a: Int?) { - fun foo() { - val a = a - if (a != null) { - println(2 + a) - } - } + @Test + fun `should not report a null-check on a shadowed property`() { + val code = """ + class A(private var a: Int?) { + fun foo() { + val a = a + if (a != null) { + println(2 + a) + } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `should not report a null-check on a non-mutable constructor property`() { - val code = """ - class A(private val a: Int?) { - fun foo() { - if (a != null) { - println(2 + a) - } - } + @Test + fun `should not report a null-check on a non-mutable constructor property`() { + val code = """ + class A(private val a: Int?) { + fun foo() { + if (a != null) { + println(2 + a) + } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `should report a null-check on a mutable class property`() { - val code = """ - class A { - private var a: Int? = 5 - fun foo() { - if (a != null) { - println(2 + a!!) - } - } + @Test + fun `should report a null-check on a mutable class property`() { + val code = """ + class A { + private var a: Int? = 5 + fun foo() { + if (a != null) { + println(2 + a!!) + } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `should not report a null-check on a val property`() { - val code = """ - class A { - private val a: Int? = 5 - fun foo() { - if (a != null) { - println(2 + a) - } - } + @Test + fun `should not report a null-check on a val property`() { + val code = """ + class A { + private val a: Int? = 5 + fun foo() { + if (a != null) { + println(2 + a) + } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `should report a null-check on a val property with a getter`() { - val code = """ - import kotlin.random.Random - - class A { - private val a: Int? - get() = genA() - fun foo() { - if (a != null) { - println(2 + a!!) - } - } - private fun genA(): Int? { - val randInt = Random.nextInt() - return if (randInt % 2 == 0) randInt else null - } + @Test + fun `should report a null-check on a val property with a getter`() { + val code = """ + import kotlin.random.Random + + class A { + private val a: Int? + get() = genA() + fun foo() { + if (a != null) { + println(2 + a!!) + } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `should report a null-check conducted within an inner class`() { - val code = """ - class A(private var a: Int?) { - inner class B { - fun foo() { - if (a != null) { - println(2 + a!!) - } - } - } + private fun genA(): Int? { + val randInt = Random.nextInt() + return if (randInt % 2 == 0) randInt else null } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `should report an inner-class mutable property`() { - val code = """ - class A(private val a: Int?) { - inner class B(private var a: Int) { - fun foo() { - if (a != null) { - println(2 + a!!) - } - } - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } + @Test + fun `should report a null-check conducted within an inner class`() { + val code = """ + class A(private var a: Int?) { + inner class B { fun foo() { if (a != null) { - println(2 + a) + println(2 + a!!) } } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `should report a null-check on a mutable file property`() { - val code = """ - private var a: Int? = 5 - - class A { + @Test + fun `should report an inner-class mutable property`() { + val code = """ + class A(private val a: Int?) { + inner class B(private var a: Int) { fun foo() { if (a != null) { println(2 + a!!) } } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - @Test - fun `should not report a null-check on a non-mutable file property`() { - val code = """ - private val a: Int? = 5 - - class A { - fun foo() { - if (a != null) { - println(2 + a) - } - } + fun foo() { + if (a != null) { + println(2 + a) + } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `should not report a null-check when there is no binding context`() { - val code = """ - class A(private var a: Int?) { - fun foo() { - if (a != null) { - println(2 + a!!) - } - } + @Test + fun `should report a null-check on a mutable file property`() { + val code = """ + private var a: Int? = 5 + + class A { + fun foo() { + if (a != null) { + println(2 + a!!) + } } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `should report a null-check when null is the first element in the if-statement`() { - val code = """ - class A(private var a: Int?) { - fun foo() { - if (null != a) { - println(2 + a!!) - } - } + @Test + fun `should not report a null-check on a non-mutable file property`() { + val code = """ + private val a: Int? = 5 + + class A { + fun foo() { + if (a != null) { + println(2 + a) + } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `should not report when the if-expression has no explicit null value`() { - val code = """ - class A(private var a: Int?) { - fun foo() { - val otherA = null - if (a != otherA) { - println(2 + a!!) - } - } + @Test + fun `should not report a null-check when there is no binding context`() { + val code = """ + class A(private var a: Int?) { + fun foo() { + if (a != null) { + println(2 + a!!) + } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `should not report a null-check on a function`() { - val code = """ - class A { - private fun otherFoo(): Int? { - return null - } - fun foo() { - if (otherFoo() != null) { - println(2 + otherFoo()!!) - } - } + @Test + fun `should report a null-check when null is the first element in the if-statement`() { + val code = """ + class A(private var a: Int?) { + fun foo() { + if (null != a) { + println(2 + a!!) + } + } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } + + @Test + fun `should not report when the if-expression has no explicit null value`() { + val code = """ + class A(private var a: Int?) { + fun foo() { + val otherA = null + if (a != otherA) { + println(2 + a!!) + } + } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `should not report a null-check on a function`() { + val code = """ + class A { + private fun otherFoo(): Int? { + return null + } + fun foo() { + if (otherFoo() != null) { + println(2 + otherFoo()!!) + } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/NullableToStringCallSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/NullableToStringCallSpec.kt index 8d37dff084e..2cd3bfe64cf 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/NullableToStringCallSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/NullableToStringCallSpec.kt @@ -4,182 +4,178 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class NullableToStringCallSpec(private val env: KotlinCoreEnvironment) { private val subject = NullableToStringCall() - @Nested - inner class `NullableToString rule` { - @Test - fun `reports when a nullable toString is explicitly called`() { - val code = """ - fun test(a: Any?) { - println(a.toString()) - } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - assertThat(actual.first().message).isEqualTo("This call 'a.toString()' may return the string \"null\".") - } + @Test + fun `reports when a nullable toString is explicitly called`() { + val code = """ + fun test(a: Any?) { + println(a.toString()) + } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + assertThat(actual.first().message).isEqualTo("This call 'a.toString()' may return the string \"null\".") + } - @Test - fun `reports when a nullable toString is implicitly called in a string template`() { - val code = """ - fun test(a: Any?) { - println("${'$'}a") - } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - assertThat(actual.first().message).isEqualTo("This call '\$a' may return the string \"null\".") - } + @Test + fun `reports when a nullable toString is implicitly called in a string template`() { + val code = """ + fun test(a: Any?) { + println("${'$'}a") + } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + assertThat(actual.first().message).isEqualTo("This call '\$a' may return the string \"null\".") + } - @Test - fun `reports when a nullable toString is implicitly called in curly braces in a string template`() { - val code = """ - fun test(a: Any?) { - println("${'$'}{a}") - } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - assertThat(actual.first().message).isEqualTo("This call '\${a}' may return the string \"null\".") - } + @Test + fun `reports when a nullable toString is implicitly called in curly braces in a string template`() { + val code = """ + fun test(a: Any?) { + println("${'$'}{a}") + } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + assertThat(actual.first().message).isEqualTo("This call '\${a}' may return the string \"null\".") + } - @Test - fun `reports when a nullable toString is implicitly called in a raw string template`() { - val code = """ - fun test(a: Any?) { - println(${'"'}""${'$'}a""${'"'}) - } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - assertThat(actual.first().message).isEqualTo("This call '\$a' may return the string \"null\".") - } + @Test + fun `reports when a nullable toString is implicitly called in a raw string template`() { + val code = """ + fun test(a: Any?) { + println(${'"'}""${'$'}a""${'"'}) + } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + assertThat(actual.first().message).isEqualTo("This call '\$a' may return the string \"null\".") + } - @Test - fun `reports when a nullable toString is explicitly called and the expression is qualified or call expression`() { - val code = """ - data class Foo(val a: Any?) { - fun bar(): Int? = null - } - fun baz(): Long? = null - - fun test(foo: Foo) { - val x = foo.a.toString() - val y = foo.bar().toString() - val z = baz().toString() - } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(3) - assertThat(actual[0].message).isEqualTo("This call 'foo.a.toString()' may return the string \"null\".") - assertThat(actual[1].message).isEqualTo("This call 'foo.bar().toString()' may return the string \"null\".") - assertThat(actual[2].message).isEqualTo("This call 'baz().toString()' may return the string \"null\".") - } + @Test + fun `reports when a nullable toString is explicitly called and the expression is qualified or call expression`() { + val code = """ + data class Foo(val a: Any?) { + fun bar(): Int? = null + } + fun baz(): Long? = null + + fun test(foo: Foo) { + val x = foo.a.toString() + val y = foo.bar().toString() + val z = baz().toString() + } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(3) + assertThat(actual[0].message).isEqualTo("This call 'foo.a.toString()' may return the string \"null\".") + assertThat(actual[1].message).isEqualTo("This call 'foo.bar().toString()' may return the string \"null\".") + assertThat(actual[2].message).isEqualTo("This call 'baz().toString()' may return the string \"null\".") + } - @Test - fun `reports when a nullable toString is implicitly called and the expression is qualified or call expression`() { - val code = """ - data class Foo(val a: Any?) { - fun bar(): Int? = null - } - fun baz(): Long? = null - - fun test(foo: Foo) { - val x = "${'$'}{foo.a}" - val y = "${'$'}{foo.bar()}" - val z = "${'$'}{baz()}" - } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(3) - assertThat(actual[0].message).isEqualTo("This call '\${foo.a}' may return the string \"null\".") - assertThat(actual[1].message).isEqualTo("This call '\${foo.bar()}' may return the string \"null\".") - assertThat(actual[2].message).isEqualTo("This call '\${baz()}' may return the string \"null\".") - } + @Test + fun `reports when a nullable toString is implicitly called and the expression is qualified or call expression`() { + val code = """ + data class Foo(val a: Any?) { + fun bar(): Int? = null + } + fun baz(): Long? = null + + fun test(foo: Foo) { + val x = "${'$'}{foo.a}" + val y = "${'$'}{foo.bar()}" + val z = "${'$'}{baz()}" + } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(3) + assertThat(actual[0].message).isEqualTo("This call '\${foo.a}' may return the string \"null\".") + assertThat(actual[1].message).isEqualTo("This call '\${foo.bar()}' may return the string \"null\".") + assertThat(actual[2].message).isEqualTo("This call '\${baz()}' may return the string \"null\".") + } - @Test - fun `reports when a nullable toString is implicitly called and the expression is safe qualified expression`() { - val code = """ - data class Foo(val a: Any) - - fun test(foo: Foo?) { - val y = "${'$'}{foo?.a}" - } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - assertThat(actual[0].message).isEqualTo("This call '\${foo?.a}' may return the string \"null\".") - } + @Test + fun `reports when a nullable toString is implicitly called and the expression is safe qualified expression`() { + val code = """ + data class Foo(val a: Any) + + fun test(foo: Foo?) { + val y = "${'$'}{foo?.a}" + } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + assertThat(actual[0].message).isEqualTo("This call '\${foo?.a}' may return the string \"null\".") + } - @Test - fun `does not report when a nullable toString is not called`() { - val code = """ - fun test(a: Any?) { - println(a?.toString()) - println("${'$'}{a ?: "-"}") - } - fun test2(a: Any) { - println(a.toString()) - println("${'$'}a") - println("${'$'}{a}") - println(${'"'}""${'$'}a""${'"'}) - } - fun test3(a: Any?) { - if (a != null) { - println(a.toString()) - println("${'$'}a") - println("${'$'}{a}") - println(${'"'}""${'$'}a""${'"'}) - } - } - fun test4(a: Any?) { - requireNotNull(a) + @Test + fun `does not report when a nullable toString is not called`() { + val code = """ + fun test(a: Any?) { + println(a?.toString()) + println("${'$'}{a ?: "-"}") + } + fun test2(a: Any) { + println(a.toString()) + println("${'$'}a") + println("${'$'}{a}") + println(${'"'}""${'$'}a""${'"'}) + } + fun test3(a: Any?) { + if (a != null) { println(a.toString()) println("${'$'}a") println("${'$'}{a}") println(${'"'}""${'$'}a""${'"'}) } + } + fun test4(a: Any?) { + requireNotNull(a) + println(a.toString()) + println("${'$'}a") + println("${'$'}{a}") + println(${'"'}""${'$'}a""${'"'}) + } - data class Foo(val a: Any?) - fun test5(foo: Foo) { - if (foo.a == null) return - val x = foo.a.toString() - val y = "${'$'}{foo.a}" - } + data class Foo(val a: Any?) + fun test5(foo: Foo) { + if (foo.a == null) return + val x = foo.a.toString() + val y = "${'$'}{foo.a}" + } - data class Bar(val a: Any) - fun test6(bar: Bar?) { - if (bar == null) return - val x = bar?.a.toString() - val y = "${'$'}{bar?.a}" - } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).isEmpty() - } + data class Bar(val a: Any) + fun test6(bar: Bar?) { + if (bar == null) return + val x = bar?.a.toString() + val y = "${'$'}{bar?.a}" + } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).isEmpty() + } - // https://github.com/detekt/detekt/issues/4059 - @Test - fun `ignores platform types`() { - val code = """ - class Foo(val a: Any) { - fun test(foo: Foo?) { - // getSimpleName() is not annotated with nullability information in the JDK, so compiler treats - // it as a platform type with unknown nullability. IDE behavior is different as it can take - // advantage of external annotations, which unfortunately isn't supported in the compiler, so we - // whitelist all platform types to avoid false positives. - val y = "${'$'}{javaClass.simpleName}" - } + // https://github.com/detekt/detekt/issues/4059 + @Test + fun `ignores platform types`() { + val code = """ + class Foo(val a: Any) { + fun test(foo: Foo?) { + // getSimpleName() is not annotated with nullability information in the JDK, so compiler treats + // it as a platform type with unknown nullability. IDE behavior is different as it can take + // advantage of external annotations, which unfortunately isn't supported in the compiler, so we + // whitelist all platform types to avoid false positives. + val y = "${'$'}{javaClass.simpleName}" } - """.trimIndent() - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).isEmpty() - } + } + """.trimIndent() + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).isEmpty() } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/RedundantElseInWhenSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/RedundantElseInWhenSpec.kt index 810f1ca0051..a507cd5f31b 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/RedundantElseInWhenSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/RedundantElseInWhenSpec.kt @@ -12,242 +12,239 @@ class RedundantElseInWhenSpec(private val env: KotlinCoreEnvironment) { private val subject = RedundantElseInWhen() @Nested - inner class `RedundantElseInWhen rule` { - @Nested - inner class `enum` { - @Test - fun `reports when _when_ expression used as statement contains _else_ case when all cases already covered`() { - val code = """ - enum class Color { - RED, - GREEN, - BLUE - } - - fun whenOnEnumFail(c: Color) { - when (c) { - Color.BLUE -> {} - Color.GREEN -> {} - Color.RED -> {} - else -> {} - } + inner class `enum` { + @Test + fun `reports when _when_ expression used as statement contains _else_ case when all cases already covered`() { + val code = """ + enum class Color { + RED, + GREEN, + BLUE + } + + fun whenOnEnumFail(c: Color) { + when (c) { + Color.BLUE -> {} + Color.GREEN -> {} + Color.RED -> {} + else -> {} } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + } - @Test - fun `reports when _when_ expression contains _else_ case when all cases already covered`() { - val code = """ - enum class Color { - RED, - GREEN, - BLUE - } - - fun whenOnEnumFail(c: Color) { - val x = when (c) { - Color.BLUE -> 1 - Color.GREEN -> 2 - Color.RED -> 3 - else -> 100 - } + @Test + fun `reports when _when_ expression contains _else_ case when all cases already covered`() { + val code = """ + enum class Color { + RED, + GREEN, + BLUE + } + + fun whenOnEnumFail(c: Color) { + val x = when (c) { + Color.BLUE -> 1 + Color.GREEN -> 2 + Color.RED -> 3 + else -> 100 } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) + } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + } + + @Test + fun `does not report when _when_ expression contains _else_ case when not all cases explicitly covered`() { + val code = """ + enum class Color { + RED, + GREEN, + BLUE } - @Test - fun `does not report when _when_ expression contains _else_ case when not all cases explicitly covered`() { - val code = """ - enum class Color { - RED, - GREEN, - BLUE + fun whenOnEnumPass(c: Color) { + when (c) { + Color.BLUE -> {} + Color.GREEN -> {} + else -> {} } - fun whenOnEnumPass(c: Color) { - when (c) { - Color.BLUE -> {} - Color.GREEN -> {} - else -> {} - } + val x = when (c) { + Color.BLUE -> 1 + Color.GREEN -> 2 + else -> 100 + } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - val x = when (c) { - Color.BLUE -> 1 - Color.GREEN -> 2 - else -> 100 - } + @Test + fun `does not report when _when_ expression does not contain else case`() { + val code = """ + enum class Color { + RED, + GREEN, + BLUE + } + + fun whenOnEnumPassA(c: Color) { + when (c) { + Color.BLUE -> {} + Color.GREEN -> {} + Color.RED -> {} + } + + val x = when (c) { + Color.BLUE -> 1 + Color.GREEN -> 2 + Color.RED -> 3 } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } - @Test - fun `does not report when _when_ expression does not contain else case`() { - val code = """ - enum class Color { - RED, - GREEN, - BLUE + fun whenOnEnumPassB(c: Color) { + when (c) { + Color.BLUE -> {} + Color.GREEN -> {} } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + } - fun whenOnEnumPassA(c: Color) { - when (c) { - Color.BLUE -> {} - Color.GREEN -> {} - Color.RED -> {} - } + @Nested + inner class `sealed classes` { + @Test + fun `reports when _when_ expression used as statement contains _else_ case when all cases already covered`() { + val code = """ + sealed class Variant { + object VariantA : Variant() + class VariantB : Variant() + object VariantC : Variant() + } - val x = when (c) { - Color.BLUE -> 1 - Color.GREEN -> 2 - Color.RED -> 3 + fun whenOnEnumFail(v: Variant) { + when (v) { + is Variant.VariantA -> {} + is Variant.VariantB -> {} + is Variant.VariantC -> {} + else -> {} } } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - fun whenOnEnumPassB(c: Color) { - when (c) { - Color.BLUE -> {} - Color.GREEN -> {} + @Test + fun `reports when _when_ expression contains _else_ case when all cases already covered`() { + val code = """ + sealed class Variant { + object VariantA : Variant() + class VariantB : Variant() + object VariantC : Variant() + } + + fun whenOnEnumFail(v: Variant) { + val x = when (v) { + is Variant.VariantA -> "a" + is Variant.VariantB -> "b" + is Variant.VariantC -> "c" + else -> "other" } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) } - @Nested - inner class `sealed classes` { - @Test - fun `reports when _when_ expression used as statement contains _else_ case when all cases already covered`() { - val code = """ - sealed class Variant { - object VariantA : Variant() - class VariantB : Variant() - object VariantC : Variant() - } + @Test + fun `does not report when _when_ expression contains _else_ case when not all cases explicitly covered`() { + val code = """ + sealed class Variant { + object VariantA : Variant() + class VariantB : Variant() + object VariantC : Variant() + } - fun whenOnEnumFail(v: Variant) { - when (v) { - is Variant.VariantA -> {} - is Variant.VariantB -> {} - is Variant.VariantC -> {} - else -> {} - } + fun whenOnEnumPass(v: Variant) { + when (v) { + is Variant.VariantA -> {} + is Variant.VariantB -> {} + else -> {} } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - @Test - fun `reports when _when_ expression contains _else_ case when all cases already covered`() { - val code = """ - sealed class Variant { - object VariantA : Variant() - class VariantB : Variant() - object VariantC : Variant() + val x = when (v) { + is Variant.VariantA -> "a" + is Variant.VariantB -> "b" + else -> "other" } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - fun whenOnEnumFail(v: Variant) { - val x = when (v) { - is Variant.VariantA -> "a" - is Variant.VariantB -> "b" - is Variant.VariantC -> "c" - else -> "other" - } + @Test + fun `does not report when _when_ expression does not contain else case`() { + val code = """ + sealed class Variant { + object VariantA : Variant() + class VariantB : Variant() + object VariantC : Variant() + } + + fun whenOnEnumPass(v: Variant) { + when (v) { + is Variant.VariantA -> {} + is Variant.VariantB -> {} } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + } + + @Nested + inner class `standard when` { + @Test + fun `does not report when _when_ not checking for missing cases`() { + val code = """ + fun whenChecks() { + val x = 3 + val s = "3" - @Test - fun `does not report when _when_ expression contains _else_ case when not all cases explicitly covered`() { - val code = """ - sealed class Variant { - object VariantA : Variant() - class VariantB : Variant() - object VariantC : Variant() + when (x) { + 0, 1 -> print("x == 0 or x == 1") + else -> print("otherwise") } - fun whenOnEnumPass(v: Variant) { - when (v) { - is Variant.VariantA -> {} - is Variant.VariantB -> {} - else -> {} - } - - val x = when (v) { - is Variant.VariantA -> "a" - is Variant.VariantB -> "b" - else -> "other" - } + when (x) { + Integer.parseInt(s) -> print("s encodes x") + else -> print("s does not encode x") } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - @Test - fun `does not report when _when_ expression does not contain else case`() { - val code = """ - sealed class Variant { - object VariantA : Variant() - class VariantB : Variant() - object VariantC : Variant() + when (x) { + in 1..10 -> print("x is in the range") + !in 10..20 -> print("x is outside the range") + else -> print("none of the above") } - fun whenOnEnumPass(v: Variant) { - when (v) { - is Variant.VariantA -> {} - is Variant.VariantB -> {} - } + val y = when(s) { + is String -> s.startsWith("prefix") + else -> false } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - } - @Nested - inner class `standard when` { - @Test - fun `does not report when _when_ not checking for missing cases`() { - val code = """ - fun whenChecks() { - val x = 3 - val s = "3" - - when (x) { - 0, 1 -> print("x == 0 or x == 1") - else -> print("otherwise") - } - - when (x) { - Integer.parseInt(s) -> print("s encodes x") - else -> print("s does not encode x") - } - - when (x) { - in 1..10 -> print("x is in the range") - !in 10..20 -> print("x is outside the range") - else -> print("none of the above") - } - - val y = when(s) { - is String -> s.startsWith("prefix") - else -> false - } - - when { - x.equals(s) -> print("x equals s") - x.plus(3) == 4 -> print("x is 1") - else -> print("x is funny") - } + when { + x.equals(s) -> print("x equals s") + x.plus(3) == 4 -> print("x is 1") + else -> print("x is funny") } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnconditionalJumpStatementInLoopSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnconditionalJumpStatementInLoopSpec.kt index 5ba94fefea4..6c5c8d7b7ab 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnconditionalJumpStatementInLoopSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnconditionalJumpStatementInLoopSpec.kt @@ -2,359 +2,354 @@ package io.gitlab.arturbosch.detekt.rules.bugs import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class UnconditionalJumpStatementInLoopSpec { private val subject = UnconditionalJumpStatementInLoop() - @Nested - inner class `UnconditionalJumpStatementInLoop rule` { - - @Test - fun `reports an unconditional return in for loop`() { - val code = """ - fun f() { - for (i in 1..2) return - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports an unconditional return in for loop`() { + val code = """ + fun f() { + for (i in 1..2) return + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports an unconditional return in while loop`() { - val code = """ - fun f() { - while (true) { return } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports an unconditional return in while loop`() { + val code = """ + fun f() { + while (true) { return } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports an unconditional return in do-while loop`() { - val code = """ - fun f() { - do { return } while(true) - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports an unconditional return in do-while loop`() { + val code = """ + fun f() { + do { return } while(true) + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports an unconditional continue in for loop`() { - val code = """ - fun f() { - for (i in 1..2) continue - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports an unconditional continue in for loop`() { + val code = """ + fun f() { + for (i in 1..2) continue + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports an unconditional continue in while loop`() { - val code = """ - fun f() { - while (true) { continue } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports an unconditional continue in while loop`() { + val code = """ + fun f() { + while (true) { continue } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports an unconditional continue in do-while loop`() { - val code = """ - fun f() { - do { continue } while(true) - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports an unconditional continue in do-while loop`() { + val code = """ + fun f() { + do { continue } while(true) + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports an unconditional break in for loop`() { - val code = """ - fun f() { - for (i in 1..2) break - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports an unconditional break in for loop`() { + val code = """ + fun f() { + for (i in 1..2) break + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports an unconditional break in while loop`() { - val code = """ - fun f() { - while (true) { break } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports an unconditional break in while loop`() { + val code = """ + fun f() { + while (true) { break } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports an unconditional break in do-while loop`() { - val code = """ - fun f() { - do { break } while(true) - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports an unconditional break in do-while loop`() { + val code = """ + fun f() { + do { break } while(true) + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports an unconditional return in a nested loop`() { - val code = """ - fun f() { - for (i in 1..2) { - for (j in 1..2) { - return - } + @Test + fun `reports an unconditional return in a nested loop`() { + val code = """ + fun f() { + for (i in 1..2) { + for (j in 1..2) { + return } } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports an unconditional continue in a nested loop`() { - val code = """ - fun f() { - for (i in 1..2) { - for (j in 1..2) { - continue - } + @Test + fun `reports an unconditional continue in a nested loop`() { + val code = """ + fun f() { + for (i in 1..2) { + for (j in 1..2) { + continue } } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports an unconditional break in a nested loop`() { - val code = """ - fun f() { - for (i in 1..2) { - for (j in 1..2) { - break - } + @Test + fun `reports an unconditional break in a nested loop`() { + val code = """ + fun f() { + for (i in 1..2) { + for (j in 1..2) { + break } } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report a conditional return in an if-else block`() { - val code = """ - fun f() { - for (i in 1..2) { - if (i > 1) { - return - } - if (i > 1) println() else return + @Test + fun `does not report a conditional return in an if-else block`() { + val code = """ + fun f() { + for (i in 1..2) { + if (i > 1) { + return } + if (i > 1) println() else return } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report a conditional continue in an if-else block`() { - val code = """ - fun f() { - for (i in 1..2) { - if (i > 1) { - continue - } - if (i > 1) println() else continue + @Test + fun `does not report a conditional continue in an if-else block`() { + val code = """ + fun f() { + for (i in 1..2) { + if (i > 1) { + continue } + if (i > 1) println() else continue } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report a conditional break in an if-else block`() { - val code = """ - fun f() { - for (i in 1..2) { - if (i > 1) { - break - } - if (i > 1) println() else break + @Test + fun `does not report a conditional break in an if-else block`() { + val code = """ + fun f() { + for (i in 1..2) { + if (i > 1) { + break } + if (i > 1) println() else break } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `reports an unconditional return after Elvis operator`() { - val code = """ - fun main() { - fun compute(i: Int) = null - for (i in 1..5) - return compute(i) ?: return - } - """ + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports an unconditional return after Elvis operator`() { + val code = """ + fun main() { + fun compute(i: Int) = null + for (i in 1..5) + return compute(i) ?: return + } + """ + + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report a conditional continue after Elvis operator`() { - val code = """ - fun f(): Int { - fun compute(i: Int): Int? = null - for (i in 1..5) { - return compute(i) ?: continue - } - return 0 + @Test + fun `does not report a conditional continue after Elvis operator`() { + val code = """ + fun f(): Int { + fun compute(i: Int): Int? = null + for (i in 1..5) { + return compute(i) ?: continue } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + return 0 + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report a conditional break after Elvis operator`() { - val code = """ - fun f(): Int { - fun compute(i: Int): Int? = null - for (i in 1..5) { - return compute(i) ?: break - } - return 0 + @Test + fun `does not report a conditional break after Elvis operator`() { + val code = """ + fun f(): Int { + fun compute(i: Int): Int? = null + for (i in 1..5) { + return compute(i) ?: break } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + return 0 + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report a conditional return after assignment with Elvis operator`() { - val code = """ - fun f(): Int { - fun compute(i: Int): Int? = null - for (i in 1..5) { - val int = compute(i) ?: return 0 - return int + 1 - } - return 0 + @Test + fun `does not report a conditional return after assignment with Elvis operator`() { + val code = """ + fun f(): Int { + fun compute(i: Int): Int? = null + for (i in 1..5) { + val int = compute(i) ?: return 0 + return int + 1 } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + return 0 + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report a conditional continue after assignment with Elvis operator`() { - val code = """ - fun f(): Int { - fun compute(i: Int): Int? = null - for (i in 1..5) { - val int = compute(i) ?: continue - return int + 1 - } - return 0 + @Test + fun `does not report a conditional continue after assignment with Elvis operator`() { + val code = """ + fun f(): Int { + fun compute(i: Int): Int? = null + for (i in 1..5) { + val int = compute(i) ?: continue + return int + 1 } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + return 0 + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report a conditional break after assignment with Elvis operator`() { - val code = """ - fun f(): Int { - fun compute(i: Int): Int? = null - for (i in 1..5) { - val int = compute(i) ?: break - return int + 1 - } - return 0 + @Test + fun `does not report a conditional break after assignment with Elvis operator`() { + val code = """ + fun f(): Int { + fun compute(i: Int): Int? = null + for (i in 1..5) { + val int = compute(i) ?: break + return int + 1 } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + return 0 + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report a conditional return after expression with Elvis operator`() { - val code = """ - fun f() { - fun compute(i: Int): Int? = null - for (i in 1..5) { - compute(i) ?: return - } + @Test + fun `does not report a conditional return after expression with Elvis operator`() { + val code = """ + fun f() { + fun compute(i: Int): Int? = null + for (i in 1..5) { + compute(i) ?: return } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report a conditional continue after expression with Elvis operator`() { - val code = """ - fun f() { - fun compute(i: Int): Int? = null - for (i in 1..5) { - compute(i) ?: continue - } + @Test + fun `does not report a conditional continue after expression with Elvis operator`() { + val code = """ + fun f() { + fun compute(i: Int): Int? = null + for (i in 1..5) { + compute(i) ?: continue } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report a conditional break after expression with Elvis operator`() { - val code = """ - fun f() { - fun compute(i: Int): Int? = null - for (i in 1..5) { - compute(i) ?: break - } + @Test + fun `does not report a conditional break after expression with Elvis operator`() { + val code = """ + fun f() { + fun compute(i: Int): Int? = null + for (i in 1..5) { + compute(i) ?: break } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report a conditional jump in a nested block`() { - val code = """ - fun f() { - for (i in 1..2) { - try { - break - } finally { - } + @Test + fun `does not report a conditional jump in a nested block`() { + val code = """ + fun f() { + for (i in 1..2) { + try { + break + } finally { } } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report a return after a conditional jump`() { - val findings = subject.compileAndLint( - """ - fun f(): Int { - for (i in 0 until 10) { - val a = i * i - if (a < 27) continue - return a - } - return 0 + @Test + fun `does not report a return after a conditional jump`() { + val findings = subject.compileAndLint( + """ + fun f(): Int { + for (i in 0 until 10) { + val a = i * i + if (a < 27) continue + return a } - - fun g(): Int { - for (i in 0 until 10) { - val a = i * i - when { - a < 27 -> continue - } - return a + return 0 + } + + fun g(): Int { + for (i in 0 until 10) { + val a = i * i + when { + a < 27 -> continue } - return 0 + return a } - """ - ) + return 0 + } + """ + ) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnreachableCatchBlockSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnreachableCatchBlockSpec.kt index 749f9ff15f5..98e6a584f32 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnreachableCatchBlockSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnreachableCatchBlockSpec.kt @@ -5,77 +5,73 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class UnreachableCatchBlockSpec(private val env: KotlinCoreEnvironment) { private val subject = UnreachableCatchBlock() - @Nested - inner class `UnreachableCatchBlock rule` { - @Test - fun `reports a unreachable catch block that is after the super class catch block`() { - val code = """ - fun test() { - try { - } catch (t: Throwable) { - } catch (e: Exception) { - } + @Test + fun `reports a unreachable catch block that is after the super class catch block`() { + val code = """ + fun test() { + try { + } catch (t: Throwable) { + } catch (e: Exception) { } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings).hasSourceLocation(4, 7) - } + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings).hasSourceLocation(4, 7) + } - @Test - fun `reports a unreachable catch block that is after the same class catch block`() { - val code = """ - fun test() { - try { - } catch (e: Exception) { - } catch (e: Exception) { - } + @Test + fun `reports a unreachable catch block that is after the same class catch block`() { + val code = """ + fun test() { + try { + } catch (e: Exception) { + } catch (e: Exception) { } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings).hasSourceLocation(4, 7) - } + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings).hasSourceLocation(4, 7) + } - @Test - fun `reports two unreachable catch blocks that is after the super class catch block`() { - val code = """ - fun test() { - try { - } catch (e: RuntimeException) { - } catch (e: IllegalArgumentException) { - } catch (e: IllegalStateException) { - } + @Test + fun `reports two unreachable catch blocks that is after the super class catch block`() { + val code = """ + fun test() { + try { + } catch (e: RuntimeException) { + } catch (e: IllegalArgumentException) { + } catch (e: IllegalStateException) { } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(2) - assertThat(findings).hasSourceLocations( - SourceLocation(4, 7), - SourceLocation(5, 7) - ) - } + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(2) + assertThat(findings).hasSourceLocations( + SourceLocation(4, 7), + SourceLocation(5, 7) + ) + } - @Test - fun `does not report unreachable catch block`() { - val code = """ - fun test() { - try { - } catch (e: IllegalArgumentException) { - } catch (e: IllegalStateException) { - } catch (e: RuntimeException) { - } + @Test + fun `does not report unreachable catch block`() { + val code = """ + fun test() { + try { + } catch (e: IllegalArgumentException) { + } catch (e: IllegalStateException) { + } catch (e: RuntimeException) { } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnreachableCodeSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnreachableCodeSpec.kt index a6b63115e56..e6ab5a6b553 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnreachableCodeSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnreachableCodeSpec.kt @@ -5,173 +5,168 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class UnreachableCodeSpec(private val env: KotlinCoreEnvironment) { private val subject = UnreachableCode(Config.empty) - @Nested - inner class `UnreachableCode rule` { + @Test + fun `reports unreachable code after return`() { + val code = """ + fun f(i: Int) { + if (i == 0) { + return + println() + } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `reports unreachable code after return`() { - val code = """ - fun f(i: Int) { - if (i == 0) { - return - println() - } + @Test + fun `reports unreachable code after return in lambda`() { + val code = """ + fun f(s: String): Boolean { + s.let { + return it.length < 3 + println() } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + return false + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) + } - @Test - fun `reports unreachable code after return in lambda`() { - val code = """ - fun f(s: String): Boolean { - s.let { - return it.length < 3 + @Test + fun `reports unreachable code after return with label`() { + val code = """ + fun f(ints: List): List { + return ints.map f@{ + if (it == 0) { + return@f 0 println() } - return false + return@f 1 } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `reports unreachable code after return with label`() { - val code = """ - fun f(ints: List): List { - return ints.map f@{ - if (it == 0) { - return@f 0 - println() - } - return@f 1 - } + @Test + fun `reports unreachable code after throwing an exception`() { + val code = """ + fun f(i: Int) { + if (i == 0) { + throw IllegalArgumentException() + println() } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `reports unreachable code after throwing an exception`() { - val code = """ - fun f(i: Int) { - if (i == 0) { - throw IllegalArgumentException() - println() - } + @Test + fun `reports unreachable code after break and continue`() { + val code = """ + fun f() { + for (i in 1..2) { + break + println() } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `reports unreachable code after break and continue`() { - val code = """ - fun f() { - for (i in 1..2) { - break - println() - } - for (i in 1..2) { - continue - println() - } + for (i in 1..2) { + continue + println() } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) + } - @Test - fun `does not report reachable code after conditional return with label`() { - val code = """ - fun f(ints: List) { - ints.forEach { - if (it == 0) return@forEach - println() - } + @Test + fun `does not report reachable code after conditional return with label`() { + val code = """ + fun f(ints: List) { + ints.forEach { + if (it == 0) return@forEach + println() } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report reachable code after if`() { - val code = """ - fun f(i: Int) { - if (i == 0) { - println() - } - throw IllegalArgumentException() + @Test + fun `does not report reachable code after if`() { + val code = """ + fun f(i: Int) { + if (i == 0) { + println() } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + throw IllegalArgumentException() + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report reachable code in if body`() { - val code = """ - fun f(i: Int) { - if (i == 0) { - println(i) - throw IllegalArgumentException() - } - println() + @Test + fun `does not report reachable code in if body`() { + val code = """ + fun f(i: Int) { + if (i == 0) { + println(i) + throw IllegalArgumentException() } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + println() + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `reports unreachable code after if expression`() { - val code = """ - fun test(b: Boolean): Int { - if (b) { - return 1 - } else { - return 2 - } - return 0 + @Test + fun `reports unreachable code after if expression`() { + val code = """ + fun test(b: Boolean): Int { + if (b) { + return 1 + } else { + return 2 } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + return 0 + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `reports unreachable code after when expression`() { - val code = """ - enum class E { A, B } - - fun test(e: E): Int { - when (e) { - E.A -> return 1 - E.B -> return 2 - } - return 0 + @Test + fun `reports unreachable code after when expression`() { + val code = """ + enum class E { A, B } + + fun test(e: E): Int { + when (e) { + E.A -> return 1 + E.B -> return 2 } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + return 0 + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `reports unreachable code after try expression`() { - val code = """ - fun test(): Int { - try { - return 1 - } catch (e: Exception) { - throw e - } - return 0 + @Test + fun `reports unreachable code after try expression`() { + val code = """ + fun test(): Int { + try { + return 1 + } catch (e: Exception) { + throw e } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + return 0 + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnsafeCastSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnsafeCastSpec.kt index 0f535fa76e6..f1c4bb6f755 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnsafeCastSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnsafeCastSpec.kt @@ -4,54 +4,49 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class UnsafeCastSpec(private val env: KotlinCoreEnvironment) { private val subject = UnsafeCast() - @Nested - inner class `check safe and unsafe casts` { - - @Test - fun `reports cast that cannot succeed`() { - val code = """ - fun test(s: String) { - println(s as Int) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + @Test + fun `reports cast that cannot succeed`() { + val code = """ + fun test(s: String) { + println(s as Int) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `reports 'safe' cast that cannot succeed`() { - val code = """ - fun test(s: String) { - println((s as? Int) ?: 0) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + @Test + fun `reports 'safe' cast that cannot succeed`() { + val code = """ + fun test(s: String) { + println((s as? Int) ?: 0) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `does not report cast that might succeed`() { - val code = """ - fun test(s: Any) { - println(s as Int) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does not report cast that might succeed`() { + val code = """ + fun test(s: Any) { + println(s as Int) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report 'safe' cast that might succeed`() { - val code = """ - fun test(s: Any) { - println((s as? Int) ?: 0) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does not report 'safe' cast that might succeed`() { + val code = """ + fun test(s: Any) { + println((s as? Int) ?: 0) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnusedUnaryOperatorSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnusedUnaryOperatorSpec.kt index bb85244c6f7..7683fbe216b 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnusedUnaryOperatorSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/UnusedUnaryOperatorSpec.kt @@ -4,126 +4,122 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class UnusedUnaryOperatorSpec(private val env: KotlinCoreEnvironment) { private val subject = UnusedUnaryOperator() - @Nested - inner class `UnusedUnaryOperatorSpec rule` { - @Test - fun `unused plus operator`() { - val code = """ - fun test() { - val x = 1 + 2 - + 3 - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings).hasSourceLocation(3, 9) - assertThat(findings[0]).hasMessage("This '+ 3' is not used") - } + @Test + fun `unused plus operator`() { + val code = """ + fun test() { + val x = 1 + 2 + + 3 + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings).hasSourceLocation(3, 9) + assertThat(findings[0]).hasMessage("This '+ 3' is not used") + } - @Test - fun `unused minus operator`() { - val code = """ - fun test() { - val x = 1 + 2 - - 3 - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings).hasSourceLocation(3, 9) - assertThat(findings[0]).hasMessage("This '- 3' is not used") - } + @Test + fun `unused minus operator`() { + val code = """ + fun test() { + val x = 1 + 2 + - 3 + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings).hasSourceLocation(3, 9) + assertThat(findings[0]).hasMessage("This '- 3' is not used") + } - @Test - fun `unused plus operator in binary expression`() { - val code = """ - fun test() { - val x = 1 + 2 - + 3 + 4 + 5 - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0]).hasMessage("This '+ 3 + 4 + 5' is not used") - } + @Test + fun `unused plus operator in binary expression`() { + val code = """ + fun test() { + val x = 1 + 2 + + 3 + 4 + 5 + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0]).hasMessage("This '+ 3 + 4 + 5' is not used") + } - @Test - fun `used plus operator`() { - val code = """ - fun test() { - val x = (1 + 2 - + 3 + 4 + 5) - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + @Test + fun `used plus operator`() { + val code = """ + fun test() { + val x = (1 + 2 + + 3 + 4 + 5) + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `used minus operator`() { - val code = """ - fun test() { - val x = -1 - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + @Test + fun `used minus operator`() { + val code = """ + fun test() { + val x = -1 + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `used as return value`() { - val code = """ - fun test(): Int { - return -1 - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + @Test + fun `used as return value`() { + val code = """ + fun test(): Int { + return -1 + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `used as value argument`() { - val code = """ - fun foo(x: Int) {} - fun test() { - foo(x = -1) - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + @Test + fun `used as value argument`() { + val code = """ + fun foo(x: Int) {} + fun test() { + foo(x = -1) + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `used as annotation value argument`() { - val code = """ - annotation class Ann(val x: Int) - @Ann(x = -1) - val y = 2 - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + @Test + fun `used as annotation value argument`() { + val code = """ + annotation class Ann(val x: Int) + @Ann(x = -1) + val y = 2 + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `overloaded unary operator`() { - val code = """ - data class Foo(val x: Int) - operator fun Foo.plus(other: Foo) = Foo(this.x + other.x) - operator fun Foo.unaryMinus() = Foo(-x) - fun test() { - val p = Foo(1) + Foo(2) - - Foo(3) - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + @Test + fun `overloaded unary operator`() { + val code = """ + data class Foo(val x: Int) + operator fun Foo.plus(other: Foo) = Foo(this.x + other.x) + operator fun Foo.unaryMinus() = Foo(-x) + fun test() { + val p = Foo(1) + Foo(2) + - Foo(3) + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() } } diff --git a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/WrongEqualsTypeParameterSpec.kt b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/WrongEqualsTypeParameterSpec.kt index 0c42a10e18a..cc0a0acca68 100644 --- a/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/WrongEqualsTypeParameterSpec.kt +++ b/detekt-rules-errorprone/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/WrongEqualsTypeParameterSpec.kt @@ -3,87 +3,82 @@ package io.gitlab.arturbosch.detekt.rules.bugs import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class WrongEqualsTypeParameterSpec { private val subject = WrongEqualsTypeParameter(Config.empty) - @Nested - inner class `WrongEqualsTypeParameter rule` { - - @Test - fun `does not report nullable Any as parameter`() { - val code = """ - class A { - override fun equals(other: Any?): Boolean { - return super.equals(other) - } + @Test + fun `does not report nullable Any as parameter`() { + val code = """ + class A { + override fun equals(other: Any?): Boolean { + return super.equals(other) } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports a String as parameter`() { - val code = """ - class A { - fun equals(other: String): Boolean { - return super.equals(other) - } + @Test + fun `reports a String as parameter`() { + val code = """ + class A { + fun equals(other: String): Boolean { + return super.equals(other) } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report equals() with an additional parameter`() { - val code = """ - class A { - fun equals(other: Any?, i: Int): Boolean { - return super.equals(other) - } + @Test + fun `does not report equals() with an additional parameter`() { + val code = """ + class A { + fun equals(other: Any?, i: Int): Boolean { + return super.equals(other) } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report an overridden equals() with a different signature`() { - val code = """ - interface I { - fun equals(other: Any?, i: Int): Boolean - fun equals(): Boolean + @Test + fun `does not report an overridden equals() with a different signature`() { + val code = """ + interface I { + fun equals(other: Any?, i: Int): Boolean + fun equals(): Boolean + } + + class A : I { + override fun equals(other: Any?, i: Int): Boolean { + return super.equals(other) } - class A : I { - override fun equals(other: Any?, i: Int): Boolean { - return super.equals(other) - } - - override fun equals() = true - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + override fun equals() = true + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report an interface declaration`() { - val code = """ - interface I { - fun equals(other: String) - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report an interface declaration`() { + val code = """ + interface I { + fun equals(other: String) + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report top level functions`() { - val code = """ - fun equals(other: String) {} - fun equals(other: Any?) {} - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report top level functions`() { + val code = """ + fun equals(other: String) {} + fun equals(other: Any?) {} + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ExceptionRaisedInUnexpectedLocationSpec.kt b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ExceptionRaisedInUnexpectedLocationSpec.kt index 44be6fa1af6..fd6b9f82c97 100644 --- a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ExceptionRaisedInUnexpectedLocationSpec.kt +++ b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ExceptionRaisedInUnexpectedLocationSpec.kt @@ -5,51 +5,46 @@ import io.gitlab.arturbosch.detekt.test.TestConfig import io.gitlab.arturbosch.detekt.test.compileAndLint import io.gitlab.arturbosch.detekt.test.lint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ExceptionRaisedInUnexpectedLocationSpec { val subject = ExceptionRaisedInUnexpectedLocation() - @Nested - inner class `ExceptionRaisedInUnexpectedLocation rule` { - - @Test - fun `reports methods raising an unexpected exception`() { - val path = resourceAsPath("ExceptionRaisedInMethodsPositive.kt") - assertThat(subject.lint(path)).hasSize(5) - } + @Test + fun `reports methods raising an unexpected exception`() { + val path = resourceAsPath("ExceptionRaisedInMethodsPositive.kt") + assertThat(subject.lint(path)).hasSize(5) + } - @Test - fun `does not report methods raising no exception`() { - val path = resourceAsPath("ExceptionRaisedInMethodsNegative.kt") - assertThat(subject.lint(path)).isEmpty() - } + @Test + fun `does not report methods raising no exception`() { + val path = resourceAsPath("ExceptionRaisedInMethodsNegative.kt") + assertThat(subject.lint(path)).isEmpty() + } - @Test - fun `reports the configured method`() { - val config = TestConfig(mapOf("methodNames" to listOf("toDo", "todo2"))) - val findings = ExceptionRaisedInUnexpectedLocation(config).compileAndLint( - """ - fun toDo() { - throw IllegalStateException() - } - """ - ) - assertThat(findings).hasSize(1) + @Test + fun `reports the configured method`() { + val config = TestConfig(mapOf("methodNames" to listOf("toDo", "todo2"))) + val findings = ExceptionRaisedInUnexpectedLocation(config).compileAndLint( + """ + fun toDo() { + throw IllegalStateException() } + """ + ) + assertThat(findings).hasSize(1) + } - @Test - fun `reports the configured method with String`() { - val config = TestConfig(mapOf("methodNames" to "toDo,todo2")) - val findings = ExceptionRaisedInUnexpectedLocation(config).compileAndLint( - """ - fun toDo() { - throw IllegalStateException() - } - """ - ) - assertThat(findings).hasSize(1) + @Test + fun `reports the configured method with String`() { + val config = TestConfig(mapOf("methodNames" to "toDo,todo2")) + val findings = ExceptionRaisedInUnexpectedLocation(config).compileAndLint( + """ + fun toDo() { + throw IllegalStateException() } + """ + ) + assertThat(findings).hasSize(1) } } diff --git a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/InstanceOfCheckForExceptionSpec.kt b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/InstanceOfCheckForExceptionSpec.kt index 80c67b8ba19..a9bf4dc029d 100644 --- a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/InstanceOfCheckForExceptionSpec.kt +++ b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/InstanceOfCheckForExceptionSpec.kt @@ -4,77 +4,72 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class InstanceOfCheckForExceptionSpec(val env: KotlinCoreEnvironment) { val subject = InstanceOfCheckForException() - @Nested - inner class `InstanceOfCheckForException rule` { - - @Test - fun `has is and as checks`() { - val code = """ - fun x() { - try { - } catch(e: Exception) { - if (e is IllegalArgumentException || (e as IllegalArgumentException) != null) { - return - } + @Test + fun `has is and as checks`() { + val code = """ + fun x() { + try { + } catch(e: Exception) { + if (e is IllegalArgumentException || (e as IllegalArgumentException) != null) { + return } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) + } - @Test - fun `has nested is and as checks`() { - val code = """ - fun x() { - try { - } catch(e: Exception) { - if (1 == 1) { - val b = e !is IllegalArgumentException || (e as IllegalArgumentException) != null - } + @Test + fun `has nested is and as checks`() { + val code = """ + fun x() { + try { + } catch(e: Exception) { + if (1 == 1) { + val b = e !is IllegalArgumentException || (e as IllegalArgumentException) != null } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) + } - @Test - fun `has no instance of check`() { - val code = """ - fun x() { - try { - } catch(e: Exception) { - val s = "" - if (s is String || (s as String) != null) { - val other: Exception? = null - val b = other !is IllegalArgumentException || (other as IllegalArgumentException) != null - } + @Test + fun `has no instance of check`() { + val code = """ + fun x() { + try { + } catch(e: Exception) { + val s = "" + if (s is String || (s as String) != null) { + val other: Exception? = null + val b = other !is IllegalArgumentException || (other as IllegalArgumentException) != null } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `has no checks for the subtype of an exception`() { - val code = """ - interface I - - fun foo() { - try { - } catch(e: Exception) { - if (e is I || (e as I) != null) { - } + @Test + fun `has no checks for the subtype of an exception`() { + val code = """ + interface I + + fun foo() { + try { + } catch(e: Exception) { + if (e is I || (e as I) != null) { } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } } diff --git a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/NotImplementedDeclarationSpec.kt b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/NotImplementedDeclarationSpec.kt index 622912b87d6..1cb09a0646b 100644 --- a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/NotImplementedDeclarationSpec.kt +++ b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/NotImplementedDeclarationSpec.kt @@ -2,45 +2,40 @@ package io.gitlab.arturbosch.detekt.rules.exceptions import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class NotImplementedDeclarationSpec { val subject = NotImplementedDeclaration() - @Nested - inner class `NotImplementedDeclaration rule` { - - @Test - fun `reports NotImplementedErrors`() { - val code = """ - fun f() { - if (1 == 1) throw NotImplementedError() - throw NotImplementedError() - } - """ - assertThat(subject.compileAndLint(code)).hasSize(2) + @Test + fun `reports NotImplementedErrors`() { + val code = """ + fun f() { + if (1 == 1) throw NotImplementedError() + throw NotImplementedError() } + """ + assertThat(subject.compileAndLint(code)).hasSize(2) + } - @Test - fun `reports TODO method calls`() { - val code = """ - fun f() { - TODO("not implemented") - TODO() - } - """ - assertThat(subject.compileAndLint(code)).hasSize(2) + @Test + fun `reports TODO method calls`() { + val code = """ + fun f() { + TODO("not implemented") + TODO() } + """ + assertThat(subject.compileAndLint(code)).hasSize(2) + } - @Test - fun `does not report TODO comments`() { - val code = """ - fun f() { - // TODO - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() + @Test + fun `does not report TODO comments`() { + val code = """ + fun f() { + // TODO } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ObjectExtendsThrowableSpec.kt b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ObjectExtendsThrowableSpec.kt index 67742c104e9..4a6a7747927 100644 --- a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ObjectExtendsThrowableSpec.kt +++ b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ObjectExtendsThrowableSpec.kt @@ -4,7 +4,6 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest @@ -12,135 +11,131 @@ class ObjectExtendsThrowableSpec(val env: KotlinCoreEnvironment) { val subject = ObjectExtendsThrowable() - @Nested - inner class `ObjectExtendsThrowable rule` { - - @Test - fun `reports top-level objects that extend Throwable`() { - val code = """ - object BanException : Throwable() - object AuthException : RuntimeException() - object ReportedException : Exception() - object FatalException : Error() - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(4) - } + @Test + fun `reports top-level objects that extend Throwable`() { + val code = """ + object BanException : Throwable() + object AuthException : RuntimeException() + object ReportedException : Exception() + object FatalException : Error() + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(4) + } - @Test - fun `reports object subtype of sealed class that extends Throwable`() { - val code = """ - sealed class DomainException : RuntimeException() { - data class Exception1(val prop1: String, val prop2: Boolean) : DomainException() - class Exception2 : DomainException() - object Exception3 : DomainException() - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + @Test + fun `reports object subtype of sealed class that extends Throwable`() { + val code = """ + sealed class DomainException : RuntimeException() { + data class Exception1(val prop1: String, val prop2: Boolean) : DomainException() + class Exception2 : DomainException() + object Exception3 : DomainException() } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `reports object that extends custom exception`() { - val code = """ - object ObjectCustomException : CustomException("singleton custom exception") + @Test + fun `reports object that extends custom exception`() { + val code = """ + object ObjectCustomException : CustomException("singleton custom exception") - open class CustomException(message: String) : RuntimeException(message) - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + open class CustomException(message: String) : RuntimeException(message) + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `reports companion objects that extend Throwable`() { - val code = """ - class Test1 { - companion object : Throwable() { - const val NAME = "Test 1" - } + @Test + fun `reports companion objects that extend Throwable`() { + val code = """ + class Test1 { + companion object : Throwable() { + const val NAME = "Test 1" } + } - class Test2 { - companion object : Exception() { - const val NAME = "Test 2" - } + class Test2 { + companion object : Exception() { + const val NAME = "Test 2" } + } - class Test3 { - companion object Named : Error() { - const val NAME = "Test 3" - } + class Test3 { + companion object Named : Error() { + const val NAME = "Test 3" } + } - class Test4 { - companion object Named : RuntimeException() { - const val NAME = "Test 4" - } + class Test4 { + companion object Named : RuntimeException() { + const val NAME = "Test 4" } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(4) } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(4) + } - @Test - fun `does not report objects that do not extend Throwable`() { - val code = """ - object BanException - object AuthException : CustomException(message = "Authentication failed!") - - sealed class DomainException { - object Exception1 : DomainException() - object Exception2 : DomainException() - object Exception3 : DomainException() - } + @Test + fun `does not report objects that do not extend Throwable`() { + val code = """ + object BanException + object AuthException : CustomException(message = "Authentication failed!") - open class CustomException(message: String) - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + sealed class DomainException { + object Exception1 : DomainException() + object Exception2 : DomainException() + object Exception3 : DomainException() } - @Test - fun `does not report companion objects that do not extend Throwable`() { - val code = """ - class Test1 { - companion object { - const val NAME = "Test 1" - } - } + open class CustomException(message: String) + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - class Test2 { - companion object Named { - const val NAME = "Test 3" - } + @Test + fun `does not report companion objects that do not extend Throwable`() { + val code = """ + class Test1 { + companion object { + const val NAME = "Test 1" } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } - @Test - fun `does not report non-objects that do extend Throwable`() { - val code = """ - class BanException : Throwable() - data class AuthException(val code: Int) : RuntimeException() - class ReportedException : Exception() - class FatalException : Error() - class ObjectCustomException : CustomException("singleton custom exception") - - sealed class DomainException : RuntimeException() { - data class Exception1(val prop1: String, val prop2: Boolean) : DomainException() - class Exception2 : DomainException() - class Exception3 : DomainException() + class Test2 { + companion object Named { + const val NAME = "Test 3" } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - open class CustomException(message: String) - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + @Test + fun `does not report non-objects that do extend Throwable`() { + val code = """ + class BanException : Throwable() + data class AuthException(val code: Int) : RuntimeException() + class ReportedException : Exception() + class FatalException : Error() + class ObjectCustomException : CustomException("singleton custom exception") + + sealed class DomainException : RuntimeException() { + data class Exception1(val prop1: String, val prop2: Boolean) : DomainException() + class Exception2 : DomainException() + class Exception3 : DomainException() } - @Test - fun `does not report an anonymous object that extends Throwable`() { - val code = """ - val exception = object : AbstractCustomException() {} + open class CustomException(message: String) + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `does not report an anonymous object that extends Throwable`() { + val code = """ + val exception = object : AbstractCustomException() {} - abstract class AbstractCustomException : RuntimeException() - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + abstract class AbstractCustomException : RuntimeException() + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } } diff --git a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/PrintStackTraceSpec.kt b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/PrintStackTraceSpec.kt index e04c449f34c..1b69cc52508 100644 --- a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/PrintStackTraceSpec.kt +++ b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/PrintStackTraceSpec.kt @@ -9,56 +9,52 @@ class PrintStackTraceSpec { val subject = PrintStackTrace() @Nested - inner class `print stack trace rule` { - - @Nested - inner class `catch clauses with printStacktrace methods` { - - @Test - fun `prints a stacktrace`() { - val code = """ - fun x() { - try { - } catch (e: Exception) { - e.printStackTrace() - } + inner class `catch clauses with printStacktrace methods` { + + @Test + fun `prints a stacktrace`() { + val code = """ + fun x() { + try { + } catch (e: Exception) { + e.printStackTrace() } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not print a stacktrace`() { - val code = """ - fun x() { - try { - } catch (e: Exception) { - e.fillInStackTrace() - val msg = e.message - fun printStackTrace() {} - printStackTrace() - } + @Test + fun `does not print a stacktrace`() { + val code = """ + fun x() { + try { + } catch (e: Exception) { + e.fillInStackTrace() + val msg = e.message + fun printStackTrace() {} + printStackTrace() } - """ - assertThat(subject.compileAndLint(code)).isEmpty() } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } + } - @Nested - inner class `a stacktrace printed by a thread` { + @Nested + inner class `a stacktrace printed by a thread` { - @Test - fun `prints one`() { - val code = """ - fun x() { - Thread.dumpStack() + @Test + fun `prints one`() { + val code = """ + fun x() { + Thread.dumpStack() - fun dumpStack() {} - dumpStack() - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) + fun dumpStack() {} + dumpStack() } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) } } } diff --git a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/RethrowCaughtExceptionSpec.kt b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/RethrowCaughtExceptionSpec.kt index c5253f48ad9..3d971d7fcbf 100644 --- a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/RethrowCaughtExceptionSpec.kt +++ b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/RethrowCaughtExceptionSpec.kt @@ -2,213 +2,208 @@ package io.gitlab.arturbosch.detekt.rules.exceptions import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class RethrowCaughtExceptionSpec { val subject = RethrowCaughtException() - @Nested - inner class `RethrowCaughtException rule` { + @Test + fun `reports when the same exception is rethrown`() { + val code = """ + fun f() { + try { + } catch (e: IllegalStateException) { + throw e + } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports when the same exception is rethrown`() { - val code = """ + @Test + fun `does not report when the other exception is rethrown with same name`() { + val code = """ + class A { + private lateinit var e: Exception fun f() { try { } catch (e: IllegalStateException) { - throw e + throw this.e } } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report when the other exception is rethrown with same name`() { - val code = """ - class A { - private lateinit var e: Exception - fun f() { - try { - } catch (e: IllegalStateException) { - throw this.e - } - } + @Test + fun `reports when the same exception succeeded by dead code is rethrown`() { + val code = """ + fun f() { + try { + } catch (e: IllegalStateException) { + throw e + print("log") } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports when the same exception succeeded by dead code is rethrown`() { - val code = """ - fun f() { + @Test + fun `reports when the same nested exception is rethrown`() { + val code = """ + fun f() { + try { + } catch (outer: IllegalStateException) { try { - } catch (e: IllegalStateException) { - throw e - print("log") + } catch (inner: IllegalStateException) { + throw inner } } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports when the same nested exception is rethrown`() { - val code = """ - fun f() { - try { - } catch (outer: IllegalStateException) { - try { - } catch (inner: IllegalStateException) { - throw inner - } - } + @Test + fun `does not report a wrapped exception`() { + val code = """ + fun f() { + try { + } catch (e: IllegalStateException) { + throw IllegalArgumentException(e) } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report a wrapped exception`() { - val code = """ - fun f() { - try { - } catch (e: IllegalStateException) { - throw IllegalArgumentException(e) - } + @Test + fun `does not report wrapped exceptions`() { + val code = """ + fun f() { + try { + } catch (e: IllegalStateException) { + throw IllegalArgumentException(e) + } catch (f: Exception) { + throw IllegalArgumentException("msg", f) } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report wrapped exceptions`() { - val code = """ - fun f() { - try { - } catch (e: IllegalStateException) { - throw IllegalArgumentException(e) - } catch (f: Exception) { - throw IllegalArgumentException("msg", f) - } + @Test + fun `does not report logged exceptions`() { + val code = """ + fun f() { + try { + } catch (e: IllegalStateException) { + print(e) + } catch (f: Exception) { + print(f) + throw IllegalArgumentException("msg", f) } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report logged exceptions`() { - val code = """ - fun f() { - try { - } catch (e: IllegalStateException) { - print(e) - } catch (f: Exception) { - print(f) - throw IllegalArgumentException("msg", f) - } + @Test + fun `does not report when taking specific actions before throwing the exception`() { + val code = """ + fun f() { + try { + } catch (e: IllegalStateException) { + print("log") // taking specific action before throwing the exception + throw e } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report when taking specific actions before throwing the exception`() { - val code = """ - fun f() { - try { - } catch (e: IllegalStateException) { - print("log") // taking specific action before throwing the exception - throw e - } - try { - } catch (e: IllegalStateException) { - print(e.message) // taking specific action before throwing the exception - throw e - } + try { + } catch (e: IllegalStateException) { + print(e.message) // taking specific action before throwing the exception + throw e } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report when exception rethrown only in first catch`() { - val code = """ - fun f() { - try { - } catch (e: IllegalStateException) { - throw e - } catch (e: Exception) { - print(e) - } + @Test + fun `does not report when exception rethrown only in first catch`() { + val code = """ + fun f() { + try { + } catch (e: IllegalStateException) { + throw e + } catch (e: Exception) { + print(e) } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report when some work is done in last catch`() { - val code = """ - fun f() { - try { - } catch (e: IllegalStateException) { - throw e - } catch (e: Exception) { - print(e) - throw e - } + @Test + fun `does not report when some work is done in last catch`() { + val code = """ + fun f() { + try { + } catch (e: IllegalStateException) { + throw e + } catch (e: Exception) { + print(e) + throw e } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report when there is no catch clauses`() { - val code = """ - fun f() { - try { - } finally { - } + @Test + fun `does not report when there is no catch clauses`() { + val code = """ + fun f() { + try { + } finally { } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports when exception rethrown in last catch`() { - val code = """ - fun f() { - try { - } catch (e: IllegalStateException) { - print(e) - } catch (e: Exception) { - throw e - } + @Test + fun `reports when exception rethrown in last catch`() { + val code = """ + fun f() { + try { + } catch (e: IllegalStateException) { + print(e) + } catch (e: Exception) { + throw e } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports 2 violations for each catch`() { - val code = """ - fun f() { - try { - } catch (e: IllegalStateException) { - throw e - } catch (e: Exception) { - // some comment - throw e - } + @Test + fun `reports 2 violations for each catch`() { + val code = """ + fun f() { + try { + } catch (e: IllegalStateException) { + throw e + } catch (e: Exception) { + // some comment + throw e } - """ - val result = subject.compileAndLint(code) - assertThat(result).hasSize(2) - // ensure correct violation order - assertThat(result[0].startPosition.line == 4).isTrue - assertThat(result[1].startPosition.line == 7).isTrue - } + } + """ + val result = subject.compileAndLint(code) + assertThat(result).hasSize(2) + // ensure correct violation order + assertThat(result[0].startPosition.line == 4).isTrue + assertThat(result[1].startPosition.line == 7).isTrue } } diff --git a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ReturnFromFinallySpec.kt b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ReturnFromFinallySpec.kt index 7deaa1d3552..d66894ae092 100644 --- a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ReturnFromFinallySpec.kt +++ b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ReturnFromFinallySpec.kt @@ -13,273 +13,268 @@ class ReturnFromFinallySpec(val env: KotlinCoreEnvironment) { val subject = ReturnFromFinally() - @Nested - inner class `ReturnFromFinally rule` { - - @Nested - inner class `a finally block with a return statement` { - val code = """ - fun x() { - try { - } finally { - return - } + inner class `a finally block with a return statement` { + val code = """ + fun x() { + try { + } finally { + return } - """ + } + """ + + @Test + fun `should report`() { + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } + } - @Test - fun `should report`() { - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) + @Nested + inner class `a finally block with no return statement` { + val code = """ + fun x() { + try { + } finally { + } } + """ + + @Test + fun `should not report`() { + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `a finally block with no return statement` { - val code = """ - fun x() { - try { - } finally { + @Nested + inner class `a finally block with a nested return statement` { + val code = """ + fun x() { + try { + } finally { + if (1 == 1) { + return } } - """ - - @Test - fun `should not report`() { - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() } + """ + + @Test + fun `should report`() { + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) } + } - @Nested - inner class `a finally block with a nested return statement` { - val code = """ - fun x() { - try { - } finally { - if (1 == 1) { - return - } + @Nested + inner class `a finally block with a return in an inner function` { + val code = """ + fun x() { + try { + } finally { + fun y() { + return } + y() } - """ - - @Test - fun `should report`() { - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) } + """ + + @Test + fun `should not report`() { + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `a finally block with a return in an inner function` { - val code = """ - fun x() { + @Nested + inner class `a finally block with a return as labelled expression` { + val code = """ + fun x() { + label@{ try { } finally { - fun y() { - return - } - y() + return@label } } - """ - - @Test - fun `should not report`() { - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() } + """ + + @Test + fun `should report when ignoreLabeled is false`() { + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } + + @Test + fun `should not report when ignoreLabeled is true`() { + val config = TestConfig(mapOf("ignoreLabeled" to "true")) + val findings = ReturnFromFinally(config).compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `a finally block with a return as labelled expression` { + @Nested + inner class `a finally block as expression for property` { + @Test + fun `should report`() { val code = """ - fun x() { - label@{ - try { - } finally { - return@label - } - } + val expression = try { + "try" + } catch (e: Exception) { + "exception" + } finally { + "finally" } """ - @Test - fun `should report when ignoreLabeled is false`() { - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + val finding = subject.compileAndLintWithContext(env, code) - @Test - fun `should not report when ignoreLabeled is true`() { - val config = TestConfig(mapOf("ignoreLabeled" to "true")) - val findings = ReturnFromFinally(config).compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + assertThat(finding).hasSize(1) } + } - @Nested - inner class `a finally block as expression for property` { - @Test - fun `should report`() { - val code = """ - val expression = try { - "try" - } catch (e: Exception) { - "exception" - } finally { - "finally" - } - """ + @Nested + inner class `a finally block as expression for method` { + @Test + fun `should report`() { + val code = """ + fun expression() = try { + "try" + } catch (e: Exception) { + "exception" + } finally { + "finally" + } + """ - val finding = subject.compileAndLintWithContext(env, code) + val finding = subject.compileAndLintWithContext(env, code) - assertThat(finding).hasSize(1) - } + assertThat(finding).hasSize(1) } + } - @Nested - inner class `a finally block as expression for method` { - @Test - fun `should report`() { - val code = """ - fun expression() = try { - "try" - } catch (e: Exception) { - "exception" - } finally { - "finally" - } - """ + @Nested + inner class `when a finally block called method that return value` { + @Test + fun `should report`() { + val code = """ + fun expression() = try { + "try" + } catch (e: Exception) { + "exception" + } finally { + compute() + } + + fun compute(): String = "value" + """ - val finding = subject.compileAndLintWithContext(env, code) + val finding = subject.compileAndLintWithContext(env, code) - assertThat(finding).hasSize(1) - } + assertThat(finding).hasSize(1) } + } - @Nested - inner class `when a finally block called method that return value` { - @Test - fun `should report`() { - val code = """ - fun expression() = try { - "try" - } catch (e: Exception) { - "exception" - } finally { - compute() - } - - fun compute(): String = "value" - """ - - val finding = subject.compileAndLintWithContext(env, code) + @Nested + inner class `when finally block absents in expression for property` { + @Test + fun `shouldn't report`() { + val code = """ + val expression = try { + "try" + } catch (e: Exception) { + "exception" + } + """ - assertThat(finding).hasSize(1) - } - } + val finding = subject.compileAndLintWithContext(env, code) - @Nested - inner class `when finally block absents in expression for property` { - @Test - fun `shouldn't report`() { - val code = """ - val expression = try { - "try" - } catch (e: Exception) { - "exception" - } - """ - - val finding = subject.compileAndLintWithContext(env, code) - - assertThat(finding).hasSize(0) - } + assertThat(finding).hasSize(0) } + } - @Nested - inner class `when finally block absents in expression for method` { + @Nested + inner class `when finally block absents in expression for method` { - @Test - fun `shouldn't report`() { - val code = """ - fun expression() = try { - "try" - } catch (e: Exception) { - "exception" - } - """ + @Test + fun `shouldn't report`() { + val code = """ + fun expression() = try { + "try" + } catch (e: Exception) { + "exception" + } + """ - val finding = subject.compileAndLintWithContext(env, code) + val finding = subject.compileAndLintWithContext(env, code) - assertThat(finding).hasSize(0) - } + assertThat(finding).hasSize(0) } + } - @Nested - inner class `when try catch finally block is independent` { - @Test - fun `shouldn't report`() { - val code = """ - fun expression() { - try { - "try" - } catch (e: Exception) { - "exception" - } finally { - "finally" - } + @Nested + inner class `when try catch finally block is independent` { + @Test + fun `shouldn't report`() { + val code = """ + fun expression() { + try { + "try" + } catch (e: Exception) { + "exception" + } finally { + "finally" } - """ + } + """ - val finding = subject.compileAndLintWithContext(env, code) + val finding = subject.compileAndLintWithContext(env, code) - assertThat(finding).hasSize(0) - } + assertThat(finding).hasSize(0) } + } - @Nested - inner class `when finally block doesn't contain return value` { - @Test - fun `shouldn't report`() { - val code = """ - val expression = try { - "try" - } catch (e: Exception) { - "exception" - } finally { - println("finally") - } - """ + @Nested + inner class `when finally block doesn't contain return value` { + @Test + fun `shouldn't report`() { + val code = """ + val expression = try { + "try" + } catch (e: Exception) { + "exception" + } finally { + println("finally") + } + """ - val finding = subject.compileAndLintWithContext(env, code) + val finding = subject.compileAndLintWithContext(env, code) - assertThat(finding).hasSize(0) - } + assertThat(finding).hasSize(0) } + } - @Nested - inner class `when return value in finally block is property` { - @Test - fun `should report`() { - val code = """ - val property: String = "property" - val expression = try { - "try" - } catch (e: Exception) { - "exception" - } finally { - println("finally") - property - } - """ + @Nested + inner class `when return value in finally block is property` { + @Test + fun `should report`() { + val code = """ + val property: String = "property" + val expression = try { + "try" + } catch (e: Exception) { + "exception" + } finally { + println("finally") + property + } + """ - val finding = subject.compileAndLintWithContext(env, code) + val finding = subject.compileAndLintWithContext(env, code) - assertThat(finding).hasSize(1) - } + assertThat(finding).hasSize(1) } } } diff --git a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/SwallowedExceptionSpec.kt b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/SwallowedExceptionSpec.kt index 48b04332b21..e1b985a6b46 100644 --- a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/SwallowedExceptionSpec.kt +++ b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/SwallowedExceptionSpec.kt @@ -11,315 +11,303 @@ import org.junit.jupiter.params.provider.MethodSource class SwallowedExceptionSpec { val subject = SwallowedException() - @Nested - inner class `SwallowedException rule` { + @Test + fun `reports a swallowed exception`() { + val code = """ + fun f() { + try { + } catch (e: Exception) { + throw IllegalArgumentException() + } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports a swallowed exception`() { - val code = """ - fun f() { - try { - } catch (e: Exception) { - throw IllegalArgumentException() - } + @Test + fun `reports swallowed exceptions only using exception strings`() { + val code = """ + fun f() { + try { + } catch (e: IllegalStateException) { + throw IllegalArgumentException(e.message) + } catch (f: Exception) { + throw Exception(IllegalArgumentException(f.toString())) } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(2) + } - @Test - fun `reports swallowed exceptions only using exception strings`() { - val code = """ - fun f() { - try { - } catch (e: IllegalStateException) { - throw IllegalArgumentException(e.message) - } catch (f: Exception) { - throw Exception(IllegalArgumentException(f.toString())) - } + @Test + fun `reports swallowed exceptions only using exception strings via variables`() { + val code = """ + fun f() { + try { + } catch (e: IllegalStateException) { + val message = e.message + throw IllegalArgumentException(message) + } catch (f: Exception) { + val message = f.toString() + throw Exception(IllegalArgumentException(message)) } - """ - assertThat(subject.compileAndLint(code)).hasSize(2) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(2) + } - @Test - fun `reports swallowed exceptions only using exception strings via variables`() { - val code = """ - fun f() { - try { - } catch (e: IllegalStateException) { + @Test + fun `reports swallowed exceptions only using exception strings via variables in 'if' block`() { + val code = """ + fun f() { + try { + } catch (e: IllegalStateException) { + if (true) { val message = e.message throw IllegalArgumentException(message) - } catch (f: Exception) { - val message = f.toString() + } + } catch (f: Exception) { + val message = f.toString() + if (true) { throw Exception(IllegalArgumentException(message)) } } - """ - assertThat(subject.compileAndLint(code)).hasSize(2) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(2) + } - @Test - fun `reports swallowed exceptions only using exception strings via variables in 'if' block`() { - val code = """ - fun f() { - try { - } catch (e: IllegalStateException) { - if (true) { - val message = e.message - throw IllegalArgumentException(message) - } - } catch (f: Exception) { - val message = f.toString() - if (true) { - throw Exception(IllegalArgumentException(message)) - } + @Test + fun `reports swallowed exceptions when it has multiple throw expressions`() { + val code = """ + fun f(condition: Boolean) { + try { + println() + } catch (e: IllegalStateException) { + if (condition) { + throw IllegalArgumentException(e.message) } + throw IllegalArgumentException(e) } - """ - assertThat(subject.compileAndLint(code)).hasSize(2) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports swallowed exceptions when it has multiple throw expressions`() { - val code = """ - fun f(condition: Boolean) { - try { - println() - } catch (e: IllegalStateException) { - if (condition) { - throw IllegalArgumentException(e.message) - } + @Test + fun `reports swallowed exceptions when it has multiple throw expressions 2`() { + val code = """ + fun f(condition: Boolean) { + try { + println() + } catch (e: IllegalStateException) { + if (condition) { throw IllegalArgumentException(e) } + throw IllegalArgumentException(e.message) } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports swallowed exceptions when it has multiple throw expressions 2`() { - val code = """ - fun f(condition: Boolean) { + @Test + fun `reports nested swallowed exceptions`() { + val code = """ + fun f(condition: Boolean) { + try { + println() + } catch (e: IllegalStateException) { try { - println() - } catch (e: IllegalStateException) { - if (condition) { - throw IllegalArgumentException(e) - } - throw IllegalArgumentException(e.message) + } catch (nested: Exception) { + throw IllegalArgumentException() } + throw IllegalArgumentException(e) } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } + + @Test + fun `reports a swallowed exception that is not logged`() { + val code = """ + fun f() { + try { + } catch (e: Exception) { + println() + } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } + + @Nested + inner class `when given listOf(IllegalArgumentException) ignores given exception types config` { + val ignoredExceptionValue = listOf("IllegalArgumentException") + + val config = + TestConfig("ignoredExceptionTypes" to ignoredExceptionValue) + + val rule = SwallowedException(config) @Test - fun `reports nested swallowed exceptions`() { + fun `ignores given exception type in configuration`() { val code = """ - fun f(condition: Boolean) { - try { - println() - } catch (e: IllegalStateException) { - try { - } catch (nested: Exception) { - throw IllegalArgumentException() - } - throw IllegalArgumentException(e) - } + fun f() { + try { + } catch (e: IllegalArgumentException) { } + } """ - assertThat(subject.compileAndLint(code)).hasSize(1) + assertThat(rule.compileAndLint(code)).isEmpty() } @Test - fun `reports a swallowed exception that is not logged`() { + fun `reports exception type that is missing in the configuration`() { val code = """ - fun f() { - try { - } catch (e: Exception) { - println() - } + fun f() { + try { + } catch (e: Exception) { } + } """ - assertThat(subject.compileAndLint(code)).hasSize(1) + assertThat(rule.compileAndLint(code)).hasSize(1) } + } - @Nested - inner class `when given listOf(IllegalArgumentException)` { - val ignoredExceptionValue = listOf("IllegalArgumentException") - - @Nested - inner class `ignores given exception types config` { - - val config = - TestConfig("ignoredExceptionTypes" to ignoredExceptionValue) + @Nested + inner class `when given IllegalArgumentException ignores given exception types config` { + val ignoredExceptionValue = "IllegalArgumentException" - val rule = SwallowedException(config) + val config = + TestConfig("ignoredExceptionTypes" to ignoredExceptionValue) - @Test - fun `ignores given exception type in configuration`() { - val code = """ - fun f() { - try { - } catch (e: IllegalArgumentException) { - } - } - """ - assertThat(rule.compileAndLint(code)).isEmpty() - } + val rule = SwallowedException(config) - @Test - fun `reports exception type that is missing in the configuration`() { - val code = """ - fun f() { - try { - } catch (e: Exception) { - } - } - """ - assertThat(rule.compileAndLint(code)).hasSize(1) + @Test + fun `ignores given exception type in configuration`() { + val code = """ + fun f() { + try { + } catch (e: IllegalArgumentException) { } } + """ + assertThat(rule.compileAndLint(code)).isEmpty() } - @Nested - inner class `when given IllegalArgumentException` { - val ignoredExceptionValue = "IllegalArgumentException" - - @Nested - inner class `ignores given exception types config` { - - val config = - TestConfig("ignoredExceptionTypes" to ignoredExceptionValue) - - val rule = SwallowedException(config) - - @Test - fun `ignores given exception type in configuration`() { - val code = """ - fun f() { - try { - } catch (e: IllegalArgumentException) { - } - } - """ - assertThat(rule.compileAndLint(code)).isEmpty() - } - - @Test - fun `reports exception type that is missing in the configuration`() { - val code = """ - fun f() { - try { - } catch (e: Exception) { - } - } - """ - assertThat(rule.compileAndLint(code)).hasSize(1) + @Test + fun `reports exception type that is missing in the configuration`() { + val code = """ + fun f() { + try { + } catch (e: Exception) { } } + """ + assertThat(rule.compileAndLint(code)).hasSize(1) } + } - @Nested - inner class `ignores given exception name config` { - - val config = TestConfig(mapOf("allowedExceptionNameRegex" to "myIgnore")) - val rule = SwallowedException(config) - - @Test - fun `ignores given exception name`() { - val code = """ - fun f() { - try { - } catch (myIgnore: IllegalArgumentException) { - } - } - """ - assertThat(rule.compileAndLint(code)).isEmpty() - } + @Nested + inner class `ignores given exception name config` { - @Test - fun `reports exception name`() { - val code = """ - fun f() { - try { - } catch (e: IllegalArgumentException) { - } - } - """ - assertThat(rule.compileAndLint(code)).hasSize(1) - } - } + val config = TestConfig(mapOf("allowedExceptionNameRegex" to "myIgnore")) + val rule = SwallowedException(config) @Test - fun `does not report wrapped exceptions`() { + fun `ignores given exception name`() { val code = """ fun f() { try { - } catch (e: IllegalStateException) { - throw IllegalArgumentException(e.message, e) - } catch (e: Exception) { - throw IllegalArgumentException(e) + } catch (myIgnore: IllegalArgumentException) { } } """ - assertThat(subject.compileAndLint(code)).isEmpty() + assertThat(rule.compileAndLint(code)).isEmpty() } @Test - fun `does not report used exception variables`() { + fun `reports exception name`() { val code = """ fun f() { try { } catch (e: IllegalArgumentException) { - print(e) - } catch (e: Exception) { - print(e.message) } } """ - assertThat(subject.compileAndLint(code)).isEmpty() + assertThat(rule.compileAndLint(code)).hasSize(1) } + } - @ParameterizedTest(name = "ignores {0} in the catch clause by default") - @MethodSource("io.gitlab.arturbosch.detekt.rules.exceptions.SwallowedException#getEXCEPTIONS_IGNORED_BY_DEFAULT") - fun `ignores $exceptionName in the catch clause by default`(exceptionName: String) { - val code = """ - import java.net.MalformedURLException - import java.text.ParseException + @Test + fun `does not report wrapped exceptions`() { + val code = """ + fun f() { + try { + } catch (e: IllegalStateException) { + throw IllegalArgumentException(e.message, e) + } catch (e: Exception) { + throw IllegalArgumentException(e) + } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - fun f() { - try { - } catch (e: $exceptionName) { - throw Exception() - } + @Test + fun `does not report used exception variables`() { + val code = """ + fun f() { + try { + } catch (e: IllegalArgumentException) { + print(e) + } catch (e: Exception) { + print(e.message) } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @ParameterizedTest(name = "ignores {0} in the catch body by default") - @MethodSource("io.gitlab.arturbosch.detekt.rules.exceptions.SwallowedException#getEXCEPTIONS_IGNORED_BY_DEFAULT") - fun `ignores $exceptionName in the catch body by default`(exceptionName: String) { - val exceptionInstantiation = if (exceptionName == "ParseException") { - "$exceptionName(\"\", 0)" - } else { - "$exceptionName(\"\")" + @ParameterizedTest(name = "ignores {0} in the catch clause by default") + @MethodSource("io.gitlab.arturbosch.detekt.rules.exceptions.SwallowedException#getEXCEPTIONS_IGNORED_BY_DEFAULT") + fun `ignores $exceptionName in the catch clause by default`(exceptionName: String) { + val code = """ + import java.net.MalformedURLException + import java.text.ParseException + + fun f() { + try { + } catch (e: $exceptionName) { + throw Exception() + } } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - val code = """ - import java.net.MalformedURLException - import java.text.ParseException + @ParameterizedTest(name = "ignores {0} in the catch body by default") + @MethodSource("io.gitlab.arturbosch.detekt.rules.exceptions.SwallowedException#getEXCEPTIONS_IGNORED_BY_DEFAULT") + fun `ignores $exceptionName in the catch body by default`(exceptionName: String) { + val exceptionInstantiation = if (exceptionName == "ParseException") { + "$exceptionName(\"\", 0)" + } else { + "$exceptionName(\"\")" + } - fun f() { - try { - } catch (e: Exception) { - throw $exceptionInstantiation - } + val code = """ + import java.net.MalformedURLException + import java.text.ParseException + + fun f() { + try { + } catch (e: Exception) { + throw $exceptionInstantiation } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionFromFinallySpec.kt b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionFromFinallySpec.kt index 9f20043c677..9d648bb096f 100644 --- a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionFromFinallySpec.kt +++ b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionFromFinallySpec.kt @@ -2,54 +2,49 @@ package io.gitlab.arturbosch.detekt.rules.exceptions import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ThrowingExceptionFromFinallySpec { val subject = ThrowingExceptionFromFinally() - @Nested - inner class `ThrowingExceptionFromFinally rule` { - - @Test - fun `should report a throw expression`() { - val code = """ - fun x() { - try { - } finally { - if (1 == 1) { - throw IllegalArgumentException() - } + @Test + fun `should report a throw expression`() { + val code = """ + fun x() { + try { + } finally { + if (1 == 1) { + throw IllegalArgumentException() } } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `should report a nested throw expression`() { - val code = """ - fun x() { - try { - } finally { - throw IllegalArgumentException() - } + @Test + fun `should report a nested throw expression`() { + val code = """ + fun x() { + try { + } finally { + throw IllegalArgumentException() } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `should not report a finally expression without a throw expression`() { - val code = """ - fun x() { - try { - } finally { - println() - } + @Test + fun `should not report a finally expression without a throw expression`() { + val code = """ + fun x() { + try { + } finally { + println() } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionInMainSpec.kt b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionInMainSpec.kt index d965409ddb7..7300329b18e 100644 --- a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionInMainSpec.kt +++ b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionInMainSpec.kt @@ -3,94 +3,89 @@ package io.gitlab.arturbosch.detekt.rules.exceptions import io.gitlab.arturbosch.detekt.test.compileAndLint import io.gitlab.arturbosch.detekt.test.lint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ThrowingExceptionInMainSpec { val subject = ThrowingExceptionInMain() - @Nested - inner class `ThrowingExceptionInMain rule` { - - @Test - fun `reports a runnable main function which throws an exception`() { - val code = """ - fun main(args: Array) { throw IllegalArgumentException() } - fun main(vararg args: String) { throw IllegalArgumentException() } - fun main() { throw IllegalArgumentException() } - """ - assertThat(subject.compileAndLint(code)).hasSize(3) - } + @Test + fun `reports a runnable main function which throws an exception`() { + val code = """ + fun main(args: Array) { throw IllegalArgumentException() } + fun main(vararg args: String) { throw IllegalArgumentException() } + fun main() { throw IllegalArgumentException() } + """ + assertThat(subject.compileAndLint(code)).hasSize(3) + } - @Test - fun `reports runnable main functions with @JvmStatic annotation which throw an exception`() { - val code = """ - class A { - companion object { - @JvmStatic - fun main(args: Array) { throw IllegalArgumentException() } - } - } - - class B { - companion object { - @kotlin.jvm.JvmStatic - fun main() { throw IllegalArgumentException() } - } - } - - object O { + @Test + fun `reports runnable main functions with @JvmStatic annotation which throw an exception`() { + val code = """ + class A { + companion object { @JvmStatic fun main(args: Array) { throw IllegalArgumentException() } } - """ - assertThat(subject.compileAndLint(code)).hasSize(3) - } + } + + class B { + companion object { + @kotlin.jvm.JvmStatic + fun main() { throw IllegalArgumentException() } + } + } + + object O { + @JvmStatic + fun main(args: Array) { throw IllegalArgumentException() } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(3) + } - @Test - fun `does not report top level main functions with a wrong signature`() { - val code = """ - private fun main(args: Array) { throw IllegalArgumentException() } - private fun main() { throw IllegalArgumentException() } - fun mai() { throw IllegalArgumentException() } - fun main(args: String) { throw IllegalArgumentException() } - fun main(args: Array, i: Int) { throw IllegalArgumentException() } - """ - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `does not report top level main functions with a wrong signature`() { + val code = """ + private fun main(args: Array) { throw IllegalArgumentException() } + private fun main() { throw IllegalArgumentException() } + fun mai() { throw IllegalArgumentException() } + fun main(args: String) { throw IllegalArgumentException() } + fun main(args: Array, i: Int) { throw IllegalArgumentException() } + """ + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `does not report top level main functions which throw no exception`() { - val code = """ - fun main(args: Array) { } - fun main() { } - fun mai() { } - fun main(args: String) { } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report top level main functions which throw no exception`() { + val code = """ + fun main(args: Array) { } + fun main() { } + fun mai() { } + fun main(args: String) { } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report top level main functions with expression body which throw no exception`() { - val code = """ - fun main(args: Array) = "" - fun main() = Unit - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report top level main functions with expression body which throw no exception`() { + val code = """ + fun main(args: Array) = "" + fun main() = Unit + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report main functions with no @JvmStatic annotation inside a class`() { - val code = """ - class A { + @Test + fun `does not report main functions with no @JvmStatic annotation inside a class`() { + val code = """ + class A { + fun main(args: Array) { throw IllegalArgumentException() } + + companion object { fun main(args: Array) { throw IllegalArgumentException() } - - companion object { - fun main(args: Array) { throw IllegalArgumentException() } - } } - """ - assertThat(subject.compileAndLint(code)).isEmpty() } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionsWithoutMessageOrCauseSpec.kt b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionsWithoutMessageOrCauseSpec.kt index fa4970f6317..43c7f1ca0a8 100644 --- a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionsWithoutMessageOrCauseSpec.kt +++ b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingExceptionsWithoutMessageOrCauseSpec.kt @@ -13,44 +13,40 @@ class ThrowingExceptionsWithoutMessageOrCauseSpec { ) @Nested - inner class `ThrowingExceptionsWithoutMessageOrCause rule` { + inner class `several exception calls` { - @Nested - inner class `several exception calls` { - - val code = """ - fun x() { - IllegalArgumentException(IllegalArgumentException()) - IllegalArgumentException("foo") - throw IllegalArgumentException() - } - """ - - @Test - fun `reports calls to the default constructor`() { - assertThat(subject.compileAndLint(code)).hasSize(2) + val code = """ + fun x() { + IllegalArgumentException(IllegalArgumentException()) + IllegalArgumentException("foo") + throw IllegalArgumentException() } + """ - @Test - fun `does not report calls to the default constructor with empty configuration`() { - val config = TestConfig("exceptions" to emptyList()) - val findings = ThrowingExceptionsWithoutMessageOrCause(config).compileAndLint(code) - assertThat(findings).isEmpty() - } + @Test + fun `reports calls to the default constructor`() { + assertThat(subject.compileAndLint(code)).hasSize(2) + } + + @Test + fun `does not report calls to the default constructor with empty configuration`() { + val config = TestConfig("exceptions" to emptyList()) + val findings = ThrowingExceptionsWithoutMessageOrCause(config).compileAndLint(code) + assertThat(findings).isEmpty() } + } + + @Nested + inner class `a test code which asserts an exception` { - @Nested - inner class `a test code which asserts an exception` { - - @Test - fun `does not report a call to this exception`() { - val code = """ - fun test() { - org.assertj.core.api.Assertions.assertThatIllegalArgumentException().isThrownBy { println() } - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() + @Test + fun `does not report a call to this exception`() { + val code = """ + fun test() { + org.assertj.core.api.Assertions.assertThatIllegalArgumentException().isThrownBy { println() } } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } } diff --git a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingNewInstanceOfSameExceptionSpec.kt b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingNewInstanceOfSameExceptionSpec.kt index 32f05721924..05c87835d9c 100644 --- a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingNewInstanceOfSameExceptionSpec.kt +++ b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/ThrowingNewInstanceOfSameExceptionSpec.kt @@ -10,61 +10,57 @@ class ThrowingNewInstanceOfSameExceptionSpec { val subject = ThrowingNewInstanceOfSameException() @Nested - inner class `ThrowingNewInstanceOfSameException rule` { - - @Nested - inner class `a catch block which rethrows a new instance of the caught exception` { - val code = """ - fun x() { - try { - } catch (e: IllegalStateException) { - throw IllegalStateException(e) - } + inner class `a catch block which rethrows a new instance of the caught exception` { + val code = """ + fun x() { + try { + } catch (e: IllegalStateException) { + throw IllegalStateException(e) } - """ + } + """ - @Test - fun `should report`() { - val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(1) - } + @Test + fun `should report`() { + val findings = subject.compileAndLint(code) + assertThat(findings).hasSize(1) } + } - @Nested - inner class `a catch block which rethrows a new instance of another exception` { - val code = """ - fun x() { - try { - } catch (e: IllegalStateException) { - throw IllegalArgumentException(e) - } + @Nested + inner class `a catch block which rethrows a new instance of another exception` { + val code = """ + fun x() { + try { + } catch (e: IllegalStateException) { + throw IllegalArgumentException(e) } - """ + } + """ - @Test - fun `should not report`() { - val findings = subject.compileAndLint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not report`() { + val findings = subject.compileAndLint(code) + assertThat(findings).isEmpty() } + } - @Nested - @DisplayName("a catch block which throws a new instance of the same exception type without wrapping the caught exception") - inner class CatchBlockThrowingSameExceptionWithoutWrapping { - val code = """ - fun x() { - try { - } catch (e: IllegalStateException) { - throw IllegalStateException() - } + @Nested + @DisplayName("a catch block which throws a new instance of the same exception type without wrapping the caught exception") + inner class CatchBlockThrowingSameExceptionWithoutWrapping { + val code = """ + fun x() { + try { + } catch (e: IllegalStateException) { + throw IllegalStateException() } - """ + } + """ - @Test - fun `should not report`() { - val findings = subject.compileAndLint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not report`() { + val findings = subject.compileAndLint(code) + assertThat(findings).isEmpty() } } } diff --git a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/TooGenericExceptionSpec.kt b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/TooGenericExceptionSpec.kt index f1e35830b46..8b354f6ccc1 100644 --- a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/TooGenericExceptionSpec.kt +++ b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/TooGenericExceptionSpec.kt @@ -3,25 +3,20 @@ package io.gitlab.arturbosch.detekt.rules.exceptions import io.github.detekt.test.utils.compileContentForTest import io.gitlab.arturbosch.detekt.test.yamlConfig import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class TooGenericExceptionSpec { - @Nested - inner class `TooGenericException rule` { + @Test + fun `should not report any as all catch exception rules are deactivated`() { + val config = yamlConfig("deactivated-exceptions.yml") + val ruleSet = ExceptionsProvider().instance(config) + val file = compileContentForTest(tooGenericExceptionCode) - @Test - fun `should not report any as all catch exception rules are deactivated`() { - val config = yamlConfig("deactivated-exceptions.yml") - val ruleSet = ExceptionsProvider().instance(config) - val file = compileContentForTest(tooGenericExceptionCode) + @Suppress("DEPRECATION") + val findings = ruleSet.accept(file) - @Suppress("DEPRECATION") - val findings = ruleSet.accept(file) - - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() } } diff --git a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/TooGenericExceptionThrownSpec.kt b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/TooGenericExceptionThrownSpec.kt index cdee12b0650..8d913557e21 100644 --- a/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/TooGenericExceptionThrownSpec.kt +++ b/detekt-rules-exceptions/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/exceptions/TooGenericExceptionThrownSpec.kt @@ -3,7 +3,6 @@ package io.gitlab.arturbosch.detekt.rules.exceptions import io.gitlab.arturbosch.detekt.test.TestConfig import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource @@ -12,58 +11,54 @@ private const val EXCEPTION_NAMES = "exceptionNames" class TooGenericExceptionThrownSpec { - @Nested - inner class `a file with many thrown exceptions` { + @ParameterizedTest + @ValueSource(strings = ["Error", "Exception", "Throwable", "RuntimeException"]) + fun `should report $exceptionName`(exceptionName: String) { + val config = TestConfig(mapOf(EXCEPTION_NAMES to "[$exceptionName]")) + val rule = TooGenericExceptionThrown(config) - @ParameterizedTest - @ValueSource(strings = ["Error", "Exception", "Throwable", "RuntimeException"]) - fun `should report $exceptionName`(exceptionName: String) { - val config = TestConfig(mapOf(EXCEPTION_NAMES to "[$exceptionName]")) - val rule = TooGenericExceptionThrown(config) + val findings = rule.compileAndLint(tooGenericExceptionCode) - val findings = rule.compileAndLint(tooGenericExceptionCode) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should not report thrown exceptions`() { - val config = TestConfig(mapOf(EXCEPTION_NAMES to "['MyException', Bar]")) - val rule = TooGenericExceptionThrown(config) + assertThat(findings).hasSize(1) + } - val findings = rule.compileAndLint(tooGenericExceptionCode) + @Test + fun `should not report thrown exceptions`() { + val config = TestConfig(mapOf(EXCEPTION_NAMES to "['MyException', Bar]")) + val rule = TooGenericExceptionThrown(config) - assertThat(findings).isEmpty() - } + val findings = rule.compileAndLint(tooGenericExceptionCode) - @Test - fun `should not report caught exceptions`() { - val config = TestConfig(mapOf(EXCEPTION_NAMES to "['Exception']")) - val rule = TooGenericExceptionThrown(config) + assertThat(findings).isEmpty() + } - val code = """ - fun f() { - try { - throw Throwable() - } catch (caught: Exception) { - throw Error() - } + @Test + fun `should not report caught exceptions`() { + val config = TestConfig(mapOf(EXCEPTION_NAMES to "['Exception']")) + val rule = TooGenericExceptionThrown(config) + + val code = """ + fun f() { + try { + throw Throwable() + } catch (caught: Exception) { + throw Error() } - """ - val findings = rule.compileAndLint(code) + } + """ + val findings = rule.compileAndLint(code) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `should not report initialize exceptions`() { - val config = TestConfig(mapOf(EXCEPTION_NAMES to "['Exception']")) - val rule = TooGenericExceptionThrown(config) + @Test + fun `should not report initialize exceptions`() { + val config = TestConfig(mapOf(EXCEPTION_NAMES to "['Exception']")) + val rule = TooGenericExceptionThrown(config) - val code = """fun f() { val ex = Exception() }""" - val findings = rule.compileAndLint(code) + val code = """fun f() { val ex = Exception() }""" + val findings = rule.compileAndLint(code) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() } } diff --git a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/BooleanPropertyNamingSpec.kt b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/BooleanPropertyNamingSpec.kt index cb99102857b..a6fa028720e 100644 --- a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/BooleanPropertyNamingSpec.kt +++ b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/BooleanPropertyNamingSpec.kt @@ -14,584 +14,580 @@ class BooleanPropertyNamingSpec(val env: KotlinCoreEnvironment) { val subject = BooleanPropertyNaming() @Nested - inner class `BooleanPropertyNaming rule` { - - @Nested - inner class `argument declarations` { - @Test - fun `should warn about Kotlin Boolean`() { - val code = """data class Test (var default: Boolean)""" - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should not warn about Kotlin Boolean override by default`() { - val code = """ - interface Test { - val default: Boolean - } - - data class TestImpl (override var default: Boolean) : Test - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should warn about Kotlin Boolean override if ignoreOverridden is false`() { - val code = """ - interface Test { - val default: Boolean - } - - data class TestImpl (override var default: Boolean) : Test - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(2) - } - - @Test - fun `should not warn about Kotlin Boolean override if ignoreOverridden is true`() { - val code = """ - interface Test { - val default: Boolean - } - - data class TestImpl (override var default: Boolean) : Test - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should warn about Kotlin Boolean nullable`() { - val code = """data class Test (var default: Boolean?)""" - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should not warn about Kotlin Boolean nullable override by default`() { - val code = """ - interface Test { - val default: Boolean? - } - - data class TestImpl (override var default: Boolean?) : Test - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should warn about Kotlin Boolean nullable override if ignoreOverridden is false`() { - val code = """ - interface Test { - val default: Boolean? - } - - data class TestImpl (override var default: Boolean?) : Test - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(2) - } - - @Test - fun `should not warn about Kotlin Boolean nullable override if ignoreOverridden is true`() { - val code = """ - interface Test { - val default: Boolean? - } - - data class TestImpl (override var default: Boolean?) : Test - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should warn about Kotlin Boolean initialized`() { - val code = """data class Test (var default: Boolean = false)""" - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should not warn about Kotlin Boolean initialized override by default`() { - val code = """ - interface Test { - val default: Boolean - } - - data class TestImpl (override var default: Boolean = false) : Test - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should warn about Kotlin Boolean initialized override if ignoreOverridden is false`() { - val code = """ - interface Test { - val default: Boolean - } - - data class TestImpl (override var default: Boolean = false) : Test - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(2) - } - - @Test - fun `should not warn about Kotlin Boolean initialized override if ignoreOverridden is true`() { - val code = """ - interface Test { - val default: Boolean - } - - data class TestImpl (override var default: Boolean = false) : Test - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should warn about Java Boolean`() { - val code = """data class Test (var default: java.lang.Boolean)""" - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should not warn about Java Boolean override by default`() { - val code = """ - interface Test { - val default: java.lang.Boolean - } - - data class TestImpl (override var default: java.lang.Boolean) : Test - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should warn about Java Boolean override if ignoreOverridden is false`() { - val code = """ - interface Test { - val default: java.lang.Boolean - } - - data class TestImpl (override var default: java.lang.Boolean) : Test - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(2) - } - - @Test - fun `should not warn about Java Boolean override if ignoreOverridden is true`() { - val code = """ - interface Test { - val default: java.lang.Boolean - } - - data class TestImpl (override var default: java.lang.Boolean) : Test - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should not detect primitive types`() { - val code = """data class Test (var count: Int)""" - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).isEmpty() - } - - @Test - fun `should not detect names that match an allowed pattern`() { - val code = """data class Test (var isEnabled: Boolean, var hasDefault: Boolean)""" - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).isEmpty() - } - } - - @Nested - inner class `property declarations` { - @Test - fun `should warn about Kotlin Boolean`() { - val code = """ - class Test { - var default: Boolean = true - } - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should not warn about Kotlin Boolean override by default`() { - val code = """ - interface Test { - val default: Boolean - } - - class TestImpl : Test { - override var default: Boolean = true - } - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should warn about Kotlin Boolean override if isIgnoreOverridden is false`() { - val code = """ - interface Test { - val default: Boolean - } - - class TestImpl : Test { - override var default: Boolean = true - } - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(2) - } - - @Test - fun `should not warn about Kotlin Boolean override if isIgnoreOverridden is true`() { - val code = """ - interface Test { - val default: Boolean - } - - class TestImpl : Test { - override var default: Boolean = true - } - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should warn about Kotlin Boolean nullable`() { - val code = """ - class Test { - var default: Boolean? = null - } - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should not warn about Kotlin Boolean nullable override by default`() { - val code = """ - interface Test { - val default: Boolean? - } - - class TestImpl : Test { - override var default: Boolean? = null - } - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should warn about Kotlin Boolean nullable override if ignoreOverridden is false`() { - val code = """ - interface Test { - val default: Boolean? - } - - class TestImpl : Test { - override var default: Boolean? = null - } - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(2) - } - - @Test - fun `should not warn about Kotlin Boolean nullable override if ignoreOverridden is true`() { - val code = """ - interface Test { - val default: Boolean? - } - - class TestImpl : Test { - override var default: Boolean? = null - } - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should warn about Kotlin Boolean initialized`() { - val code = """ - class Test { - var default: Boolean = false - } - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should not warn about Kotlin Boolean initialized override by default`() { - val code = """ - interface Test { - val default: Boolean - } - - class TestImpl : Test { - override var default: Boolean = false - } - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should warn about Kotlin Boolean initialized override if ignoreOverridden is false`() { - val code = """ - interface Test { - val default: Boolean - } - - class TestImpl : Test { - override var default: Boolean = false - } - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(2) - } - - @Test - fun `should not warn about Kotlin Boolean initialized override if ignoreOverridden is true`() { - val code = """ - interface Test { - val default: Boolean - } - - class TestImpl : Test { - override var default: Boolean = false - } - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should warn about inferred boolean type`() { - val code = """ - class Test { - var default = true - } - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should not warn about inferred boolean type override by default`() { - val code = """ - interface Test { - val default: Boolean - } - - class TestImpl : Test { - override var default = true - } - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should warn about inferred boolean type override if ignoreOverridden is false`() { - val code = """ - interface Test { - val default: Boolean - } - - class TestImpl : Test { - override var default = true - } - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(2) - } - - @Test - fun `should not warn about inferred boolean type override if ignoreOverridden is true`() { - val code = """ - interface Test { - val default: Boolean - } - - class TestImpl : Test { - override var default = true - } - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should warn about Java Boolean`() { - val code = """ - class Test { - var default: java.lang.Boolean = java.lang.Boolean(true) - } - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should not warn about Java Boolean override by default`() { - val code = """ - interface Test { - val default: java.lang.Boolean - } - - class TestImpl : Test { - override var default: java.lang.Boolean = java.lang.Boolean(true) - } - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should warn about Java Boolean override if ignoreOverridden is false`() { - val code = """ - interface Test { - val default: java.lang.Boolean - } - - class TestImpl : Test { - override var default: java.lang.Boolean = java.lang.Boolean(true) - } - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(2) - } - - @Test - fun `should not warn about Java Boolean override if ignoreOverridden is true`() { - val code = """ - interface Test { - val default: java.lang.Boolean - } - - class TestImpl : Test { - override var default: java.lang.Boolean = java.lang.Boolean(true) - } - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) - val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) - - assertThat(findings).hasSize(1) - } - - @Test - fun `should not detect primitive types`() { - val code = """ - class Test { - var count: Int = 0 - } - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).isEmpty() - } - - @Test - fun `should not detect names that match an allowed pattern`() { - val code = """ - class Test { - var isEnabled: Boolean = true - var hasDefault: Boolean = true - } - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).isEmpty() - } - - @Test - fun `should not detect names that match an allowed pattern from config`() { - val code = """ - class Test { - var needReload: Boolean = true - } - """ - - val config = TestConfig(mapOf(ALLOWED_PATTERN to "^(is|has|are|need)")) - assertThat(BooleanPropertyNaming(config).compileAndLint(code)) - .isEmpty() - } + inner class `argument declarations` { + @Test + fun `should warn about Kotlin Boolean`() { + val code = """data class Test (var default: Boolean)""" + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should not warn about Kotlin Boolean override by default`() { + val code = """ + interface Test { + val default: Boolean + } + + data class TestImpl (override var default: Boolean) : Test + """ + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should warn about Kotlin Boolean override if ignoreOverridden is false`() { + val code = """ + interface Test { + val default: Boolean + } + + data class TestImpl (override var default: Boolean) : Test + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(2) + } + + @Test + fun `should not warn about Kotlin Boolean override if ignoreOverridden is true`() { + val code = """ + interface Test { + val default: Boolean + } + + data class TestImpl (override var default: Boolean) : Test + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should warn about Kotlin Boolean nullable`() { + val code = """data class Test (var default: Boolean?)""" + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should not warn about Kotlin Boolean nullable override by default`() { + val code = """ + interface Test { + val default: Boolean? + } + + data class TestImpl (override var default: Boolean?) : Test + """ + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should warn about Kotlin Boolean nullable override if ignoreOverridden is false`() { + val code = """ + interface Test { + val default: Boolean? + } + + data class TestImpl (override var default: Boolean?) : Test + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(2) + } + + @Test + fun `should not warn about Kotlin Boolean nullable override if ignoreOverridden is true`() { + val code = """ + interface Test { + val default: Boolean? + } + + data class TestImpl (override var default: Boolean?) : Test + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should warn about Kotlin Boolean initialized`() { + val code = """data class Test (var default: Boolean = false)""" + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should not warn about Kotlin Boolean initialized override by default`() { + val code = """ + interface Test { + val default: Boolean + } + + data class TestImpl (override var default: Boolean = false) : Test + """ + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should warn about Kotlin Boolean initialized override if ignoreOverridden is false`() { + val code = """ + interface Test { + val default: Boolean + } + + data class TestImpl (override var default: Boolean = false) : Test + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(2) + } + + @Test + fun `should not warn about Kotlin Boolean initialized override if ignoreOverridden is true`() { + val code = """ + interface Test { + val default: Boolean + } + + data class TestImpl (override var default: Boolean = false) : Test + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should warn about Java Boolean`() { + val code = """data class Test (var default: java.lang.Boolean)""" + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should not warn about Java Boolean override by default`() { + val code = """ + interface Test { + val default: java.lang.Boolean + } + + data class TestImpl (override var default: java.lang.Boolean) : Test + """ + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should warn about Java Boolean override if ignoreOverridden is false`() { + val code = """ + interface Test { + val default: java.lang.Boolean + } + + data class TestImpl (override var default: java.lang.Boolean) : Test + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(2) + } + + @Test + fun `should not warn about Java Boolean override if ignoreOverridden is true`() { + val code = """ + interface Test { + val default: java.lang.Boolean + } + + data class TestImpl (override var default: java.lang.Boolean) : Test + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should not detect primitive types`() { + val code = """data class Test (var count: Int)""" + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).isEmpty() + } + + @Test + fun `should not detect names that match an allowed pattern`() { + val code = """data class Test (var isEnabled: Boolean, var hasDefault: Boolean)""" + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).isEmpty() + } + } + + @Nested + inner class `property declarations` { + @Test + fun `should warn about Kotlin Boolean`() { + val code = """ + class Test { + var default: Boolean = true + } + """ + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should not warn about Kotlin Boolean override by default`() { + val code = """ + interface Test { + val default: Boolean + } + + class TestImpl : Test { + override var default: Boolean = true + } + """ + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should warn about Kotlin Boolean override if isIgnoreOverridden is false`() { + val code = """ + interface Test { + val default: Boolean + } + + class TestImpl : Test { + override var default: Boolean = true + } + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(2) + } + + @Test + fun `should not warn about Kotlin Boolean override if isIgnoreOverridden is true`() { + val code = """ + interface Test { + val default: Boolean + } + + class TestImpl : Test { + override var default: Boolean = true + } + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should warn about Kotlin Boolean nullable`() { + val code = """ + class Test { + var default: Boolean? = null + } + """ + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should not warn about Kotlin Boolean nullable override by default`() { + val code = """ + interface Test { + val default: Boolean? + } + + class TestImpl : Test { + override var default: Boolean? = null + } + """ + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should warn about Kotlin Boolean nullable override if ignoreOverridden is false`() { + val code = """ + interface Test { + val default: Boolean? + } + + class TestImpl : Test { + override var default: Boolean? = null + } + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(2) + } + + @Test + fun `should not warn about Kotlin Boolean nullable override if ignoreOverridden is true`() { + val code = """ + interface Test { + val default: Boolean? + } + + class TestImpl : Test { + override var default: Boolean? = null + } + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should warn about Kotlin Boolean initialized`() { + val code = """ + class Test { + var default: Boolean = false + } + """ + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should not warn about Kotlin Boolean initialized override by default`() { + val code = """ + interface Test { + val default: Boolean + } + + class TestImpl : Test { + override var default: Boolean = false + } + """ + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should warn about Kotlin Boolean initialized override if ignoreOverridden is false`() { + val code = """ + interface Test { + val default: Boolean + } + + class TestImpl : Test { + override var default: Boolean = false + } + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(2) + } + + @Test + fun `should not warn about Kotlin Boolean initialized override if ignoreOverridden is true`() { + val code = """ + interface Test { + val default: Boolean + } + + class TestImpl : Test { + override var default: Boolean = false + } + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should warn about inferred boolean type`() { + val code = """ + class Test { + var default = true + } + """ + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should not warn about inferred boolean type override by default`() { + val code = """ + interface Test { + val default: Boolean + } + + class TestImpl : Test { + override var default = true + } + """ + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should warn about inferred boolean type override if ignoreOverridden is false`() { + val code = """ + interface Test { + val default: Boolean + } + + class TestImpl : Test { + override var default = true + } + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(2) + } + + @Test + fun `should not warn about inferred boolean type override if ignoreOverridden is true`() { + val code = """ + interface Test { + val default: Boolean + } + + class TestImpl : Test { + override var default = true + } + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should warn about Java Boolean`() { + val code = """ + class Test { + var default: java.lang.Boolean = java.lang.Boolean(true) + } + """ + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should not warn about Java Boolean override by default`() { + val code = """ + interface Test { + val default: java.lang.Boolean + } + + class TestImpl : Test { + override var default: java.lang.Boolean = java.lang.Boolean(true) + } + """ + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should warn about Java Boolean override if ignoreOverridden is false`() { + val code = """ + interface Test { + val default: java.lang.Boolean + } + + class TestImpl : Test { + override var default: java.lang.Boolean = java.lang.Boolean(true) + } + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to false)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(2) + } + + @Test + fun `should not warn about Java Boolean override if ignoreOverridden is true`() { + val code = """ + interface Test { + val default: java.lang.Boolean + } + + class TestImpl : Test { + override var default: java.lang.Boolean = java.lang.Boolean(true) + } + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to true)) + val findings = BooleanPropertyNaming(config).compileAndLintWithContext(env, code) + + assertThat(findings).hasSize(1) + } + + @Test + fun `should not detect primitive types`() { + val code = """ + class Test { + var count: Int = 0 + } + """ + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).isEmpty() + } + + @Test + fun `should not detect names that match an allowed pattern`() { + val code = """ + class Test { + var isEnabled: Boolean = true + var hasDefault: Boolean = true + } + """ + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).isEmpty() + } + + @Test + fun `should not detect names that match an allowed pattern from config`() { + val code = """ + class Test { + var needReload: Boolean = true + } + """ + + val config = TestConfig(mapOf(ALLOWED_PATTERN to "^(is|has|are|need)")) + assertThat(BooleanPropertyNaming(config).compileAndLint(code)) + .isEmpty() } } } diff --git a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/ClassNamingSpec.kt b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/ClassNamingSpec.kt index 117494b867d..15eb171da22 100644 --- a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/ClassNamingSpec.kt +++ b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/ClassNamingSpec.kt @@ -2,71 +2,66 @@ package io.gitlab.arturbosch.detekt.rules.naming import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ClassNamingSpec { - @Nested - inner class `different naming conventions inside classes` { + @Test + fun `should detect no violations class with numbers`() { + val code = """ + class MyClassWithNumbers5 + """ - @Test - fun `should detect no violations class with numbers`() { - val code = """ - class MyClassWithNumbers5 - """ - - assertThat(ClassNaming().compileAndLint(code)).isEmpty() - } + assertThat(ClassNaming().compileAndLint(code)).isEmpty() + } - @Test - fun `should detect no violations`() { - val code = """ - class NamingConventions { - } - """ + @Test + fun `should detect no violations`() { + val code = """ + class NamingConventions { + } + """ - assertThat(ClassNaming().compileAndLint(code)).isEmpty() - } + assertThat(ClassNaming().compileAndLint(code)).isEmpty() + } - @Test - fun `should detect no violations with class using backticks`() { - val code = """ - class `NamingConventions` - """ + @Test + fun `should detect no violations with class using backticks`() { + val code = """ + class `NamingConventions` + """ - assertThat(ClassNaming().compileAndLint(code)).isEmpty() - } + assertThat(ClassNaming().compileAndLint(code)).isEmpty() + } - @Test - fun `should detect because it have a _`() { - val code = """ - class _NamingConventions - """ + @Test + fun `should detect because it have a _`() { + val code = """ + class _NamingConventions + """ - assertThat(ClassNaming().compileAndLint(code)) - .hasSize(1) - .hasTextLocations(6 to 24) - } + assertThat(ClassNaming().compileAndLint(code)) + .hasSize(1) + .hasTextLocations(6 to 24) + } - @Test - fun `should detect because it have starts with lowercase`() { - val code = """ - class namingConventions {} - """ + @Test + fun `should detect because it have starts with lowercase`() { + val code = """ + class namingConventions {} + """ - assertThat(ClassNaming().compileAndLint(code)) - .hasSize(1) - .hasTextLocations(6 to 23) - } + assertThat(ClassNaming().compileAndLint(code)) + .hasSize(1) + .hasTextLocations(6 to 23) + } - @Test - fun `should ignore the issue by alias suppression`() { - val code = """ - @Suppress("ClassName") - class namingConventions {} - """ - assertThat(ClassNaming().compileAndLint(code)).isEmpty() - } + @Test + fun `should ignore the issue by alias suppression`() { + val code = """ + @Suppress("ClassName") + class namingConventions {} + """ + assertThat(ClassNaming().compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/ConstructorParameterNamingSpec.kt b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/ConstructorParameterNamingSpec.kt index beb5ff2954b..758e898a1c3 100644 --- a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/ConstructorParameterNamingSpec.kt +++ b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/ConstructorParameterNamingSpec.kt @@ -3,68 +3,63 @@ package io.gitlab.arturbosch.detekt.rules.naming import io.gitlab.arturbosch.detekt.test.TestConfig import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ConstructorParameterNamingSpec { - @Nested - inner class `parameters in a constructor of a class` { + @Test + fun `should detect no violations`() { + val code = """ + class C(val param: String, private val privateParam: String) - @Test - fun `should detect no violations`() { - val code = """ - class C(val param: String, private val privateParam: String) - - class D { - constructor(param: String) {} - constructor(param: String, privateParam: String) {} - } - """ - assertThat(ConstructorParameterNaming().compileAndLint(code)).isEmpty() - } + class D { + constructor(param: String) {} + constructor(param: String, privateParam: String) {} + } + """ + assertThat(ConstructorParameterNaming().compileAndLint(code)).isEmpty() + } - @Test - fun `should find some violations`() { - val code = """ - class C(val PARAM: String, private val PRIVATE_PARAM: String) + @Test + fun `should find some violations`() { + val code = """ + class C(val PARAM: String, private val PRIVATE_PARAM: String) - class C { - constructor(PARAM: String) {} - constructor(PARAM: String, PRIVATE_PARAM: String) {} - } - """ - assertThat(ConstructorParameterNaming().compileAndLint(code)).hasSize(5) - } + class C { + constructor(PARAM: String) {} + constructor(PARAM: String, PRIVATE_PARAM: String) {} + } + """ + assertThat(ConstructorParameterNaming().compileAndLint(code)).hasSize(5) + } - @Test - fun `should find a violation in the correct text location`() { - val code = """ - class C(val PARAM: String) - """ - assertThat(ConstructorParameterNaming().compileAndLint(code)).hasTextLocations(8 to 25) - } + @Test + fun `should find a violation in the correct text location`() { + val code = """ + class C(val PARAM: String) + """ + assertThat(ConstructorParameterNaming().compileAndLint(code)).hasTextLocations(8 to 25) + } - @Test - fun `should not complain about override by default`() { - val code = """ - class C(override val PARAM: String) : I + @Test + fun `should not complain about override by default`() { + val code = """ + class C(override val PARAM: String) : I - interface I { val PARAM: String } - """ - assertThat(ConstructorParameterNaming().compileAndLint(code)).isEmpty() - } + interface I { val PARAM: String } + """ + assertThat(ConstructorParameterNaming().compileAndLint(code)).isEmpty() + } - @Test - fun `should not complain about override when ignore overridden = false`() { - val code = """ - class C(override val PARAM: String) : I + @Test + fun `should not complain about override when ignore overridden = false`() { + val code = """ + class C(override val PARAM: String) : I - interface I { val PARAM: String } - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to "false")) - assertThat(ConstructorParameterNaming(config).compileAndLint(code)).hasTextLocations(8 to 34) - } + interface I { val PARAM: String } + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to "false")) + assertThat(ConstructorParameterNaming(config).compileAndLint(code)).hasTextLocations(8 to 34) } } diff --git a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/EnumNamingSpec.kt b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/EnumNamingSpec.kt index ee21a50737e..ac6cda15e40 100644 --- a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/EnumNamingSpec.kt +++ b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/EnumNamingSpec.kt @@ -2,65 +2,60 @@ package io.gitlab.arturbosch.detekt.rules.naming import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class EnumNamingSpec { - @Nested - inner class `some enum entry declarations` { - - @Test - fun `should detect no violation`() { - val findings = EnumNaming().compileAndLint( - """ - enum class WorkFlow { - ACTIVE, NOT_ACTIVE, Unknown, Number1 - } - """ - ) - assertThat(findings).isEmpty() - } - - @Test - fun `enum name that start with lowercase`() { - val code = """ - enum class WorkFlow { - default - } + @Test + fun `should detect no violation`() { + val findings = EnumNaming().compileAndLint( """ - assertThat(NamingRules().compileAndLint(code)).hasSize(1) - } - - @Test - fun `reports an underscore in enum name`() { - val code = """ - enum class WorkFlow { - _Default - } + enum class WorkFlow { + ACTIVE, NOT_ACTIVE, Unknown, Number1 + } """ - assertThat(EnumNaming().compileAndLint(code)).hasSize(1) - } + ) + assertThat(findings).isEmpty() + } - @Test - fun `no reports an underscore in enum name because it's suppressed`() { - val code = """ - enum class WorkFlow { - @Suppress("EnumNaming") _Default - } - """ - assertThat(EnumNaming().compileAndLint(code)).isEmpty() - } + @Test + fun `enum name that start with lowercase`() { + val code = """ + enum class WorkFlow { + default + } + """ + assertThat(NamingRules().compileAndLint(code)).hasSize(1) + } - @Test - fun `reports the correct text location in enum name`() { - val code = """ - enum class WorkFlow { - _Default, - } - """ - val findings = EnumNaming().compileAndLint(code) - assertThat(findings).hasTextLocations(26 to 34) - } + @Test + fun `reports an underscore in enum name`() { + val code = """ + enum class WorkFlow { + _Default + } + """ + assertThat(EnumNaming().compileAndLint(code)).hasSize(1) + } + + @Test + fun `no reports an underscore in enum name because it's suppressed`() { + val code = """ + enum class WorkFlow { + @Suppress("EnumNaming") _Default + } + """ + assertThat(EnumNaming().compileAndLint(code)).isEmpty() + } + + @Test + fun `reports the correct text location in enum name`() { + val code = """ + enum class WorkFlow { + _Default, + } + """ + val findings = EnumNaming().compileAndLint(code) + assertThat(findings).hasTextLocations(26 to 34) } } diff --git a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/ForbiddenClassNameSpec.kt b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/ForbiddenClassNameSpec.kt index 08ec41842c5..8ab8c2e9aa1 100644 --- a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/ForbiddenClassNameSpec.kt +++ b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/ForbiddenClassNameSpec.kt @@ -3,77 +3,72 @@ package io.gitlab.arturbosch.detekt.rules.naming import io.gitlab.arturbosch.detekt.test.TestConfig import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test private const val FORBIDDEN_NAME = "forbiddenName" class ForbiddenClassNameSpec { - @Nested - inner class `ForbiddenClassName rule` { - - @Test - fun `should report classes with forbidden names`() { - val code = """ - class TestManager {} // violation - class TestProvider {} // violation - class TestHolder - """ - assertThat( - ForbiddenClassName(TestConfig(mapOf(FORBIDDEN_NAME to listOf("Manager", "Provider")))) - .compileAndLint(code) - ) - .hasSize(2) - } - - @Test - fun `should report a class that starts with a forbidden name`() { - val code = "class TestProvider {}" - assertThat( - ForbiddenClassName(TestConfig(mapOf(FORBIDDEN_NAME to listOf("test")))) - .compileAndLint(code) - ) - .hasSize(1) - } + @Test + fun `should report classes with forbidden names`() { + val code = """ + class TestManager {} // violation + class TestProvider {} // violation + class TestHolder + """ + assertThat( + ForbiddenClassName(TestConfig(mapOf(FORBIDDEN_NAME to listOf("Manager", "Provider")))) + .compileAndLint(code) + ) + .hasSize(2) + } - @Test - fun `should report classes with forbidden names using config string`() { - val code = """ - class TestManager {} // violation - class TestProvider {} // violation - class TestHolder - """ - assertThat( - ForbiddenClassName(TestConfig(mapOf(FORBIDDEN_NAME to "Manager, Provider"))) - .compileAndLint(code) - ) - .hasSize(2) - } + @Test + fun `should report a class that starts with a forbidden name`() { + val code = "class TestProvider {}" + assertThat( + ForbiddenClassName(TestConfig(mapOf(FORBIDDEN_NAME to listOf("test")))) + .compileAndLint(code) + ) + .hasSize(1) + } - @Test - fun `should report classes with forbidden names using config string using wildcards`() { - val code = """ - class TestManager {} // violation - class TestProvider {} // violation - class TestHolder - """ - assertThat( - ForbiddenClassName(TestConfig(mapOf(FORBIDDEN_NAME to "*Manager*, *Provider*"))) - .compileAndLint(code) - ) - .hasSize(2) - } + @Test + fun `should report classes with forbidden names using config string`() { + val code = """ + class TestManager {} // violation + class TestProvider {} // violation + class TestHolder + """ + assertThat( + ForbiddenClassName(TestConfig(mapOf(FORBIDDEN_NAME to "Manager, Provider"))) + .compileAndLint(code) + ) + .hasSize(2) + } - @Test - fun `should report all forbidden names in message`() { - val code = """ - class TestManager {} - """ - val actual = ForbiddenClassName(TestConfig(mapOf(FORBIDDEN_NAME to "Test, Manager, Provider"))) + @Test + fun `should report classes with forbidden names using config string using wildcards`() { + val code = """ + class TestManager {} // violation + class TestProvider {} // violation + class TestHolder + """ + assertThat( + ForbiddenClassName(TestConfig(mapOf(FORBIDDEN_NAME to "*Manager*, *Provider*"))) .compileAndLint(code) - assertThat(actual.first().message) - .isEqualTo("Class name TestManager is forbidden as it contains: Test, Manager") - } + ) + .hasSize(2) + } + + @Test + fun `should report all forbidden names in message`() { + val code = """ + class TestManager {} + """ + val actual = ForbiddenClassName(TestConfig(mapOf(FORBIDDEN_NAME to "Test, Manager, Provider"))) + .compileAndLint(code) + assertThat(actual.first().message) + .isEqualTo("Class name TestManager is forbidden as it contains: Test, Manager") } } diff --git a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/FunctionNamingSpec.kt b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/FunctionNamingSpec.kt index d77a12f0a9b..e9c0e445a76 100644 --- a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/FunctionNamingSpec.kt +++ b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/FunctionNamingSpec.kt @@ -4,114 +4,109 @@ 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 org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class FunctionNamingSpec { - @Nested - inner class `FunctionNaming rule` { - - @Test - fun `allows FunctionName as alias for suppressing`() { - val code = """ - @Suppress("FunctionName") - fun MY_FUN() {} - """ - assertThat(FunctionNaming().compileAndLint(code)).isEmpty() - } + @Test + fun `allows FunctionName as alias for suppressing`() { + val code = """ + @Suppress("FunctionName") + fun MY_FUN() {} + """ + assertThat(FunctionNaming().compileAndLint(code)).isEmpty() + } - @Test - fun `allows anonymous functions`() { - val code = """ - val f: (Int) -> Int = fun(i: Int): Int { - return i + i - } - """ - assertThat(FunctionNaming().compileAndLint(code)).isEmpty() + @Test + fun `allows anonymous functions`() { + val code = """ + val f: (Int) -> Int = fun(i: Int): Int { + return i + i } + """ + assertThat(FunctionNaming().compileAndLint(code)).isEmpty() + } - @Test - fun `ignores functions in classes matching excludeClassPattern`() { - val code = """ - class WhateverTest { - fun SHOULD_NOT_BE_FLAGGED() {} - } - """ - val config = TestConfig(mapOf(FunctionNaming.EXCLUDE_CLASS_PATTERN to ".*Test$")) - assertThat(FunctionNaming(config).compileAndLint(code)).isEmpty() + @Test + fun `ignores functions in classes matching excludeClassPattern`() { + val code = """ + class WhateverTest { + fun SHOULD_NOT_BE_FLAGGED() {} } + """ + val config = TestConfig(mapOf(FunctionNaming.EXCLUDE_CLASS_PATTERN to ".*Test$")) + assertThat(FunctionNaming(config).compileAndLint(code)).isEmpty() + } - @Test - fun `flags functions inside functions`() { - val code = """ - class C : I { - override fun shouldNotBeFlagged() { - fun SHOULD_BE_FLAGGED() { } - } + @Test + fun `flags functions inside functions`() { + val code = """ + class C : I { + override fun shouldNotBeFlagged() { + fun SHOULD_BE_FLAGGED() { } } - interface I { fun shouldNotBeFlagged() } - """ - assertThat(FunctionNaming().compileAndLint(code)).hasSourceLocation(3, 13) } + interface I { fun shouldNotBeFlagged() } + """ + assertThat(FunctionNaming().compileAndLint(code)).hasSourceLocation(3, 13) + } - @Test - fun `ignores overridden functions by default`() { - val code = """ - class C : I { - override fun SHOULD_NOT_BE_FLAGGED() {} - } - interface I { @Suppress("FunctionNaming") fun SHOULD_NOT_BE_FLAGGED() } - """ - assertThat(FunctionNaming().compileAndLint(code)).isEmpty() + @Test + fun `ignores overridden functions by default`() { + val code = """ + class C : I { + override fun SHOULD_NOT_BE_FLAGGED() {} } + interface I { @Suppress("FunctionNaming") fun SHOULD_NOT_BE_FLAGGED() } + """ + assertThat(FunctionNaming().compileAndLint(code)).isEmpty() + } - @Test - fun `does not report when the function name is identical to the type of the result`() { - val code = """ - interface Foo - private class FooImpl : Foo + @Test + fun `does not report when the function name is identical to the type of the result`() { + val code = """ + interface Foo + private class FooImpl : Foo - fun Foo(): Foo = FooImpl() - """ - val config = TestConfig(mapOf(FunctionNaming.IGNORE_OVERRIDDEN to "false")) - assertThat(FunctionNaming(config).compileAndLint(code)).isEmpty() - } + fun Foo(): Foo = FooImpl() + """ + val config = TestConfig(mapOf(FunctionNaming.IGNORE_OVERRIDDEN to "false")) + assertThat(FunctionNaming(config).compileAndLint(code)).isEmpty() + } - @Test - fun `flags functions with bad names inside overridden functions by default`() { - val code = """ - class C : I { - override fun SHOULD_BE_FLAGGED() { - fun SHOULD_BE_FLAGGED() {} - } + @Test + fun `flags functions with bad names inside overridden functions by default`() { + val code = """ + class C : I { + override fun SHOULD_BE_FLAGGED() { + fun SHOULD_BE_FLAGGED() {} } - interface I { @Suppress("FunctionNaming") fun SHOULD_BE_FLAGGED() } - """ - assertThat(FunctionNaming().compileAndLint(code)).hasSourceLocation(3, 13) } + interface I { @Suppress("FunctionNaming") fun SHOULD_BE_FLAGGED() } + """ + assertThat(FunctionNaming().compileAndLint(code)).hasSourceLocation(3, 13) + } - @Test - fun `doesn't ignore overridden functions if ignoreOverridden is false`() { - val code = """ - class C : I { - override fun SHOULD_BE_FLAGGED() {} - } - interface I { fun SHOULD_BE_FLAGGED() } - """ - val config = TestConfig(mapOf(FunctionNaming.IGNORE_OVERRIDDEN to "false")) - assertThat(FunctionNaming(config).compileAndLint(code)).hasSourceLocations( - SourceLocation(2, 18), - SourceLocation(4, 19) - ) + @Test + fun `doesn't ignore overridden functions if ignoreOverridden is false`() { + val code = """ + class C : I { + override fun SHOULD_BE_FLAGGED() {} } + interface I { fun SHOULD_BE_FLAGGED() } + """ + val config = TestConfig(mapOf(FunctionNaming.IGNORE_OVERRIDDEN to "false")) + assertThat(FunctionNaming(config).compileAndLint(code)).hasSourceLocations( + SourceLocation(2, 18), + SourceLocation(4, 19) + ) + } - @Test - fun `doesn't allow functions with backtick`() { - val code = """ - fun `7his is a function name _`() = Unit - """ - assertThat(FunctionNaming().compileAndLint(code)).hasSourceLocations(SourceLocation(1, 5)) - } + @Test + fun `doesn't allow functions with backtick`() { + val code = """ + fun `7his is a function name _`() = Unit + """ + assertThat(FunctionNaming().compileAndLint(code)).hasSourceLocations(SourceLocation(1, 5)) } } diff --git a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/InvalidPackageDeclarationSpec.kt b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/InvalidPackageDeclarationSpec.kt index 6f2130476a1..230b8c24fda 100644 --- a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/InvalidPackageDeclarationSpec.kt +++ b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/InvalidPackageDeclarationSpec.kt @@ -14,147 +14,143 @@ private const val REQUIRE_ROOT_PACKAGE = "requireRootInDeclaration" class InvalidPackageDeclarationSpec { - @Nested - inner class `InvalidPackageDeclaration rule` { - - @Test - fun `should pass if package declaration is correct`() { - val source = """ - package foo.bar + @Test + fun `should pass if package declaration is correct`() { + val source = """ + package foo.bar - class C - """ + class C + """ - val ktFile = compileContentForTest(source, createPath("project/src/foo/bar/File.kt")) - val findings = InvalidPackageDeclaration().lint(ktFile) + val ktFile = compileContentForTest(source, createPath("project/src/foo/bar/File.kt")) + val findings = InvalidPackageDeclaration().lint(ktFile) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `should report if package declaration does not match source location`() { - val source = "package foo\n\nclass C" + @Test + fun `should report if package declaration does not match source location`() { + val source = "package foo\n\nclass C" - val ktFile = compileContentForTest(source, createPath("project/src/bar/File.kt")) - val findings = InvalidPackageDeclaration().lint(ktFile) + val ktFile = compileContentForTest(source, createPath("project/src/bar/File.kt")) + val findings = InvalidPackageDeclaration().lint(ktFile) - assertThat(findings).hasSize(1) - assertThat(findings).hasTextLocations(0 to 11) - } + assertThat(findings).hasSize(1) + assertThat(findings).hasTextLocations(0 to 11) + } - @Nested - inner class `with root package specified` { + @Nested + inner class `with root package specified` { - val config = TestConfig(mapOf(ROOT_PACKAGE to "com.example")) + val config = TestConfig(mapOf(ROOT_PACKAGE to "com.example")) - @Test - fun `should pass if file is located within the root package`() { - val source = """ - package com.example + @Test + fun `should pass if file is located within the root package`() { + val source = """ + package com.example - class C - """ + class C + """ - val ktFile = compileContentForTest(source, createPath("src/File.kt")) - val findings = InvalidPackageDeclaration(config).lint(ktFile) + val ktFile = compileContentForTest(source, createPath("src/File.kt")) + val findings = InvalidPackageDeclaration(config).lint(ktFile) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `should pass if file is located relative to root package`() { - val source = """ - package com.example.foo.bar + @Test + fun `should pass if file is located relative to root package`() { + val source = """ + package com.example.foo.bar - class C - """ + class C + """ - val ktFile = compileContentForTest(source, createPath("src/foo/bar/File.kt")) - val findings = InvalidPackageDeclaration(config).lint(ktFile) + val ktFile = compileContentForTest(source, createPath("src/foo/bar/File.kt")) + val findings = InvalidPackageDeclaration(config).lint(ktFile) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `should pass if file is located in directory corresponding to package declaration`() { - val source = """ - package com.example.foo.bar + @Test + fun `should pass if file is located in directory corresponding to package declaration`() { + val source = """ + package com.example.foo.bar - class C - """ + class C + """ - val ktFile = compileContentForTest(source, createPath("src/com/example/foo/bar/File.kt")) - val findings = InvalidPackageDeclaration(config).lint(ktFile) + val ktFile = compileContentForTest(source, createPath("src/com/example/foo/bar/File.kt")) + val findings = InvalidPackageDeclaration(config).lint(ktFile) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `should report if package declaration does not match`() { - val source = """ - package com.example.foo.baz + @Test + fun `should report if package declaration does not match`() { + val source = """ + package com.example.foo.baz - class C - """ + class C + """ - val ktFile = compileContentForTest(source, createPath("src/foo/bar/File.kt")) - val findings = InvalidPackageDeclaration(config).lint(ktFile) + val ktFile = compileContentForTest(source, createPath("src/foo/bar/File.kt")) + val findings = InvalidPackageDeclaration(config).lint(ktFile) - assertThat(findings).hasSize(1) - } + assertThat(findings).hasSize(1) + } - @Test - fun `should report if file path matches root package but package declaration differs`() { - val source = """ - package io.foo.bar + @Test + fun `should report if file path matches root package but package declaration differs`() { + val source = """ + package io.foo.bar - class C - """ + class C + """ - val ktFile = compileContentForTest(source, createPath("src/com/example/File.kt")) - val findings = InvalidPackageDeclaration(config).lint(ktFile) + val ktFile = compileContentForTest(source, createPath("src/com/example/File.kt")) + val findings = InvalidPackageDeclaration(config).lint(ktFile) - assertThat(findings).hasSize(1) - } + assertThat(findings).hasSize(1) } + } - @Nested - inner class `with root package required` { + @Nested + inner class `with root package required` { - val config = TestConfig(mapOf(ROOT_PACKAGE to "com.example", REQUIRE_ROOT_PACKAGE to true)) + val config = TestConfig(mapOf(ROOT_PACKAGE to "com.example", REQUIRE_ROOT_PACKAGE to true)) - @Test - fun `should pass if declaration starts with root package`() { - val source = """ - package com.example.foo.bar + @Test + fun `should pass if declaration starts with root package`() { + val source = """ + package com.example.foo.bar - class C - """ + class C + """ - val ktFileWithRelativePath = compileContentForTest(source, createPath("src/foo/bar/File.kt")) - val findingsForRelativePath = InvalidPackageDeclaration(config).lint(ktFileWithRelativePath) + val ktFileWithRelativePath = compileContentForTest(source, createPath("src/foo/bar/File.kt")) + val findingsForRelativePath = InvalidPackageDeclaration(config).lint(ktFileWithRelativePath) - assertThat(findingsForRelativePath).isEmpty() + assertThat(findingsForRelativePath).isEmpty() - val ktFileWithFullPath = compileContentForTest(source, createPath("src/com/example/foo/bar/File.kt")) - val findingsForFullPath = InvalidPackageDeclaration(config).lint(ktFileWithFullPath) + val ktFileWithFullPath = compileContentForTest(source, createPath("src/com/example/foo/bar/File.kt")) + val findingsForFullPath = InvalidPackageDeclaration(config).lint(ktFileWithFullPath) - assertThat(findingsForFullPath).isEmpty() - } + assertThat(findingsForFullPath).isEmpty() + } - @Test - fun `should report if root package is missing`() { - val source = """ - package foo.bar + @Test + fun `should report if root package is missing`() { + val source = """ + package foo.bar - class C - """ + class C + """ - val ktFile = compileContentForTest(source, createPath("src/foo/bar/File.kt")) - val findings = InvalidPackageDeclaration(config).lint(ktFile) + val ktFile = compileContentForTest(source, createPath("src/foo/bar/File.kt")) + val findings = InvalidPackageDeclaration(config).lint(ktFile) - assertThat(findings).hasSize(1) - } + assertThat(findings).hasSize(1) } } } diff --git a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/LambdaParameterNamingSpec.kt b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/LambdaParameterNamingSpec.kt index 0abbc6fd43f..04bab26f4ae 100644 --- a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/LambdaParameterNamingSpec.kt +++ b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/LambdaParameterNamingSpec.kt @@ -2,128 +2,124 @@ package io.gitlab.arturbosch.detekt.rules.naming import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class LambdaParameterNamingSpec { - @Nested - inner class `lambda parameters` { - @Test - fun `Reports no supported parameter names`() { - val code = """ - val a: (String) -> Unit = { HELLO_THERE -> Unit } - """ - assertThat(LambdaParameterNaming().compileAndLint(code)) - .hasSize(1) - .hasTextLocations("HELLO_THERE") - } + @Test + fun `Reports no supported parameter names`() { + val code = """ + val a: (String) -> Unit = { HELLO_THERE -> Unit } + """ + assertThat(LambdaParameterNaming().compileAndLint(code)) + .hasSize(1) + .hasTextLocations("HELLO_THERE") + } - @Test - fun `Reports no supported parameter names when there are multiple`() { - val code = """ - val a: (String, Int) -> Unit = { HI, HELLO_THERE -> Unit } - """ - assertThat(LambdaParameterNaming().compileAndLint(code)) - .hasSize(2) - .hasTextLocations("HI", "HELLO_THERE") - } + @Test + fun `Reports no supported parameter names when there are multiple`() { + val code = """ + val a: (String, Int) -> Unit = { HI, HELLO_THERE -> Unit } + """ + assertThat(LambdaParameterNaming().compileAndLint(code)) + .hasSize(2) + .hasTextLocations("HI", "HELLO_THERE") + } - @Test - fun `Doesn't report a valid parameter`() { - val code = """ - val a: (String) -> Unit = { helloThere -> Unit } - """ - assertThat(LambdaParameterNaming().compileAndLint(code)) - .isEmpty() - } + @Test + fun `Doesn't report a valid parameter`() { + val code = """ + val a: (String) -> Unit = { helloThere -> Unit } + """ + assertThat(LambdaParameterNaming().compileAndLint(code)) + .isEmpty() + } - @Test - fun `Doesn't report a valid parameter when define type`() { - val code = """ - val a = { helloThere: String -> Unit } - """ - assertThat(LambdaParameterNaming().compileAndLint(code)) - .isEmpty() - } + @Test + fun `Doesn't report a valid parameter when define type`() { + val code = """ + val a = { helloThere: String -> Unit } + """ + assertThat(LambdaParameterNaming().compileAndLint(code)) + .isEmpty() + } - @Test - fun `Doesn't report _`() { - val code = """ - val a: (String) -> Unit = { _ -> Unit } - """ - assertThat(LambdaParameterNaming().compileAndLint(code)) - .isEmpty() - } + @Test + fun `Doesn't report _`() { + val code = """ + val a: (String) -> Unit = { _ -> Unit } + """ + assertThat(LambdaParameterNaming().compileAndLint(code)) + .isEmpty() + } - @Test - fun `Doesn't report by using implicit name`() { - val code = """ - val a: (String) -> Unit = { Unit } - """ - assertThat(LambdaParameterNaming().compileAndLint(code)) - .isEmpty() - } + @Test + fun `Doesn't report by using implicit name`() { + val code = """ + val a: (String) -> Unit = { Unit } + """ + assertThat(LambdaParameterNaming().compileAndLint(code)) + .isEmpty() + } - @Test - fun `Doesn't report if there aren't parameters`() { - val code = """ - val a: () -> Unit = { Unit } - """ - assertThat(LambdaParameterNaming().compileAndLint(code)) - .isEmpty() - } + @Test + fun `Doesn't report if there aren't parameters`() { + val code = """ + val a: () -> Unit = { Unit } + """ + assertThat(LambdaParameterNaming().compileAndLint(code)) + .isEmpty() + } - @Test - fun `Reports no supported destructuring parameter names`() { - val code = """ - data class Bar(val a: String) - val a: (Bar) -> Unit = { (HELLO_THERE) -> Unit } - """ - assertThat(LambdaParameterNaming().compileAndLint(code)) - .hasSize(1) - .hasTextLocations("HELLO_THERE") - } + @Test + fun `Reports no supported destructuring parameter names`() { + val code = """ + data class Bar(val a: String) + val a: (Bar) -> Unit = { (HELLO_THERE) -> Unit } + """ + assertThat(LambdaParameterNaming().compileAndLint(code)) + .hasSize(1) + .hasTextLocations("HELLO_THERE") + } - @Test - fun `Reports no supported destructuring parameter names when there are multiple`() { - val code = """ - data class Bar(val a: String, val b: String) - val a: (Bar) -> Unit = { (HI, HELLO_THERE) -> Unit } - """ - assertThat(LambdaParameterNaming().compileAndLint(code)) - .hasSize(2) - .hasTextLocations("HI", "HELLO_THERE") - } + @Test + fun `Reports no supported destructuring parameter names when there are multiple`() { + val code = """ + data class Bar(val a: String, val b: String) + val a: (Bar) -> Unit = { (HI, HELLO_THERE) -> Unit } + """ + assertThat(LambdaParameterNaming().compileAndLint(code)) + .hasSize(2) + .hasTextLocations("HI", "HELLO_THERE") + } - @Test - fun `Doesn't report valid destructuring parameters`() { - val code = """ - data class Bar(val a: String, val b: String) - val a: (Bar) -> Unit = { (a, b) -> Unit } - """ - assertThat(LambdaParameterNaming().compileAndLint(code)) - .isEmpty() - } + @Test + fun `Doesn't report valid destructuring parameters`() { + val code = """ + data class Bar(val a: String, val b: String) + val a: (Bar) -> Unit = { (a, b) -> Unit } + """ + assertThat(LambdaParameterNaming().compileAndLint(code)) + .isEmpty() + } - @Test - fun `Doesn't report valid destructuring parameters when define type`() { - val code = """ - data class Bar(val a: String, val b: String) - val a: (Bar) -> Unit = { (a: String, b) -> Unit } - """ - assertThat(LambdaParameterNaming().compileAndLint(code)) - .isEmpty() - } + @Test + fun `Doesn't report valid destructuring parameters when define type`() { + val code = """ + data class Bar(val a: String, val b: String) + val a: (Bar) -> Unit = { (a: String, b) -> Unit } + """ + assertThat(LambdaParameterNaming().compileAndLint(code)) + .isEmpty() + } - @Test - fun `Doesn't report valid destructuring parameters using _`() { - val code = """ - data class Bar(val a: String, val b: String) - val a: (Bar) -> Unit = { (_, b) -> Unit } - """ - assertThat(LambdaParameterNaming().compileAndLint(code)) - .isEmpty() - } + @Test + fun `Doesn't report valid destructuring parameters using _`() { + val code = """ + data class Bar(val a: String, val b: String) + val a: (Bar) -> Unit = { (_, b) -> Unit } + """ + assertThat(LambdaParameterNaming().compileAndLint(code)) + .isEmpty() } } diff --git a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/MatchingDeclarationNameSpec.kt b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/MatchingDeclarationNameSpec.kt index ecf14e6d68a..123b56d201c 100644 --- a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/MatchingDeclarationNameSpec.kt +++ b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/MatchingDeclarationNameSpec.kt @@ -10,212 +10,208 @@ import org.junit.jupiter.api.Test class MatchingDeclarationNameSpec { @Nested - inner class `MatchingDeclarationName rule` { - - @Nested - inner class `compliant test cases` { - - @Test - fun `should pass for object declaration`() { - val ktFile = compileContentForTest("object O", filename = "O.kt") - val findings = MatchingDeclarationName().lint(ktFile) - assertThat(findings).isEmpty() - } - - @Test - fun `should pass for suppress`() { - val ktFile = compileContentForTest( - """@file:Suppress("MatchingDeclarationName") object O""", - filename = "Objects.kt" - ) - val findings = MatchingDeclarationName().lint(ktFile) - assertThat(findings).isEmpty() - } - - @Test - fun `should pass for class declaration`() { - val ktFile = compileContentForTest("class C", filename = "C.kt") - val findings = MatchingDeclarationName().lint(ktFile) - assertThat(findings).isEmpty() - } - - @Test - fun `should pass for interface declaration`() { - val ktFile = compileContentForTest("interface I", filename = "I.kt") - val findings = MatchingDeclarationName().lint(ktFile) - assertThat(findings).isEmpty() - } - - @Test - fun `should pass for enum declaration`() { - val ktFile = compileContentForTest( - """ - enum class E { - ONE, TWO, THREE - } - """, - filename = "E.kt" - ) - val findings = MatchingDeclarationName().lint(ktFile) - assertThat(findings).isEmpty() - } - - @Test - fun `should pass for multiple declaration`() { - val ktFile = compileContentForTest( - """ - class C - object O - fun a() = 5 - """, - filename = "MultiDeclarations.kt" - ) - val findings = MatchingDeclarationName().lint(ktFile) - assertThat(findings).isEmpty() - } - - @Test - fun `should pass for class declaration with utility functions`() { - val ktFile = compileContentForTest( - """ - class C - fun a() = 5 - fun C.b() = 5 - """, - filename = "C.kt" - ) - val findings = MatchingDeclarationName().lint(ktFile) - assertThat(findings).isEmpty() - } - - @Test - fun `should pass for class declaration not as first declaration with utility functions`() { - val ktFile = compileContentForTest( - """ - fun a() = 5 - fun C.b() = 5 - class C - """, - filename = "Classes.kt" - ) - val findings = MatchingDeclarationName().lint(ktFile) - assertThat(findings).isEmpty() - } - - @Test - fun `should pass for private class declaration`() { - val ktFile = compileContentForTest( - """ - private class C + inner class `compliant test cases` { + + @Test + fun `should pass for object declaration`() { + val ktFile = compileContentForTest("object O", filename = "O.kt") + val findings = MatchingDeclarationName().lint(ktFile) + assertThat(findings).isEmpty() + } + + @Test + fun `should pass for suppress`() { + val ktFile = compileContentForTest( + """@file:Suppress("MatchingDeclarationName") object O""", + filename = "Objects.kt" + ) + val findings = MatchingDeclarationName().lint(ktFile) + assertThat(findings).isEmpty() + } + + @Test + fun `should pass for class declaration`() { + val ktFile = compileContentForTest("class C", filename = "C.kt") + val findings = MatchingDeclarationName().lint(ktFile) + assertThat(findings).isEmpty() + } + + @Test + fun `should pass for interface declaration`() { + val ktFile = compileContentForTest("interface I", filename = "I.kt") + val findings = MatchingDeclarationName().lint(ktFile) + assertThat(findings).isEmpty() + } + + @Test + fun `should pass for enum declaration`() { + val ktFile = compileContentForTest( + """ + enum class E { + ONE, TWO, THREE + } + """, + filename = "E.kt" + ) + val findings = MatchingDeclarationName().lint(ktFile) + assertThat(findings).isEmpty() + } + + @Test + fun `should pass for multiple declaration`() { + val ktFile = compileContentForTest( + """ + class C + object O fun a() = 5 - """, - filename = "b.kt" - ) - val findings = MatchingDeclarationName().lint(ktFile) - assertThat(findings).isEmpty() - } - - @Test - fun `should pass for a class with a typealias`() { - val code = """ - typealias Foo = FooImpl + """, + filename = "MultiDeclarations.kt" + ) + val findings = MatchingDeclarationName().lint(ktFile) + assertThat(findings).isEmpty() + } - class FooImpl {} + @Test + fun `should pass for class declaration with utility functions`() { + val ktFile = compileContentForTest( + """ + class C + fun a() = 5 + fun C.b() = 5 + """, + filename = "C.kt" + ) + val findings = MatchingDeclarationName().lint(ktFile) + assertThat(findings).isEmpty() + } + + @Test + fun `should pass for class declaration not as first declaration with utility functions`() { + val ktFile = compileContentForTest( + """ + fun a() = 5 + fun C.b() = 5 + class C + """, + filename = "Classes.kt" + ) + val findings = MatchingDeclarationName().lint(ktFile) + assertThat(findings).isEmpty() + } + + @Test + fun `should pass for private class declaration`() { + val ktFile = compileContentForTest( + """ + private class C + fun a() = 5 + """, + filename = "b.kt" + ) + val findings = MatchingDeclarationName().lint(ktFile) + assertThat(findings).isEmpty() + } + + @Test + fun `should pass for a class with a typealias`() { + val code = """ + typealias Foo = FooImpl + + class FooImpl {} + """ + val ktFile = compileContentForTest(code, filename = "Foo.kt") + val findings = MatchingDeclarationName().lint(ktFile) + assertThat(findings).isEmpty() + } + } + + @Nested + inner class `non-compliant test cases` { + + @Test + fun `should not pass for object declaration`() { + val ktFile = compileContentForTest("object O", filename = "Objects.kt") + val findings = MatchingDeclarationName().lint(ktFile) + assertThat(findings).hasSourceLocation(1, 1) + } + + @Test + fun `should not pass for object declaration even with suppress on the object`() { + val ktFile = compileContentForTest( + """@Suppress("MatchingDeclarationName") object O""", + filename = "Objects.kt" + ) + val findings = MatchingDeclarationName().lint(ktFile) + assertThat(findings).hasSourceLocation(1, 1) + } + + @Test + fun `should not pass for class declaration`() { + val ktFile = compileContentForTest("class C", filename = "Classes.kt") + val findings = MatchingDeclarationName().lint(ktFile) + assertThat(findings).hasSourceLocation(1, 1) + } + + @Test + fun `should not pass for class declaration as first declaration with utility functions`() { + val ktFile = compileContentForTest( """ - val ktFile = compileContentForTest(code, filename = "Foo.kt") - val findings = MatchingDeclarationName().lint(ktFile) - assertThat(findings).isEmpty() - } - } - - @Nested - inner class `non-compliant test cases` { - - @Test - fun `should not pass for object declaration`() { - val ktFile = compileContentForTest("object O", filename = "Objects.kt") - val findings = MatchingDeclarationName().lint(ktFile) - assertThat(findings).hasSourceLocation(1, 1) - } - - @Test - fun `should not pass for object declaration even with suppress on the object`() { - val ktFile = compileContentForTest( - """@Suppress("MatchingDeclarationName") object O""", - filename = "Objects.kt" - ) - val findings = MatchingDeclarationName().lint(ktFile) - assertThat(findings).hasSourceLocation(1, 1) - } - - @Test - fun `should not pass for class declaration`() { - val ktFile = compileContentForTest("class C", filename = "Classes.kt") - val findings = MatchingDeclarationName().lint(ktFile) - assertThat(findings).hasSourceLocation(1, 1) - } - - @Test - fun `should not pass for class declaration as first declaration with utility functions`() { - val ktFile = compileContentForTest( - """ - class C - fun a() = 5 - fun C.b() = 5 - """.trimIndent(), - filename = "ClassUtils.kt" - ) - val findings = MatchingDeclarationName().lint(ktFile) - assertThat(findings).hasSourceLocation(1, 1) - } - - @Test - fun `should not pass for interface declaration`() { - val ktFile = compileContentForTest("interface I", filename = "Not_I.kt") - val findings = MatchingDeclarationName().lint(ktFile) - assertThat(findings).hasSourceLocation(1, 1) - } - - @Test - fun `should not pass for enum declaration`() { - val ktFile = compileContentForTest( - """ - enum class NOT_E { - ONE, TWO, THREE - } - """.trimIndent(), - filename = "E.kt" - ) - val findings = MatchingDeclarationName().lint(ktFile) - assertThat(findings).hasSourceLocation(1, 1) - } - - @Test - fun `should not pass for a typealias with a different name`() { - val code = """ - class FooImpl {} - typealias Bar = FooImpl + class C + fun a() = 5 + fun C.b() = 5 + """.trimIndent(), + filename = "ClassUtils.kt" + ) + val findings = MatchingDeclarationName().lint(ktFile) + assertThat(findings).hasSourceLocation(1, 1) + } + + @Test + fun `should not pass for interface declaration`() { + val ktFile = compileContentForTest("interface I", filename = "Not_I.kt") + val findings = MatchingDeclarationName().lint(ktFile) + assertThat(findings).hasSourceLocation(1, 1) + } + + @Test + fun `should not pass for enum declaration`() { + val ktFile = compileContentForTest( + """ + enum class NOT_E { + ONE, TWO, THREE + } + """.trimIndent(), + filename = "E.kt" + ) + val findings = MatchingDeclarationName().lint(ktFile) + assertThat(findings).hasSourceLocation(1, 1) + } + + @Test + fun `should not pass for a typealias with a different name`() { + val code = """ + class FooImpl {} + typealias Bar = FooImpl + """ + val ktFile = compileContentForTest(code, filename = "Foo.kt") + val findings = MatchingDeclarationName().lint(ktFile) + assertThat(findings).hasSize(1) + } + + @Test + fun `should not pass for class declaration not as first declaration with utility functions when mustBeFirst is false`() { + val ktFile = compileContentForTest( """ - val ktFile = compileContentForTest(code, filename = "Foo.kt") - val findings = MatchingDeclarationName().lint(ktFile) - assertThat(findings).hasSize(1) - } - - @Test - fun `should not pass for class declaration not as first declaration with utility functions when mustBeFirst is false`() { - val ktFile = compileContentForTest( - """ - fun a() = 5 - fun C.b() = 5 - class C - """, - filename = "Classes.kt" - ) - val findings = MatchingDeclarationName( - TestConfig("mustBeFirst" to "false") - ).lint(ktFile) - assertThat(findings).hasSourceLocation(4, 21) - } + fun a() = 5 + fun C.b() = 5 + class C + """.trimIndent(), + filename = "Classes.kt" + ) + val findings = MatchingDeclarationName( + TestConfig("mustBeFirst" to "false") + ).lint(ktFile) + assertThat(findings).hasSourceLocation(3, 1) } } } diff --git a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/MemberNameEqualsClassNameSpec.kt b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/MemberNameEqualsClassNameSpec.kt index 1f6799ecfa8..598fafb3d90 100644 --- a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/MemberNameEqualsClassNameSpec.kt +++ b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/MemberNameEqualsClassNameSpec.kt @@ -17,289 +17,285 @@ private const val IGNORE_OVERRIDDEN = "ignoreOverridden" class MemberNameEqualsClassNameSpec(val env: KotlinCoreEnvironment) { val subject = MemberNameEqualsClassName(Config.empty) - @Nested - inner class `MemberNameEqualsClassName rule` { - - val noIgnoreOverridden = - TestConfig( - mapOf( - IGNORE_OVERRIDDEN to "false" - ) + val noIgnoreOverridden = + TestConfig( + mapOf( + IGNORE_OVERRIDDEN to "false" ) + ) - @Nested - inner class `some classes with methods which don't have the same name` { - - @Test - fun `does not report a nested function with the same name as the class`() { - val code = """ - class MethodNameNotEqualsClassName { - fun nestedFunction() { - fun MethodNameNotEqualsClassName() {} - } + @Nested + inner class `some classes with methods which don't have the same name` { + + @Test + fun `does not report a nested function with the same name as the class`() { + val code = """ + class MethodNameNotEqualsClassName { + fun nestedFunction() { + fun MethodNameNotEqualsClassName() {} } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report a function with same name in nested class`() { - val code = """ - class MethodNameNotEqualsClassName { - class NestedNameEqualsTopClassName { - fun MethodNameNotEqualsClassName() {} - } + @Test + fun `does not report a function with same name in nested class`() { + val code = """ + class MethodNameNotEqualsClassName { + class NestedNameEqualsTopClassName { + fun MethodNameNotEqualsClassName() {} } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report a function with the same name as a companion object`() { - val code = """ - class StaticMethodNameEqualsObjectName { - companion object A { - fun A() {} - } + @Test + fun `does not report a function with the same name as a companion object`() { + val code = """ + class StaticMethodNameEqualsObjectName { + companion object A { + fun A() {} } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } + } - @Nested - inner class `some classes with members which have the same name` { + @Nested + inner class `some classes with members which have the same name` { - @Test - fun `reports a method which is named after the class`() { - val code = """ - class MethodNameEqualsClassName { - fun methodNameEqualsClassName() {} - } - """ - assertThat(MemberNameEqualsClassName().compileAndLint(code)).hasSize(1) - } + @Test + fun `reports a method which is named after the class`() { + val code = """ + class MethodNameEqualsClassName { + fun methodNameEqualsClassName() {} + } + """ + assertThat(MemberNameEqualsClassName().compileAndLint(code)).hasSize(1) + } - @Test - fun `reports a method which is named after the object`() { - val code = """ - object MethodNameEqualsObjectName { - fun MethodNameEqualsObjectName() {} - } - """ - assertThat(MemberNameEqualsClassName().compileAndLint(code)).hasSize(1) - } + @Test + fun `reports a method which is named after the object`() { + val code = """ + object MethodNameEqualsObjectName { + fun MethodNameEqualsObjectName() {} + } + """ + assertThat(MemberNameEqualsClassName().compileAndLint(code)).hasSize(1) + } - @Test - fun `reports a property which is named after the class`() { - val code = """ - class PropertyNameEqualsClassName { - val propertyNameEqualsClassName = 0 - } - """ - assertThat(MemberNameEqualsClassName().compileAndLint(code)).hasSize(1) - } + @Test + fun `reports a property which is named after the class`() { + val code = """ + class PropertyNameEqualsClassName { + val propertyNameEqualsClassName = 0 + } + """ + assertThat(MemberNameEqualsClassName().compileAndLint(code)).hasSize(1) + } - @Test - fun `reports a property which is named after the object`() { - val code = """ - object PropertyNameEqualsObjectName { - val propertyNameEqualsObjectName = 0 - } - """ - assertThat(MemberNameEqualsClassName().compileAndLint(code)).hasSize(1) - } + @Test + fun `reports a property which is named after the object`() { + val code = """ + object PropertyNameEqualsObjectName { + val propertyNameEqualsObjectName = 0 + } + """ + assertThat(MemberNameEqualsClassName().compileAndLint(code)).hasSize(1) + } - @Test - fun `reports a companion object function which is named after the class`() { - val code = """ - class StaticMethodNameEqualsClassName { - companion object { - fun StaticMethodNameEqualsClassName() {} - } + @Test + fun `reports a companion object function which is named after the class`() { + val code = """ + class StaticMethodNameEqualsClassName { + companion object { + fun StaticMethodNameEqualsClassName() {} } - """ - assertThat(MemberNameEqualsClassName().compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(MemberNameEqualsClassName().compileAndLint(code)).hasSize(1) + } - @Test - fun `reports a method which is named after the class even when it's inside another one`() { - val code = """ - class MethodNameContainer { - class MethodNameEqualsNestedClassName { - fun MethodNameEqualsNestedClassName() {} - } + @Test + fun `reports a method which is named after the class even when it's inside another one`() { + val code = """ + class MethodNameContainer { + class MethodNameEqualsNestedClassName { + fun MethodNameEqualsNestedClassName() {} } - """ - assertThat(MemberNameEqualsClassName().compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(MemberNameEqualsClassName().compileAndLint(code)).hasSize(1) + } - @Test - fun `doesn't report overridden methods which are named after the class`() { - val code = """ - class AbstractMethodNameEqualsClassName : BaseClassForMethodNameEqualsClassName() { - override fun AbstractMethodNameEqualsClassName() {} - } - abstract class BaseClassForMethodNameEqualsClassName { - abstract fun AbstractMethodNameEqualsClassName() - } - """ - assertThat(MemberNameEqualsClassName().compileAndLint(code)).isEmpty() - } + @Test + fun `doesn't report overridden methods which are named after the class`() { + val code = """ + class AbstractMethodNameEqualsClassName : BaseClassForMethodNameEqualsClassName() { + override fun AbstractMethodNameEqualsClassName() {} + } + abstract class BaseClassForMethodNameEqualsClassName { + abstract fun AbstractMethodNameEqualsClassName() + } + """ + assertThat(MemberNameEqualsClassName().compileAndLint(code)).isEmpty() + } - @Test - fun `doesn't report an methods which are named after the interface`() { - val code = """ - interface MethodNameEqualsInterfaceName { - fun MethodNameEqualsInterfaceName() {} - } - """ - assertThat(MemberNameEqualsClassName().compileAndLint(code)).isEmpty() - } + @Test + fun `doesn't report an methods which are named after the interface`() { + val code = """ + interface MethodNameEqualsInterfaceName { + fun MethodNameEqualsInterfaceName() {} + } + """ + assertThat(MemberNameEqualsClassName().compileAndLint(code)).isEmpty() + } - @Test - fun `reports overridden methods which are named after the class if they are not ignored`() { - val code = """ - class AbstractMethodNameEqualsClassName : BaseClassForMethodNameEqualsClassName() { - override fun AbstractMethodNameEqualsClassName() {} - } - abstract class BaseClassForMethodNameEqualsClassName { - abstract fun AbstractMethodNameEqualsClassName() - } - """ - assertThat(MemberNameEqualsClassName(noIgnoreOverridden).compileAndLint(code)).hasSize(1) - } + @Test + fun `reports overridden methods which are named after the class if they are not ignored`() { + val code = """ + class AbstractMethodNameEqualsClassName : BaseClassForMethodNameEqualsClassName() { + override fun AbstractMethodNameEqualsClassName() {} + } + abstract class BaseClassForMethodNameEqualsClassName { + abstract fun AbstractMethodNameEqualsClassName() + } + """ + assertThat(MemberNameEqualsClassName(noIgnoreOverridden).compileAndLint(code)).hasSize(1) + } - @Test - fun `doesn't report overridden properties which are named after the class`() { - val code = """ - class AbstractMethodNameEqualsClassName : BaseClassForMethodNameEqualsClassName() { - override val AbstractMethodNameEqualsClassName = "" - } - abstract class BaseClassForMethodNameEqualsClassName { - abstract val AbstractMethodNameEqualsClassName: String - } - """ - assertThat(MemberNameEqualsClassName().compileAndLint(code)).isEmpty() - } + @Test + fun `doesn't report overridden properties which are named after the class`() { + val code = """ + class AbstractMethodNameEqualsClassName : BaseClassForMethodNameEqualsClassName() { + override val AbstractMethodNameEqualsClassName = "" + } + abstract class BaseClassForMethodNameEqualsClassName { + abstract val AbstractMethodNameEqualsClassName: String + } + """ + assertThat(MemberNameEqualsClassName().compileAndLint(code)).isEmpty() + } - @Test - fun `reports overridden properties which are named after the class if they are not ignored`() { - val code = """ - class AbstractMethodNameEqualsClassName : BaseClassForMethodNameEqualsClassName() { - override val AbstractMethodNameEqualsClassName = "" - } - abstract class BaseClassForMethodNameEqualsClassName { - abstract val AbstractMethodNameEqualsClassName: String - } - """ - assertThat(MemberNameEqualsClassName(noIgnoreOverridden).compileAndLint(code)).hasSize(1) - } + @Test + fun `reports overridden properties which are named after the class if they are not ignored`() { + val code = """ + class AbstractMethodNameEqualsClassName : BaseClassForMethodNameEqualsClassName() { + override val AbstractMethodNameEqualsClassName = "" + } + abstract class BaseClassForMethodNameEqualsClassName { + abstract val AbstractMethodNameEqualsClassName: String + } + """ + assertThat(MemberNameEqualsClassName(noIgnoreOverridden).compileAndLint(code)).hasSize(1) } + } - @Nested - inner class `some companion object functions named after the class (factory functions)` { + @Nested + inner class `some companion object functions named after the class (factory functions)` { - @Test - fun `reports a function which has no return type`() { - val code = """ - class WrongFactoryClass1 { + @Test + fun `reports a function which has no return type`() { + val code = """ + class WrongFactoryClass1 { - companion object { - fun wrongFactoryClass1() {} - } + companion object { + fun wrongFactoryClass1() {} } - """ - assertThat(MemberNameEqualsClassName().compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(MemberNameEqualsClassName().compileAndLint(code)).hasSize(1) + } - @Test - fun `reports a function which has the wrong return type`() { - val code = """ - class WrongFactoryClass2 { - - companion object { - fun wrongFactoryClass2(): Int { - return 0 - } + @Test + fun `reports a function which has the wrong return type`() { + val code = """ + class WrongFactoryClass2 { + + companion object { + fun wrongFactoryClass2(): Int { + return 0 } } - """ - assertThat(MemberNameEqualsClassName().compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(MemberNameEqualsClassName().compileAndLint(code)).hasSize(1) + } - @Test - fun `reports a body-less function which has the wrong return type`() { - val code = """ - class WrongFactoryClass3 { - - companion object { - fun wrongFactoryClass3() = 0 - } + @Test + fun `reports a body-less function which has the wrong return type`() { + val code = """ + class WrongFactoryClass3 { + + companion object { + fun wrongFactoryClass3() = 0 } - """ - assertThat(MemberNameEqualsClassName().compileAndLintWithContext(env, code)).hasSize(1) - } + } + """ + assertThat(MemberNameEqualsClassName().compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `doesn't report a factory function`() { - val code = """ - open class A { - companion object { - fun a(condition: Boolean): A { - return if (condition) B() else C() - } + @Test + fun `doesn't report a factory function`() { + val code = """ + open class A { + companion object { + fun a(condition: Boolean): A { + return if (condition) B() else C() } } - - class B: A() - - class C: A() - """ - assertThat(MemberNameEqualsClassName().compileAndLintWithContext(env, code)).isEmpty() - } + } + + class B: A() + + class C: A() + """ + assertThat(MemberNameEqualsClassName().compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `doesn't report a generic factory function`() { - val code = """ - data class GenericClass(val wrapped: T) { - companion object { - fun genericClass(wrapped: T): GenericClass { - return GenericClass(wrapped) - } - fun genericClass(): GenericClass { - return GenericClass("wrapped") - } + @Test + fun `doesn't report a generic factory function`() { + val code = """ + data class GenericClass(val wrapped: T) { + companion object { + fun genericClass(wrapped: T): GenericClass { + return GenericClass(wrapped) + } + fun genericClass(): GenericClass { + return GenericClass("wrapped") } } - """ - assertThat(MemberNameEqualsClassName().compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(MemberNameEqualsClassName().compileAndLintWithContext(env, code)).isEmpty() + } - @Nested - @DisplayName("doesn't report a body-less factory function") - inner class IgnoreBodylessFactoryFunction { - val code = """ - open class A { - companion object { - fun a(condition: Boolean) = if (condition) B() else C() - } - } - - class B: A() + @Nested + @DisplayName("doesn't report a body-less factory function") + inner class IgnoreBodylessFactoryFunction { + val code = """ + open class A { + companion object { + fun a(condition: Boolean) = if (condition) B() else C() + } + } + + class B: A() - class C: A() - """ + class C: A() + """ - @Test - fun `with type solving`() { - assertThat(MemberNameEqualsClassName().compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `with type solving`() { + assertThat(MemberNameEqualsClassName().compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `without type solving`() { - assertThat(MemberNameEqualsClassName().compileAndLint(code)).isEmpty() - } + @Test + fun `without type solving`() { + assertThat(MemberNameEqualsClassName().compileAndLint(code)).isEmpty() } } } diff --git a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NamingConventionCustomPatternSpec.kt b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NamingConventionCustomPatternSpec.kt index 40f69bd260f..9e80565fa30 100644 --- a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NamingConventionCustomPatternSpec.kt +++ b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NamingConventionCustomPatternSpec.kt @@ -4,7 +4,6 @@ import io.gitlab.arturbosch.detekt.test.TestConfig import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatExceptionOfType -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import java.util.regex.PatternSyntaxException @@ -65,131 +64,127 @@ class NamingConventionCustomPatternSpec { } """ - @Nested - inner class `NamingRules rule` { - - @Test - fun `should use custom name for method and class`() { - val rule = NamingRules(testConfig) - assertThat( - rule.compileAndLint( - """ - class aBbD{ - fun `name with back ticks`(){ - val `123var` = "" - } - - companion object { - const val lowerCaseConst = "" - } + @Test + fun `should use custom name for method and class`() { + val rule = NamingRules(testConfig) + assertThat( + rule.compileAndLint( + """ + class aBbD{ + fun `name with back ticks`(){ + val `123var` = "" } - """ - ) - ).isEmpty() - } - @Test - fun `should use custom name for constant`() { - val rule = NamingRules(testConfig) - assertThat( - rule.compileAndLint( - """ - class aBbD{ - companion object { - const val lowerCaseConst = "" - } + companion object { + const val lowerCaseConst = "" } - """ - ) - ).isEmpty() } + """ + ) + ).isEmpty() + } - @Test - fun `should use custom name for enum`() { - val rule = NamingRules(testConfig) - assertThat( - rule.compileAndLint( - """ - class aBbD{ - enum class aBbD { - enum1, enum2 - } + @Test + fun `should use custom name for constant`() { + val rule = NamingRules(testConfig) + assertThat( + rule.compileAndLint( + """ + class aBbD{ + companion object { + const val lowerCaseConst = "" } - """ - ) - ).isEmpty() } + """ + ) + ).isEmpty() + } - @Test - fun `should use custom name for package`() { - val rule = NamingRules(testConfig) - assertThat(rule.compileAndLint("package package_1")).isEmpty() + @Test + fun `should use custom name for enum`() { + val rule = NamingRules(testConfig) + assertThat( + rule.compileAndLint( + """ + class aBbD{ + enum class aBbD { + enum1, enum2 + } } + """ + ) + ).isEmpty() + } - @Test - fun shouldExcludeClassesFromVariableNaming() { - val code = """ - class Bar { - val MYVar = 3 - } + @Test + fun `should use custom name for package`() { + val rule = NamingRules(testConfig) + assertThat(rule.compileAndLint("package package_1")).isEmpty() + } - object Foo { - val MYVar = 3 - } - """ - val config = TestConfig(mapOf(VariableNaming.EXCLUDE_CLASS_PATTERN to "Foo|Bar")) - assertThat(VariableNaming(config).compileAndLint(code)).isEmpty() + @Test + fun shouldExcludeClassesFromVariableNaming() { + val code = """ + class Bar { + val MYVar = 3 } - @Test - fun shouldNotFailWithInvalidRegexWhenDisabledVariableNaming() { - val configValues = mapOf( - "active" to "false", - VariableNaming.EXCLUDE_CLASS_PATTERN to "*Foo" - ) - val config = TestConfig(configValues) - assertThat(VariableNaming(config).compileAndLint(excludeClassPatternVariableRegexCode)).isEmpty() + object Foo { + val MYVar = 3 } + """ + val config = TestConfig(mapOf(VariableNaming.EXCLUDE_CLASS_PATTERN to "Foo|Bar")) + assertThat(VariableNaming(config).compileAndLint(code)).isEmpty() + } - @Test - fun shouldFailWithInvalidRegexVariableNaming() { - val config = TestConfig(mapOf(VariableNaming.EXCLUDE_CLASS_PATTERN to "*Foo")) - assertThatExceptionOfType(PatternSyntaxException::class.java).isThrownBy { - VariableNaming(config).compileAndLint(excludeClassPatternVariableRegexCode) - } - } + @Test + fun shouldNotFailWithInvalidRegexWhenDisabledVariableNaming() { + val configValues = mapOf( + "active" to "false", + VariableNaming.EXCLUDE_CLASS_PATTERN to "*Foo" + ) + val config = TestConfig(configValues) + assertThat(VariableNaming(config).compileAndLint(excludeClassPatternVariableRegexCode)).isEmpty() + } - @Test - fun shouldExcludeClassesFromFunctionNaming() { - val code = """ - class Bar { - fun MYFun() {} - } + @Test + fun shouldFailWithInvalidRegexVariableNaming() { + val config = TestConfig(mapOf(VariableNaming.EXCLUDE_CLASS_PATTERN to "*Foo")) + assertThatExceptionOfType(PatternSyntaxException::class.java).isThrownBy { + VariableNaming(config).compileAndLint(excludeClassPatternVariableRegexCode) + } + } - object Foo { - fun MYFun() {} - } - """ - val config = TestConfig(mapOf(FunctionNaming.EXCLUDE_CLASS_PATTERN to "Foo|Bar")) - assertThat(FunctionNaming(config).compileAndLint(code)).isEmpty() + @Test + fun shouldExcludeClassesFromFunctionNaming() { + val code = """ + class Bar { + fun MYFun() {} } - @Test - fun shouldNotFailWithInvalidRegexWhenDisabledFunctionNaming() { - val configRules = mapOf( - "active" to "false", - FunctionNaming.EXCLUDE_CLASS_PATTERN to "*Foo" - ) - val config = TestConfig(configRules) - assertThat(FunctionNaming(config).compileAndLint(excludeClassPatternFunctionRegexCode)).isEmpty() + object Foo { + fun MYFun() {} } + """ + val config = TestConfig(mapOf(FunctionNaming.EXCLUDE_CLASS_PATTERN to "Foo|Bar")) + assertThat(FunctionNaming(config).compileAndLint(code)).isEmpty() + } - @Test - fun shouldFailWithInvalidRegexFunctionNaming() { - val config = TestConfig(mapOf(FunctionNaming.EXCLUDE_CLASS_PATTERN to "*Foo")) - assertThatExceptionOfType(PatternSyntaxException::class.java).isThrownBy { - FunctionNaming(config).compileAndLint(excludeClassPatternFunctionRegexCode) - } + @Test + fun shouldNotFailWithInvalidRegexWhenDisabledFunctionNaming() { + val configRules = mapOf( + "active" to "false", + FunctionNaming.EXCLUDE_CLASS_PATTERN to "*Foo" + ) + val config = TestConfig(configRules) + assertThat(FunctionNaming(config).compileAndLint(excludeClassPatternFunctionRegexCode)).isEmpty() + } + + @Test + fun shouldFailWithInvalidRegexFunctionNaming() { + val config = TestConfig(mapOf(FunctionNaming.EXCLUDE_CLASS_PATTERN to "*Foo")) + assertThatExceptionOfType(PatternSyntaxException::class.java).isThrownBy { + FunctionNaming(config).compileAndLint(excludeClassPatternFunctionRegexCode) } } } diff --git a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NamingConventionLengthSpec.kt b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NamingConventionLengthSpec.kt index 7083aa2e7e6..6df83b026ee 100644 --- a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NamingConventionLengthSpec.kt +++ b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NamingConventionLengthSpec.kt @@ -8,107 +8,103 @@ import org.junit.jupiter.api.Test class NamingConventionLengthSpec { + @Test + fun `should not report underscore variable names`() { + val subject = NamingRules() + val code = """ + fun getResult(): Pair = TODO() + fun function() { + val (_, status) = getResult() + } + """ + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } + + @Test + fun `should not report a variable with single letter name`() { + val subject = NamingRules() + val code = "private val a = 3" + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } + @Nested - inner class `NamingRules rule` { + inner class `VariableMinLength rule with a custom minimum length` { - @Test - fun `should not report underscore variable names`() { - val subject = NamingRules() - val code = """ - fun getResult(): Pair = TODO() - fun function() { - val (_, status) = getResult() - } - """ - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() - } + val variableMinLength = + VariableMinLength(TestConfig(mapOf(VariableMinLength.MINIMUM_VARIABLE_NAME_LENGTH to "2"))) @Test - fun `should not report a variable with single letter name`() { - val subject = NamingRules() + fun `reports a very short variable name`() { val code = "private val a = 3" - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() + assertThat(variableMinLength.compileAndLint(code)).hasSize(1) } - @Nested - inner class `VariableMinLength rule with a custom minimum length` { - - val variableMinLength = - VariableMinLength(TestConfig(mapOf(VariableMinLength.MINIMUM_VARIABLE_NAME_LENGTH to "2"))) - - @Test - fun `reports a very short variable name`() { - val code = "private val a = 3" - assertThat(variableMinLength.compileAndLint(code)).hasSize(1) - } - - @Test - fun `does not report a variable with only a single underscore`() { - val code = """ - class C { - val prop: (Int) -> Unit = { _ -> Unit } - } - """ - assertThat(variableMinLength.compileAndLint(code)).isEmpty() + @Test + fun `does not report a variable with only a single underscore`() { + val code = """ + class C { + val prop: (Int) -> Unit = { _ -> Unit } } + """ + assertThat(variableMinLength.compileAndLint(code)).isEmpty() } + } - @Test - fun `should not report a variable with 64 letters`() { - val subject = NamingRules() - val code = "private val varThatIsExactly64LettersLongWhichYouMightNotWantToBelieveInLolz = 3" - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() - } + @Test + fun `should not report a variable with 64 letters`() { + val subject = NamingRules() + val code = "private val varThatIsExactly64LettersLongWhichYouMightNotWantToBelieveInLolz = 3" + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } - @Test - fun `should report a variable name that is too long`() { - val subject = NamingRules() - val code = "private val thisVariableIsDefinitelyWayTooLongLongerThanEverythingAndShouldBeMuchShorter = 3" - subject.compileAndLint(code) - assertThat(subject.findings).hasSize(1) - } + @Test + fun `should report a variable name that is too long`() { + val subject = NamingRules() + val code = "private val thisVariableIsDefinitelyWayTooLongLongerThanEverythingAndShouldBeMuchShorter = 3" + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(1) + } - @Test - fun `should not report a variable name that is okay`() { - val subject = NamingRules() - val code = "private val thisOneIsCool = 3" - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() - } + @Test + fun `should not report a variable name that is okay`() { + val subject = NamingRules() + val code = "private val thisOneIsCool = 3" + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } - @Test - fun `should report a function name that is too short`() { - val subject = NamingRules() - val code = "fun a() = 3" - subject.compileAndLint(code) - assertThat(subject.findings).hasSize(1) - } + @Test + fun `should report a function name that is too short`() { + val subject = NamingRules() + val code = "fun a() = 3" + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(1) + } - @Test - fun `should report a function name that is too long`() { - val subject = NamingRules() - val code = "fun thisFunctionIsDefinitelyWayTooLongAndShouldBeMuchShorter() = 3" - subject.compileAndLint(code) - assertThat(subject.findings).hasSize(1) - } + @Test + fun `should report a function name that is too long`() { + val subject = NamingRules() + val code = "fun thisFunctionIsDefinitelyWayTooLongAndShouldBeMuchShorter() = 3" + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(1) + } - @Test - fun `should not report a function name that is okay`() { - val subject = NamingRules() - val code = "fun three() = 3" - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() - } + @Test + fun `should not report a function name that is okay`() { + val subject = NamingRules() + val code = "fun three() = 3" + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } - @Test - fun `should report a function name that begins with a backtick, capitals, and spaces`() { - val subject = NamingRules() - val code = "fun `Hi bye`() = 3" - subject.compileAndLint(code) - assertThat(subject.findings).hasSize(1) - } + @Test + fun `should report a function name that begins with a backtick, capitals, and spaces`() { + val subject = NamingRules() + val code = "fun `Hi bye`() = 3" + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(1) } } diff --git a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NamingRulesSpec.kt b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NamingRulesSpec.kt index 85e66477cf8..2efa8e4adaf 100644 --- a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NamingRulesSpec.kt +++ b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NamingRulesSpec.kt @@ -2,22 +2,18 @@ package io.gitlab.arturbosch.detekt.rules.naming import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class NamingRulesSpec { - @Nested - inner class `naming like in constants is allowed for destructuring` { - @Test - fun `should not detect any`() { - val code = """ - data class D(val i: Int, val j: Int) - fun doStuff() { - val (_, HOLY_GRAIL) = D(5, 4) - } - """ - assertThat(NamingRules().compileAndLint(code)).isEmpty() - } + @Test + fun `should not detect any`() { + val code = """ + data class D(val i: Int, val j: Int) + fun doStuff() { + val (_, HOLY_GRAIL) = D(5, 4) + } + """ + assertThat(NamingRules().compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NoNameShadowingSpec.kt b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NoNameShadowingSpec.kt index 583ff43a274..e6f707169b9 100644 --- a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NoNameShadowingSpec.kt +++ b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NoNameShadowingSpec.kt @@ -4,114 +4,110 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class NoNameShadowingSpec(val env: KotlinCoreEnvironment) { val subject = NoNameShadowing() - @Nested - inner class `NoNameShadowing rule` { - @Test - fun `report shadowing variable`() { - val code = """ - fun test(i: Int) { - val i = 1 - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings).hasSourceLocation(2, 9) - assertThat(findings[0]).hasMessage("Name shadowed: i") - } + @Test + fun `report shadowing variable`() { + val code = """ + fun test(i: Int) { + val i = 1 + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings).hasSourceLocation(2, 9) + assertThat(findings[0]).hasMessage("Name shadowed: i") + } - @Test - fun `report shadowing destructuring declaration entry`() { - val code = """ - fun test(j: Int) { - val (j, _) = 1 to 2 - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0]).hasMessage("Name shadowed: j") - } + @Test + fun `report shadowing destructuring declaration entry`() { + val code = """ + fun test(j: Int) { + val (j, _) = 1 to 2 + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0]).hasMessage("Name shadowed: j") + } - @Test - fun `report shadowing lambda parameter`() { - val code = """ - fun test(k: Int) { - listOf(1).map { k -> - } + @Test + fun `report shadowing lambda parameter`() { + val code = """ + fun test(k: Int) { + listOf(1).map { k -> } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0]).hasMessage("Name shadowed: k") - } + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0]).hasMessage("Name shadowed: k") + } - @Test - fun `report shadowing nested lambda 'it' parameter`() { - val code = """ - fun test() { - listOf(1).forEach { - listOf(2).forEach { it -> - } + @Test + fun `report shadowing nested lambda 'it' parameter`() { + val code = """ + fun test() { + listOf(1).forEach { + listOf(2).forEach { it -> } } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0]).hasMessage("Name shadowed: it") - } + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0]).hasMessage("Name shadowed: it") + } - @Test - fun `does not report when implicit 'it' parameter isn't used`() { - val code = """ - fun test() { - listOf(1).forEach { - listOf(2).forEach { - } + @Test + fun `does not report when implicit 'it' parameter isn't used`() { + val code = """ + fun test() { + listOf(1).forEach { + listOf(2).forEach { } } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `does not report not shadowing variable`() { - val code = """ - fun test(i: Int) { - val j = i - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + @Test + fun `does not report not shadowing variable`() { + val code = """ + fun test(i: Int) { + val j = i + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `does not report not shadowing nested lambda implicit 'it' parameter`() { - val code = """ - fun test() { - listOf(1).forEach { i -> - listOf(2).forEach { - println(it) - } + @Test + fun `does not report not shadowing nested lambda implicit 'it' parameter`() { + val code = """ + fun test() { + listOf(1).forEach { i -> + listOf(2).forEach { + println(it) } - "".run { - listOf(2).forEach { - println(it) - } - } - listOf("").let { list -> - list.map { it + "x" } + } + "".run { + listOf(2).forEach { + println(it) } } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + listOf("").let { list -> + list.map { it + "x" } + } + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() } } diff --git a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NonBooleanPropertyWithPrefixIsSpec.kt b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NonBooleanPropertyWithPrefixIsSpec.kt index 9683e25ac70..e37ff5c174d 100644 --- a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NonBooleanPropertyWithPrefixIsSpec.kt +++ b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NonBooleanPropertyWithPrefixIsSpec.kt @@ -13,276 +13,272 @@ class NonBooleanPropertyWithPrefixIsSpec(val env: KotlinCoreEnvironment) { val subject = NonBooleanPropertyPrefixedWithIs() @Nested - inner class `IsPropertyNaming rule` { + inner class `argument declarations` { + @Test + fun `should not detect Kotlin Boolean`() { + val code = """data class O (var isDefault: Boolean)""" + val findings = subject.compileAndLintWithContext(env, code) - @Nested - inner class `argument declarations` { - @Test - fun `should not detect Kotlin Boolean`() { - val code = """data class O (var isDefault: Boolean)""" - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `should not detect Kotlin Boolean nullable`() { - val code = """data class O (var isDefault: Boolean?)""" - val findings = subject.compileAndLintWithContext(env, code) + @Test + fun `should not detect Kotlin Boolean nullable`() { + val code = """data class O (var isDefault: Boolean?)""" + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `should not detect Kotlin Boolean initialized`() { - val code = """data class O (var isDefault: Boolean = false)""" - val findings = subject.compileAndLintWithContext(env, code) + @Test + fun `should not detect Kotlin Boolean initialized`() { + val code = """data class O (var isDefault: Boolean = false)""" + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `should not detect Java Boolean`() { - val code = """data class O (var isDefault: java.lang.Boolean)""" - val findings = subject.compileAndLintWithContext(env, code) + @Test + fun `should not detect Java Boolean`() { + val code = """data class O (var isDefault: java.lang.Boolean)""" + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `should warn about primitive types`() { - val code = """data class O (var isDefault: Int)""" - val findings = subject.compileAndLintWithContext(env, code) + @Test + fun `should warn about primitive types`() { + val code = """data class O (var isDefault: Int)""" + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + assertThat(findings).hasSize(1) + } - @Test - fun `should warn about inner classes`() { - val code = """ - data class O (var isDefault: Inner) { - class Inner - } - """ - val findings = subject.compileAndLintWithContext(env, code) + @Test + fun `should warn about inner classes`() { + val code = """ + data class O (var isDefault: Inner) { + class Inner + } + """ + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + assertThat(findings).hasSize(1) + } - @Test - fun `should not detect short names`() { - val code = """class O (var `is`: Int)""" - val findings = subject.compileAndLintWithContext(env, code) + @Test + fun `should not detect short names`() { + val code = """class O (var `is`: Int)""" + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `should not detect titles, starting with 'is'`() { - val code = """class O (var isengardTowerHeightInFeet: Int)""" - val findings = subject.compileAndLintWithContext(env, code) + @Test + fun `should not detect titles, starting with 'is'`() { + val code = """class O (var isengardTowerHeightInFeet: Int)""" + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() } + } - @Nested - inner class `property declarations` { - @Test - fun `should not detect Kotlin Boolean`() { - val code = """ - class O { - var isDefault = false - } - """ - val findings = subject.compileAndLintWithContext(env, code) + @Nested + inner class `property declarations` { + @Test + fun `should not detect Kotlin Boolean`() { + val code = """ + class O { + var isDefault = false + } + """ + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `should not detect Kotlin Boolean property uninitialized`() { - val code = """ - class O { - var isDefault: Boolean - - init { - isDefault = true - } + @Test + fun `should not detect Kotlin Boolean property uninitialized`() { + val code = """ + class O { + var isDefault: Boolean + + init { + isDefault = true } - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).isEmpty() - } + } + """ + val findings = subject.compileAndLintWithContext(env, code) - @Test - fun `should not detect Kotlin Boolean nullable`() { - val code = """ - class O { - var isDefault: Boolean? = null - } - """ - val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - assertThat(findings).isEmpty() - } + @Test + fun `should not detect Kotlin Boolean nullable`() { + val code = """ + class O { + var isDefault: Boolean? = null + } + """ + val findings = subject.compileAndLintWithContext(env, code) - @Test - fun `should not detect Java Boolean`() { - val code = """ - class O { - var isDefault: java.lang.Boolean = java.lang.Boolean(false) - } - """ - val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - assertThat(findings).isEmpty() - } + @Test + fun `should not detect Java Boolean`() { + val code = """ + class O { + var isDefault: java.lang.Boolean = java.lang.Boolean(false) + } + """ + val findings = subject.compileAndLintWithContext(env, code) - @Test - fun `should not detect Java Boolean uninitialized`() { - val code = """ - class O { - var isDefault: java.lang.Boolean - - init { - isDefault = java.lang.Boolean(false) - } - } - """ - val findings = subject.compileAndLintWithContext(env, code) - - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `should not detect Java Boolean nullable`() { - val code = """ - class O { - var isDefault: java.lang.Boolean? = null + @Test + fun `should not detect Java Boolean uninitialized`() { + val code = """ + class O { + var isDefault: java.lang.Boolean + + init { + isDefault = java.lang.Boolean(false) } - """ - val findings = subject.compileAndLintWithContext(env, code) + } + """ + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `should warn about primitive types in class`() { - val code = """ - class O { - var isDefault: Int = 0 - } - """ - val findings = subject.compileAndLintWithContext(env, code) + @Test + fun `should not detect Java Boolean nullable`() { + val code = """ + class O { + var isDefault: java.lang.Boolean? = null + } + """ + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + assertThat(findings).isEmpty() + } - @Test - fun `should warn about inferred primitive types`() { - val code = """ - class O { - var isDefault = 0 - } - """ - val findings = subject.compileAndLintWithContext(env, code) + @Test + fun `should warn about primitive types in class`() { + val code = """ + class O { + var isDefault: Int = 0 + } + """ + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + assertThat(findings).hasSize(1) + } - @Test - fun `should warn about inferred non-primitive types`() { - val code = """ - class O { - var isDefault = listOf(1, 2, 3) - } - """ - val findings = subject.compileAndLintWithContext(env, code) + @Test + fun `should warn about inferred primitive types`() { + val code = """ + class O { + var isDefault = 0 + } + """ + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + assertThat(findings).hasSize(1) + } - @Test - fun `should warn about inner classes`() { - val code = """ - class O { - var isDefault: Inner = Inner() - - class Inner - } - """ - val findings = subject.compileAndLintWithContext(env, code) + @Test + fun `should warn about inferred non-primitive types`() { + val code = """ + class O { + var isDefault = listOf(1, 2, 3) + } + """ + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + assertThat(findings).hasSize(1) + } - @Test - fun `should not detect short names`() { - val code = """ - class O { - var `is`: Int = 0 - } - """ - val findings = subject.compileAndLintWithContext(env, code) + @Test + fun `should warn about inner classes`() { + val code = """ + class O { + var isDefault: Inner = Inner() + + class Inner + } + """ + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + assertThat(findings).hasSize(1) + } - @Test - fun `should not detect titles, starting with 'is'`() { - val code = """ - class O { - var isengardTowerHeightInFeet: Int = 500 - } - """ - val findings = subject.compileAndLintWithContext(env, code) + @Test + fun `should not detect short names`() { + val code = """ + class O { + var `is`: Int = 0 + } + """ + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `should warn about primitive types in function`() { - val code = """ - fun f() { - var isDefault: Int = 0 - } - """ - val findings = subject.compileAndLintWithContext(env, code) + @Test + fun `should not detect titles, starting with 'is'`() { + val code = """ + class O { + var isengardTowerHeightInFeet: Int = 500 + } + """ + val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + assertThat(findings).isEmpty() } - @Nested - inner class `issue regression test` { - @Test - fun `issue 4674 should handle unknown type as correct`() { - val code = """ - class Test { - val isDebuggable get() = BuildConfig.DEBUG + @Test + fun `should warn about primitive types in function`() { + val code = """ + fun f() { + var isDefault: Int = 0 } - """ + """ + val findings = subject.compileAndLintWithContext(env, code) - // BuildConfig is missing in this test so we can't compile it - val findings = subject.lintWithContext(env, code) + assertThat(findings).hasSize(1) + } + } - assertThat(findings).isEmpty() + @Nested + inner class `issue regression test` { + @Test + fun `issue 4674 should handle unknown type as correct`() { + val code = """ + class Test { + val isDebuggable get() = BuildConfig.DEBUG } + """ - @Test - fun `issue 4675 check function reference type parameter`() { - val code = """ - val isRemoved = suspend { null == null } + // BuildConfig is missing in this test so we can't compile it + val findings = subject.lintWithContext(env, code) - fun trueFun() = true - val isReferenceBoolean = ::trueFun - """ - val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - assertThat(findings).isEmpty() - } + @Test + fun `issue 4675 check function reference type parameter`() { + val code = """ + val isRemoved = suspend { null == null } + + fun trueFun() = true + val isReferenceBoolean = ::trueFun + """ + val findings = subject.compileAndLintWithContext(env, code) + + assertThat(findings).isEmpty() } } } diff --git a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/PackageNamingSpec.kt b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/PackageNamingSpec.kt index d4002c0217a..345ecc679eb 100644 --- a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/PackageNamingSpec.kt +++ b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/PackageNamingSpec.kt @@ -2,44 +2,39 @@ package io.gitlab.arturbosch.detekt.rules.naming import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class PackageNamingSpec { - @Nested - inner class `PackageNaming rule` { - - @Test - fun `should ignore the issue by alias suppression`() { - assertThat( - PackageNaming().compileAndLint( - """ - @file:Suppress("PackageDirectoryMismatch") - package FOO.BAR - """ - ) - ).isEmpty() - } + @Test + fun `should ignore the issue by alias suppression`() { + assertThat( + PackageNaming().compileAndLint( + """ + @file:Suppress("PackageDirectoryMismatch") + package FOO.BAR + """ + ) + ).isEmpty() + } - @Test - fun `should find a uppercase package name`() { - assertThat(PackageNaming().compileAndLint("package FOO.BAR")).hasSize(1) - } + @Test + fun `should find a uppercase package name`() { + assertThat(PackageNaming().compileAndLint("package FOO.BAR")).hasSize(1) + } - @Test - fun `should find a upper camel case package name`() { - assertThat(PackageNaming().compileAndLint("package Foo.Bar")).hasSize(1) - } + @Test + fun `should find a upper camel case package name`() { + assertThat(PackageNaming().compileAndLint("package Foo.Bar")).hasSize(1) + } - @Test - fun `should find a camel case package name`() { - assertThat(PackageNaming().compileAndLint("package fOO.bAR")).hasSize(1) - } + @Test + fun `should find a camel case package name`() { + assertThat(PackageNaming().compileAndLint("package fOO.bAR")).hasSize(1) + } - @Test - fun `should check an valid package name`() { - assertThat(PackageNaming().compileAndLint("package foo.bar")).isEmpty() - } + @Test + fun `should check an valid package name`() { + assertThat(PackageNaming().compileAndLint("package foo.bar")).isEmpty() } } diff --git a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/VariableNamingSpec.kt b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/VariableNamingSpec.kt index 2eab89150ea..0c9e783e631 100644 --- a/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/VariableNamingSpec.kt +++ b/detekt-rules-naming/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/naming/VariableNamingSpec.kt @@ -4,79 +4,74 @@ 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 org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class VariableNamingSpec { - @Nested - inner class `properties in classes` { - - @Test - fun `should detect all positive cases`() { - val code = """ - class C { - private val _FIELD = 5 - val FIELD get() = _FIELD - val camel_Case_Property = 5 - } - """ - assertThat(VariableNaming().compileAndLint(code)) - .hasSourceLocations( - SourceLocation(2, 17), - SourceLocation(3, 9), - SourceLocation(4, 9) - ) - } + @Test + fun `should detect all positive cases`() { + val code = """ + class C { + private val _FIELD = 5 + val FIELD get() = _FIELD + val camel_Case_Property = 5 + } + """ + assertThat(VariableNaming().compileAndLint(code)) + .hasSourceLocations( + SourceLocation(2, 17), + SourceLocation(3, 9), + SourceLocation(4, 9) + ) + } - @Test - fun `checks all negative cases`() { - val code = """ - class C { - private val _field = 5 - val field get() = _field - val camelCaseProperty = 5 - } - """ - assertThat(VariableNaming().compileAndLint(code)).isEmpty() - } + @Test + fun `checks all negative cases`() { + val code = """ + class C { + private val _field = 5 + val field get() = _field + val camelCaseProperty = 5 + } + """ + assertThat(VariableNaming().compileAndLint(code)).isEmpty() + } - @Test - fun `should not flag overridden member properties by default`() { - val code = """ - class C : I { - override val SHOULD_NOT_BE_FLAGGED = "banana" - } - interface I : I2 { - override val SHOULD_NOT_BE_FLAGGED: String - } - interface I2 { - @Suppress("VariableNaming") val SHOULD_NOT_BE_FLAGGED: String - } - """ - assertThat(VariableNaming().compileAndLint(code)).isEmpty() - } + @Test + fun `should not flag overridden member properties by default`() { + val code = """ + class C : I { + override val SHOULD_NOT_BE_FLAGGED = "banana" + } + interface I : I2 { + override val SHOULD_NOT_BE_FLAGGED: String + } + interface I2 { + @Suppress("VariableNaming") val SHOULD_NOT_BE_FLAGGED: String + } + """ + assertThat(VariableNaming().compileAndLint(code)).isEmpty() + } - @Test - fun `doesn't ignore overridden member properties if ignoreOverridden is false`() { - val code = """ - class C : I { - override val SHOULD_BE_FLAGGED = "banana" - } - interface I : I2 { - override val SHOULD_BE_FLAGGED: String - } - interface I2 { - @Suppress("VariableNaming") val SHOULD_BE_FLAGGED: String - } - """ - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to "false")) - assertThat(VariableNaming(config).compileAndLint(code)) - .hasSourceLocations( - SourceLocation(2, 18), - SourceLocation(5, 18) - ) - } + @Test + fun `doesn't ignore overridden member properties if ignoreOverridden is false`() { + val code = """ + class C : I { + override val SHOULD_BE_FLAGGED = "banana" + } + interface I : I2 { + override val SHOULD_BE_FLAGGED: String + } + interface I2 { + @Suppress("VariableNaming") val SHOULD_BE_FLAGGED: String + } + """ + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to "false")) + assertThat(VariableNaming(config).compileAndLint(code)) + .hasSourceLocations( + SourceLocation(2, 18), + SourceLocation(5, 18) + ) } } diff --git a/detekt-rules-performance/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/performance/ForEachOnRangeSpec.kt b/detekt-rules-performance/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/performance/ForEachOnRangeSpec.kt index cd464019f08..1de91df460a 100644 --- a/detekt-rules-performance/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/performance/ForEachOnRangeSpec.kt +++ b/detekt-rules-performance/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/performance/ForEachOnRangeSpec.kt @@ -10,64 +10,60 @@ class ForEachOnRangeSpec { val subject = ForEachOnRange() @Nested - inner class `ForEachOnRange rule` { - - @Nested - inner class `using a forEach on a range` { - val code = """ - fun test() { - (1..10).forEach { - println(it) - } - (1 until 10).forEach { - println(it) - } - (10 downTo 1).forEach { - println(it) - } - (10 downTo 1 step 2).forEach { - println(it) - } + inner class `using a forEach on a range` { + val code = """ + fun test() { + (1..10).forEach { + println(it) } - """ - - @Test - fun `should report the forEach usage`() { - val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(4) + (1 until 10).forEach { + println(it) + } + (10 downTo 1).forEach { + println(it) + } + (10 downTo 1 step 2).forEach { + println(it) } } + """ - @Nested - inner class `using any other method on a range` { - val code = """ - fun test() { - (1..10).isEmpty() - } - """ + @Test + fun `should report the forEach usage`() { + val findings = subject.compileAndLint(code) + assertThat(findings).hasSize(4) + } + } - @Test - fun `should not report any issues`() { - val findings = subject.compileAndLint(code) - assertThat(findings).isEmpty() - } + @Nested + inner class `using any other method on a range` { + val code = """ + fun test() { + (1..10).isEmpty() } + """ - @Nested - inner class `using a forEach on a list` { - val code = """ - fun test() { - listOf(1, 2, 3).forEach { - println(it) - } - } - """ + @Test + fun `should not report any issues`() { + val findings = subject.compileAndLint(code) + assertThat(findings).isEmpty() + } + } - @Test - fun `should not report any issues`() { - val findings = subject.compileAndLint(code) - assertThat(findings).isEmpty() + @Nested + inner class `using a forEach on a list` { + val code = """ + fun test() { + listOf(1, 2, 3).forEach { + println(it) } } + """ + + @Test + fun `should not report any issues`() { + val findings = subject.compileAndLint(code) + assertThat(findings).isEmpty() + } } } diff --git a/detekt-rules-performance/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/performance/SpreadOperatorSpec.kt b/detekt-rules-performance/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/performance/SpreadOperatorSpec.kt index 6b0dc7df1b8..993de8d6189 100644 --- a/detekt-rules-performance/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/performance/SpreadOperatorSpec.kt +++ b/detekt-rules-performance/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/performance/SpreadOperatorSpec.kt @@ -13,235 +13,232 @@ class SpreadOperatorSpec(val env: KotlinCoreEnvironment) { val subject = SpreadOperator() + /** + * This rule has different behaviour depending on whether type resolution is enabled in detekt or not. The two + * `context` blocks are there to test behaviour when type resolution is enabled and type resolution is disabled + * as different warning messages are shown in each case. + */ @Nested - inner class `SpreadOperator rule` { - /** - * This rule has different behaviour depending on whether type resolution is enabled in detekt or not. The two - * `context` blocks are there to test behaviour when type resolution is enabled and type resolution is disabled - * as different warning messages are shown in each case. - */ - @Nested - inner class `with type resolution` { - - val typeResolutionEnabledMessage = "Used in this way a spread operator causes a full copy of the array to" + - " be created before calling a method. This may result in a performance penalty." - - @Test - fun `reports when array copy required using named parameters`() { - val code = """ - val xsArray = intArrayOf(1) - fun foo(vararg xs: Int) {} - val testVal = foo(xs = *xsArray) - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - assertThat(actual.first().message).isEqualTo(typeResolutionEnabledMessage) - } + inner class `with type resolution` { + + val typeResolutionEnabledMessage = "Used in this way a spread operator causes a full copy of the array to" + + " be created before calling a method. This may result in a performance penalty." + + @Test + fun `reports when array copy required using named parameters`() { + val code = """ + val xsArray = intArrayOf(1) + fun foo(vararg xs: Int) {} + val testVal = foo(xs = *xsArray) + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + assertThat(actual.first().message).isEqualTo(typeResolutionEnabledMessage) + } - @Test - fun `reports when array copy required without using named parameters`() { - val code = """ - val xsArray = intArrayOf(1) - fun foo(vararg xs: Int) {} - val testVal = foo(*xsArray) - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - assertThat(actual.first().message).isEqualTo(typeResolutionEnabledMessage) - } + @Test + fun `reports when array copy required without using named parameters`() { + val code = """ + val xsArray = intArrayOf(1) + fun foo(vararg xs: Int) {} + val testVal = foo(*xsArray) + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + assertThat(actual.first().message).isEqualTo(typeResolutionEnabledMessage) + } - @Test - fun `doesn't report when using array constructor with spread operator`() { - val code = """ - fun foo(vararg xs: Int) {} - val testVal = foo(xs = *intArrayOf(1)) - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `doesn't report when using array constructor with spread operator`() { + val code = """ + fun foo(vararg xs: Int) {} + val testVal = foo(xs = *intArrayOf(1)) + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `doesn't report when using array constructor with spread operator when varargs parameter comes first`() { + val code = """ + fun asList(vararg ts: T, stringValue: String): List = listOf(1,2,3) + val list = asList(-1, 0, *arrayOf(1, 2, 3), 4, stringValue = "5") + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `doesn't report when passing values directly`() { + val code = """ + fun asList(vararg ts: T, stringValue: String): List = listOf(1,2,3) + val list = asList(-1, 0, 1, 2, 3, 4, stringValue = "5") + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `doesn't report when using array constructor with spread operator when varargs parameter comes first`() { - val code = """ - fun asList(vararg ts: T, stringValue: String): List = listOf(1,2,3) - val list = asList(-1, 0, *arrayOf(1, 2, 3), 4, stringValue = "5") - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + @Test + fun `doesn't report when function doesn't take a vararg parameter`() { + val code = """ + fun test0(strs: Array) { + test(strs) } - @Test - fun `doesn't report when passing values directly`() { - val code = """ - fun asList(vararg ts: T, stringValue: String): List = listOf(1,2,3) - val list = asList(-1, 0, 1, 2, 3, 4, stringValue = "5") - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + fun test(strs: Array) { + strs.forEach { println(it) } } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `doesn't report when function doesn't take a vararg parameter`() { - val code = """ - fun test0(strs: Array) { - test(strs) - } + @Test + fun `doesn't report with expression inside params`() { + val code = """ + fun test0(strs: Array) { + test(2*2) + } - fun test(strs: Array) { - strs.forEach { println(it) } - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + fun test(test : Int) { + println(test) } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `doesn't report with expression inside params`() { - val code = """ - fun test0(strs: Array) { - test(2*2) + @Test + fun `respects pass through of vararg parameter - #3145`() { + val code = """ + fun b(vararg bla: Int) = Unit + fun a(vararg bla: Int) { + b(*bla) } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `reports shadowed vararg declaration which may lead to array copy - #3145`() { + val code = """ + fun b(vararg bla: String) = Unit - fun test(test : Int) { - println(test) + fun a(vararg bla: Int) { + val bla = arrayOf("") + b(*bla) } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } + } - @Test - fun `respects pass through of vararg parameter - #3145`() { - val code = """ - fun b(vararg bla: Int) = Unit - fun a(vararg bla: Int) { - b(*bla) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Nested + inner class `without type resolution` { + + val typeResolutionDisabledMessage = "In most cases using a spread operator causes a full copy of the " + + "array to be created before calling a method. This may result in a performance penalty." + + @Test + fun `reports when array copy required using named parameters`() { + val code = """ + val xsArray = intArrayOf(1) + fun foo(vararg xs: Int) {} + val testVal = foo(xs = *xsArray) + """ + val actual = subject.compileAndLint(code) + assertThat(actual).hasSize(1) + assertThat(actual.first().message).isEqualTo(typeResolutionDisabledMessage) + } - @Test - fun `reports shadowed vararg declaration which may lead to array copy - #3145`() { - val code = """ - fun b(vararg bla: String) = Unit - - fun a(vararg bla: Int) { - val bla = arrayOf("") - b(*bla) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + @Test + fun `reports when array copy required without using named parameters`() { + val code = """ + val xsArray = intArrayOf(1) + fun foo(vararg xs: Int) {} + val testVal = foo(*xsArray) + """ + val actual = subject.compileAndLint(code) + assertThat(actual).hasSize(1) + assertThat(actual.first().message).isEqualTo(typeResolutionDisabledMessage) } - @Nested - inner class `without type resolution` { + @Test + fun `doesn't report when using array constructor with spread operator`() { + val code = """ + fun foo(vararg xs: Int) {} + val testVal = foo(xs = *intArrayOf(1)) + """ + val actual = subject.compileAndLint(code) + assertThat(actual).hasSize(1) + assertThat(actual.first().message).isEqualTo(typeResolutionDisabledMessage) + } - val typeResolutionDisabledMessage = "In most cases using a spread operator causes a full copy of the " + - "array to be created before calling a method. This may result in a performance penalty." + @Test + fun `doesn't report when using array constructor with spread operator when varargs parameter comes first`() { + val code = """ + fun asList(vararg ts: T, stringValue: String): List = listOf(1,2,3) + val list = asList(-1, 0, *arrayOf(1, 2, 3), 4, stringValue = "5") + """ + val actual = subject.compileAndLint(code) + assertThat(actual).hasSize(1) + assertThat(actual.first().message).isEqualTo(typeResolutionDisabledMessage) + } - @Test - fun `reports when array copy required using named parameters`() { - val code = """ - val xsArray = intArrayOf(1) - fun foo(vararg xs: Int) {} - val testVal = foo(xs = *xsArray) - """ - val actual = subject.compileAndLint(code) - assertThat(actual).hasSize(1) - assertThat(actual.first().message).isEqualTo(typeResolutionDisabledMessage) - } + @Test + fun `doesn't report when passing values directly`() { + val code = """ + fun asList(vararg ts: T, stringValue: String): List = listOf(1,2,3) + val list = asList(-1, 0, 1, 2, 3, 4, stringValue = "5") + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports when array copy required without using named parameters`() { - val code = """ - val xsArray = intArrayOf(1) - fun foo(vararg xs: Int) {} - val testVal = foo(*xsArray) - """ - val actual = subject.compileAndLint(code) - assertThat(actual).hasSize(1) - assertThat(actual.first().message).isEqualTo(typeResolutionDisabledMessage) + @Test + fun `doesn't report when function doesn't take a vararg parameter`() { + val code = """ + fun test0(strs: Array) { + test(strs) } - @Test - fun `doesn't report when using array constructor with spread operator`() { - val code = """ - fun foo(vararg xs: Int) {} - val testVal = foo(xs = *intArrayOf(1)) - """ - val actual = subject.compileAndLint(code) - assertThat(actual).hasSize(1) - assertThat(actual.first().message).isEqualTo(typeResolutionDisabledMessage) + fun test(strs: Array) { + strs.forEach { println(it) } } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `doesn't report when using array constructor with spread operator when varargs parameter comes first`() { - val code = """ - fun asList(vararg ts: T, stringValue: String): List = listOf(1,2,3) - val list = asList(-1, 0, *arrayOf(1, 2, 3), 4, stringValue = "5") - """ - val actual = subject.compileAndLint(code) - assertThat(actual).hasSize(1) - assertThat(actual.first().message).isEqualTo(typeResolutionDisabledMessage) + @Test + fun `doesn't report with expression inside params`() { + val code = """ + fun test0(strs: Array) { + test(2*2) } - @Test - fun `doesn't report when passing values directly`() { - val code = """ - fun asList(vararg ts: T, stringValue: String): List = listOf(1,2,3) - val list = asList(-1, 0, 1, 2, 3, 4, stringValue = "5") - """ - assertThat(subject.compileAndLint(code)).isEmpty() + fun test(test : Int) { + println(test) } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `doesn't report when function doesn't take a vararg parameter`() { - val code = """ - fun test0(strs: Array) { - test(strs) - } - - fun test(strs: Array) { - strs.forEach { println(it) } + @Test + fun `respects pass through of vararg parameter - #3145`() { + val code = """ + fun b(vararg bla: Int) = Unit + fun a(vararg bla: Int) { + b(*bla) } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `doesn't report with expression inside params`() { - val code = """ - fun test0(strs: Array) { - test(2*2) - } + @Test + fun `does not report shadowed vararg declaration, we except this false negative here - #3145`() { + val code = """ + fun b(vararg bla: String) = Unit - fun test(test : Int) { - println(test) + fun a(vararg bla: Int) { + val bla = arrayOf("") + b(*bla) } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `respects pass through of vararg parameter - #3145`() { - val code = """ - fun b(vararg bla: Int) = Unit - fun a(vararg bla: Int) { - b(*bla) - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report shadowed vararg declaration, we except this false negative here - #3145`() { - val code = """ - fun b(vararg bla: String) = Unit - - fun a(vararg bla: Int) { - val bla = arrayOf("") - b(*bla) - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } } diff --git a/detekt-rules-performance/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/performance/UnnecessaryTemporaryInstantiationSpec.kt b/detekt-rules-performance/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/performance/UnnecessaryTemporaryInstantiationSpec.kt index f82c70b7f12..1b6bdba45d1 100644 --- a/detekt-rules-performance/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/performance/UnnecessaryTemporaryInstantiationSpec.kt +++ b/detekt-rules-performance/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/performance/UnnecessaryTemporaryInstantiationSpec.kt @@ -2,25 +2,20 @@ package io.gitlab.arturbosch.detekt.rules.performance import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class UnnecessaryTemporaryInstantiationSpec { val subject = UnnecessaryTemporaryInstantiation() - @Nested - inner class `UnnecessaryTemporaryInstantiation rule` { - - @Test - fun `temporary instantiation for conversion`() { - val code = "val i = Integer(1).toString()" - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `temporary instantiation for conversion`() { + val code = "val i = Integer(1).toString()" + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `right conversion without instantiation`() { - val code = "val i = Integer.toString(1)" - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `right conversion without instantiation`() { + val code = "val i = Integer.toString(1)" + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/CanBeNonNullableSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/CanBeNonNullableSpec.kt index 1224b2a8890..e5fe215260d 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/CanBeNonNullableSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/CanBeNonNullableSpec.kt @@ -13,34 +13,51 @@ import org.junit.jupiter.api.Test class CanBeNonNullableSpec(val env: KotlinCoreEnvironment) { val subject = CanBeNonNullable(Config.empty) + @Test + fun `does not report when there is no context`() { + val code = """ + class A { + private var a: Int? = 5 + fun foo() { + a = 6 + } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + @Nested - inner class `CanBeNonNullable Rule` { + inner class `evaluating private properties` { @Test - fun `does not report when there is no context`() { + fun `reports when class-level vars are never assigned nullable values`() { val code = """ - class A { - private var a: Int? = 5 - fun foo() { - a = 6 - } + class A(bVal: Int) { + private var a: Int? = 5 + private var b: Int? + + init { + b = bVal + } + + fun foo(): Int { + val b = a!! + a = b + 1 + val a = null + return b } + } """ - assertThat(subject.compileAndLint(code)).isEmpty() + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) } - @Nested - inner class `evaluating private properties` { - @Test - fun `reports when class-level vars are never assigned nullable values`() { - val code = """ - class A(bVal: Int) { - private var a: Int? = 5 - private var b: Int? - - init { - b = bVal - } - + @Test + fun `reports when vars utilize non-nullable delegate values`() { + val code = """ + import kotlin.reflect.KProperty + + class A { + private var a: Int? by PropDelegate() + fun foo(): Int { val b = a!! a = b + 1 @@ -48,748 +65,650 @@ class CanBeNonNullableSpec(val env: KotlinCoreEnvironment) { return b } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) - } - - @Test - fun `reports when vars utilize non-nullable delegate values`() { - val code = """ - import kotlin.reflect.KProperty - - class A { - private var a: Int? by PropDelegate() - - fun foo(): Int { - val b = a!! - a = b + 1 - val a = null - return b - } + + class PropDelegate(private var propVal: Int = 0) { + operator fun getValue(thisRef: A, property: KProperty<*>): Int { + return propVal } - - class PropDelegate(private var propVal: Int = 0) { - operator fun getValue(thisRef: A, property: KProperty<*>): Int { - return propVal - } - - operator fun setValue(thisRef: A, property: KProperty<*>, value: Any?) { - if (value is Int) { - propVal = value - } + + operator fun setValue(thisRef: A, property: KProperty<*>, value: Any?) { + if (value is Int) { + propVal = value } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) + } - @Test - fun `reports when file-level vars are never assigned nullable values`() { - val code = """ - private var fileA: Int? = 5 - private var fileB: Int? = 5 + @Test + fun `reports when file-level vars are never assigned nullable values`() { + val code = """ + private var fileA: Int? = 5 + private var fileB: Int? = 5 - fun fileFoo() { - fileB = 6 - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) + fun fileFoo() { + fileB = 6 } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) + } - @Test - fun `does not report when class-level vars are assigned nullable values`() { - val code = """ - import kotlin.random.Random + @Test + fun `does not report when class-level vars are assigned nullable values`() { + val code = """ + import kotlin.random.Random - class A(fVal: Int?) { - private var a: Int? = 0 - private var b: Int? = 0 - private var c: Int? = 0 - private var d: Int? = 0 - private var e: Int? = null - private var f: Int? - - init { - f = fVal - } + class A(fVal: Int?) { + private var a: Int? = 0 + private var b: Int? = 0 + private var c: Int? = 0 + private var d: Int? = 0 + private var e: Int? = null + private var f: Int? + + init { + f = fVal + } - fun foo(fizz: Int): Int { - a = null - b = if (fizz % 2 == 0) fizz else null - c = buzz(fizz) - d = a - return fizz - } + fun foo(fizz: Int): Int { + a = null + b = if (fizz % 2 == 0) fizz else null + c = buzz(fizz) + d = a + return fizz + } - private fun buzz(bizz: Int): Int? { - return if (bizz % 2 == 0) null else bizz - } + private fun buzz(bizz: Int): Int? { + return if (bizz % 2 == 0) null else bizz } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report vars that utilize nullable delegate values`() { - val code = """ - class A(private var aDelegate: Int?) { - private var a: Int? by this::aDelegate - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does not report vars that utilize nullable delegate values`() { + val code = """ + class A(private var aDelegate: Int?) { + private var a: Int? by this::aDelegate + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report when file-level vars are assigned nullable values`() { - val code = """ - import kotlin.random.Random + @Test + fun `does not report when file-level vars are assigned nullable values`() { + val code = """ + import kotlin.random.Random + + private var fileA: Int? = 5 + private var fileB: Int? = null + private var fileC: Int? = 5 - private var fileA: Int? = 5 - private var fileB: Int? = null - private var fileC: Int? = 5 + fun fileFoo() { + fileC = null + } - fun fileFoo() { - fileC = null + class A { + fun foo() { + fileA = null } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - class A { - fun foo() { - fileA = null - } + @Test + fun `reports when vars with private setters are never assigned nullable values`() { + val code = """ + class A { + var a: Int? = 5 + private set + fun foo() { + a = 6 } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `reports when vars with private setters are never assigned nullable values`() { - val code = """ - class A { - var a: Int? = 5 - private set - fun foo() { - a = 6 - } + @Test + fun `does not report when vars with private setters are assigned nullable values`() { + val code = """ + class A { + var a: Int? = 5 + private set + fun foo() { + a = null } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report when vars with private setters are assigned nullable values`() { - val code = """ - class A { - var a: Int? = 5 - private set - fun foo() { - a = null - } + @Test + fun `does not report when vars use public setters`() { + val code = """ + class A { + var a: Int? = 5 + fun foo() { + a = 6 } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report when vars use public setters`() { - val code = """ + @Test + fun `does not report when vars use non-private setters`() { + val code = """ class A { var a: Int? = 5 + internal set fun foo() { a = 6 } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `does not report when private vars are declared in the constructor`() { + val code = """ + class A(private var a: Int?) { + fun foo() { + a = 6 + } } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + } - @Test - fun `does not report when vars use non-private setters`() { - val code = """ - class A { - var a: Int? = 5 - internal set - fun foo() { - a = 6 - } - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + @Nested + inner class `evaluating public properties` { + @Test + fun `reports when class-level vals are set to non-nullable values`() { + val code = """ + class A(cVal: Int) { + val a: Int? = 5 + val b: Int? + val c: Int? + + init { + b = 5 + c = cVal + } } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(3) + } - @Test - fun `does not report when private vars are declared in the constructor`() { - val code = """ - class A(private var a: Int?) { - fun foo() { - a = 6 - } + @Test + fun `reports when vals utilize non-nullable delegate values`() { + val code = """ + class A { + val a: Int? by lazy { + 5 } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) } - @Nested - inner class `evaluating public properties` { - @Test - fun `reports when class-level vals are set to non-nullable values`() { - val code = """ - class A(cVal: Int) { - val a: Int? = 5 - val b: Int? - val c: Int? - - init { - b = 5 - c = cVal - } + @Test + fun `reports when file-level vals are set to non-nullable values`() { + val code = """ + val fileA: Int? = 5 + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } + + @Test + fun `does not report when class-level vals are assigned a nullable value`() { + val code = """ + import kotlin.random.Random + + class A(cVal: Int?) { + val a: Int? = null + val b: Int? + val c: Int? + + init { + b = null + c = cVal } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(3) } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `reports when vals utilize non-nullable delegate values`() { - val code = """ - class A { - val a: Int? by lazy { - 5 - } + @Test + fun `does not report when vals utilize nullable delegate values`() { + val code = """ + import kotlin.random.Random + + class A { + val d: Int? by lazy { + val randVal = Random.nextInt() + if (randVal % 2 == 0) randVal else null } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `reports when file-level vals are set to non-nullable values`() { - val code = """ - val fileA: Int? = 5 - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + @Test + fun `does not report when file-level vals are assigned a nullable value`() { + val code = """ + val fileA: Int? = null + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `does not report when vals are declared non-nullable`() { + val code = """ + class A { + val a: Int = 5 } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report when class-level vals are assigned a nullable value`() { - val code = """ - import kotlin.random.Random + @Test + fun `does not report when vals are declared in the constructor`() { + val code = """ + class A(private val a: Int?) + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - class A(cVal: Int?) { - val a: Int? = null - val b: Int? - val c: Int? - - init { - b = null - c = cVal + @Test + fun `reports when vals with getters never return nullable values`() { + val code = """ + class A { + val a: Int? + get() = 5 + val b: Int? + get() { + return 5 } + val c: Int? + get() = foo() + + private fun foo(): Int { + return 5 } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(3) + } - @Test - fun `does not report when vals utilize nullable delegate values`() { - val code = """ + @Test + fun `does not report when vals with getters return potentially-nullable values`() { + val code = """ import kotlin.random.Random - + class A { - val d: Int? by lazy { - val randVal = Random.nextInt() - if (randVal % 2 == 0) randVal else null + val a: Int? + get() = Random.nextInt()?.let { if (it % 2 == 0) it else null } + val b: Int? + get() { + return Random.nextInt()?.let { if (it % 2 == 0) it else null } + } + val c: Int? + get() = foo() + + private fun foo(): Int? { + val randInt = Random.nextInt() + return if (randInt % 2 == 0) randInt else null } } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + } + + @Test + fun `does not report open properties`() { + val code = """ + open class A { + open val a: Int? = 5 + open var b: Int? = 5 + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `does not report abstract properties`() { + val code = """ + abstract class A { + abstract val a: Int? + abstract var b: Int? } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `does not report properties whose initial assignment derives from unsafe non-Java code`() { + val code = """ + class A(msg: String?) { + private val e = Exception(msg) + // e.localizedMessage is marked as String! by Kotlin, meaning Kotlin + // cannot guarantee that it will be non-null, even though it is treated + // as non-null in Kotlin code. + private var a: String? = e.localizedMessage + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + @Test + fun `does not report interface properties`() { + val code = """ + interface A { + val a: Int? + var b: Int? + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Nested + inner class `nullable function parameters` { + @Nested + inner class `using a de-nullifier` { @Test - fun `does not report when file-level vals are assigned a nullable value`() { + fun `does report when a param is de-nullified with a postfix expression`() { val code = """ - val fileA: Int? = null - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + fun foo(a: Int?) { + val b = a!! + 2 + } + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) } @Test - fun `does not report when vals are declared non-nullable`() { + fun `does report when a param is de-nullified with a dot-qualified expression`() { val code = """ - class A { - val a: Int = 5 - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + fun foo(a: Int?) { + val b = a!!.plus(2) + } + + fun fizz(b: Int?) = b!!.plus(2) + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) } @Test - fun `does not report when vals are declared in the constructor`() { + fun `does report when a de-nullifier precondition is called on the param`() { val code = """ - class A(private val a: Int?) - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + fun foo(a: Int?, b: Int?) { + val aNonNull = requireNotNull(a) + val c = aNonNull + checkNotNull(b) + } + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) } @Test - fun `reports when vals with getters never return nullable values`() { + fun `does not report a double-bang call the field of a non-null param`() { val code = """ - class A { - val a: Int? - get() = 5 - val b: Int? - get() { - return 5 - } - val c: Int? - get() = foo() - - private fun foo(): Int { - return 5 + class A(val a: Int?) + + fun foo(a: A) { + val b = a.a!! + 2 } - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(3) + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } @Test - fun `does not report when vals with getters return potentially-nullable values`() { + fun `does not report on overridden function parameter`() { val code = """ - import kotlin.random.Random + interface A { + fun foo(a: Int?) + } - class A { - val a: Int? - get() = Random.nextInt()?.let { if (it % 2 == 0) it else null } - val b: Int? - get() { - return Random.nextInt()?.let { if (it % 2 == 0) it else null } - } - val c: Int? - get() = foo() - - private fun foo(): Int? { - val randInt = Random.nextInt() - return if (randInt % 2 == 0) randInt else null + class B : A { + override fun foo(a: Int?) { + val b = a!! + 2 } } - """ + """.trimIndent() assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } } - @Test - fun `does not report open properties`() { - val code = """ - open class A { - open val a: Int? = 5 - open var b: Int? = 5 - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `does not report abstract properties`() { - val code = """ - abstract class A { - abstract val a: Int? - abstract var b: Int? - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `does not report properties whose initial assignment derives from unsafe non-Java code`() { - val code = """ - class A(msg: String?) { - private val e = Exception(msg) - // e.localizedMessage is marked as String! by Kotlin, meaning Kotlin - // cannot guarantee that it will be non-null, even though it is treated - // as non-null in Kotlin code. - private var a: String? = e.localizedMessage - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `does not report interface properties`() { - val code = """ - interface A { - val a: Int? - var b: Int? - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - @Nested - inner class `nullable function parameters` { + inner class `using a null-safe expression` { @Nested - inner class `using a de-nullifier` { + inner class `in initializer` { @Test - fun `does report when a param is de-nullified with a postfix expression`() { + fun `does not report when the safe-qualified expression is the only expression of the function`() { val code = """ - fun foo(a: Int?) { - val b = a!! + 2 + class A { + val foo = "BAR" } + + fun foo(a: A?) = a?.foo """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } + } + @Nested + inner class `in a non-return statement` { @Test - fun `does report when a param is de-nullified with a dot-qualified expression`() { - val code = """ - fun foo(a: Int?) { - val b = a!!.plus(2) - } + fun `does report when the safe-qualified expression is the only expression of the function`() { + val code = """ + class A(val foo: String) - fun fizz(b: Int?) = b!!.plus(2) + fun foo(a: A?) { + a?.let { println(it.foo) } + } """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) } @Test - fun `does report when a de-nullifier precondition is called on the param`() { + fun `does not report when the safe-qualified expression is within a lambda`() { val code = """ - fun foo(a: Int?, b: Int?) { - val aNonNull = requireNotNull(a) - val c = aNonNull + checkNotNull(b) + class A { + fun doFoo(callback: () -> Unit) { + callback.invoke() + } + } + + fun foo(a: String?, aObj: A) { + aObj.doFoo { + a?.let { println("a not null") } + } } """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } @Test - fun `does not report a double-bang call the field of a non-null param`() { + fun `does not report when the safe-qualified expression is not the only expression of the function`() { val code = """ - class A(val a: Int?) - - fun foo(a: A) { - val b = a.a!! + 2 + class A { + fun doFoo() { println("FOO") } + } + + fun foo(a: A?) { + a?.doFoo() + val b = 5 + 2 } """.trimIndent() assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } + } + @Nested + inner class `in a return statement` { @Test - fun `does not report on overridden function parameter`() { + fun `does not report when the safe-qualified expression is the only expression of the function`() { val code = """ - interface A { - fun foo(a: Int?) + class A { + val foo = "BAR" } - class B : A { - override fun foo(a: Int?) { - val b = a!! + 2 - } + fun fizz(aObj: A?): String? { + return aObj?.foo } """.trimIndent() assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } } + } + @Nested + inner class `when statements` { @Nested - inner class `using a null-safe expression` { - @Nested - inner class `in initializer` { - @Test - fun `does not report when the safe-qualified expression is the only expression of the function`() { - val code = """ - class A { - val foo = "BAR" + inner class `without a subject` { + @Test + fun `does not report when the parameter is checked on nullity`() { + val code = """ + fun foo(a: Int?) { + when { + a == null -> println("a is null") } - - fun foo(a: A?) = a?.foo - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } - @Nested - inner class `in a non-return statement` { - @Test - fun `does report when the safe-qualified expression is the only expression of the function`() { - val code = """ - class A(val foo: String) - - fun foo(a: A?) { - a?.let { println(it.foo) } - } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `does not report when the safe-qualified expression is within a lambda`() { - val code = """ - class A { - fun doFoo(callback: () -> Unit) { - callback.invoke() - } - } - - fun foo(a: String?, aObj: A) { - aObj.doFoo { - a?.let { println("a not null") } - } - } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `does not report when the safe-qualified expression is not the only expression of the function`() { - val code = """ - class A { - fun doFoo() { println("FOO") } - } - - fun foo(a: A?) { - a?.doFoo() - val b = 5 + 2 + @Test + fun `does not report when the parameter is checked on nullity in a reversed manner`() { + val code = """ + fun foo(a: Int?) { + when { + null == a -> println("a is null") } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } - @Nested - inner class `in a return statement` { - @Test - fun `does not report when the safe-qualified expression is the only expression of the function`() { - val code = """ - class A { - val foo = "BAR" - } - - fun fizz(aObj: A?): String? { - return aObj?.foo + @Test + fun `does not report when the parameter is checked on nullity with multiple clauses`() { + val code = """ + fun foo(a: Int?, other: Int) { + when { + a == null && other % 2 == 0 -> println("a is null") } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } - } - - @Nested - inner class `when statements` { - @Nested - inner class `without a subject` { - @Test - fun `does not report when the parameter is checked on nullity`() { - val code = """ - fun foo(a: Int?) { - when { - a == null -> println("a is null") - } - } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `does not report when the parameter is checked on nullity in a reversed manner`() { - val code = """ - fun foo(a: Int?) { - when { - null == a -> println("a is null") - } - } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `does not report when the parameter is checked on nullity with multiple clauses`() { - val code = """ - fun foo(a: Int?, other: Int) { - when { - a == null && other % 2 == 0 -> println("a is null") - } - } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `does report when the parameter is only checked on non-nullity`() { - val code = """ - fun foo(a: Int?) { - when { - a != null -> println(2 + a) - } - } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `does report when the parameter is only checked on non-nullity with multiple clauses`() { - val code = """ - fun foo(a: Int?) { - when { - a != null && a % 2 == 0 -> println(2 + a) - } - } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `does not report when the parameter is checked on non-nullity with an else statement`() { - val code = """ - fun foo(a: Int?) { - when { - a != null -> println(2 + a) - else -> println("a is null") - } - } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `does not report on nullable type matching`() { - val code = """ - fun foo(a: Int?) { - when { - a !is Int -> println("a is null") - } - } - fun fizz(b: Int?) { - when { - b is Int? -> println("b is null") - } - } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `does report on non-null type matching`() { - val code = """ - fun foo(a: Int?) { - when { - a is Int -> println(2 + a) - } - } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `does report on non-null type matching with multiple clauses`() { - val code = """ - fun foo(a: Int?) { - when { - a is Int && a % 2 == 0 -> println(2 + a) - } - } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `does not report on non-null type matching with an else statement`() { - val code = """ - fun foo(a: Int?) { - when { - a is Int -> println(2 + a) - else -> println("a is null") - } + @Test + fun `does report when the parameter is only checked on non-nullity`() { + val code = """ + fun foo(a: Int?) { + when { + a != null -> println(2 + a) } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) } - @Nested - inner class `with a subject` { - @Test - fun `does not report when the parameter is checked on nullity`() { - val code = """ - fun foo(a: Int?) { - when (a) { - null -> println("a is null") - } + @Test + fun `does report when the parameter is only checked on non-nullity with multiple clauses`() { + val code = """ + fun foo(a: Int?) { + when { + a != null && a % 2 == 0 -> println(2 + a) } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `does not report on nullable type matching`() { - val code = """ - fun foo(a: Int?) { - when (a) { - !is Int -> println("a is null") - } + @Test + fun `does not report when the parameter is checked on non-nullity with an else statement`() { + val code = """ + fun foo(a: Int?) { + when { + a != null -> println(2 + a) + else -> println("a is null") } + } + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - fun fizz(b: Int?) { - when (b) { - is Int? -> println("b is null") - } + @Test + fun `does not report on nullable type matching`() { + val code = """ + fun foo(a: Int?) { + when { + a !is Int -> println("a is null") } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } - @Test - fun `does report on non-null type matching`() { - val code = """ - fun foo(a: Int?) { - when(a) { - is Int -> println(2 + a) - } + fun fizz(b: Int?) { + when { + b is Int? -> println("b is null") } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + } + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report on non-null type matching with an else statement`() { - val code = """ - fun foo(a: Int?) { - when(a) { - is Int -> println(2 + a) - else -> println("a is null") - } + @Test + fun `does report on non-null type matching`() { + val code = """ + fun foo(a: Int?) { + when { + a is Int -> println(2 + a) } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) } - } - @Nested - inner class `if-statements` { @Test - fun `does not report when the parameter is checked on nullity`() { + fun `does report on non-null type matching with multiple clauses`() { val code = """ fun foo(a: Int?) { - if (a == null) { - println("'a' is null") + when { + a is Int && a % 2 == 0 -> println(2 + a) } } + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - fun fizz(a: Int?) { - if (null == a) { - println("'a' is null") + @Test + fun `does not report on non-null type matching with an else statement`() { + val code = """ + fun foo(a: Int?) { + when { + a is Int -> println(2 + a) + else -> println("a is null") } } """.trimIndent() assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } + } + @Nested + inner class `with a subject` { @Test - fun `does not report when the if-check is in the else statement`() { + fun `does not report when the parameter is checked on nullity`() { val code = """ - fun foo(num: Int, a: Int?) { - if (num % 2 == 0) { - println("'num' is even") - } else if (a == null) { - println("'a' is null") + fun foo(a: Int?) { + when (a) { + null -> println("a is null") } } """.trimIndent() @@ -797,29 +716,29 @@ class CanBeNonNullableSpec(val env: KotlinCoreEnvironment) { } @Test - fun `does report when the parameter is only checked on non-nullity in a function`() { + fun `does not report on nullable type matching`() { val code = """ fun foo(a: Int?) { - if (a != null) { - println(a + 5) + when (a) { + !is Int -> println("a is null") } } - fun fizz(a: Int?) { - if (null != a) { - println(a + 5) + fun fizz(b: Int?) { + when (b) { + is Int? -> println("b is null") } } """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } @Test - fun `does report when the parameter is only checked on non-nullity with multiple clauses`() { + fun `does report on non-null type matching`() { val code = """ - fun foo(a: Int?, other: Int) { - if (a != null && other % 2 == 0) { - println(a + 5) + fun foo(a: Int?) { + when(a) { + is Int -> println(2 + a) } } """.trimIndent() @@ -827,31 +746,109 @@ class CanBeNonNullableSpec(val env: KotlinCoreEnvironment) { } @Test - fun `does not report when the parameter is checked on non-nullity with an else statement`() { + fun `does not report on non-null type matching with an else statement`() { val code = """ fun foo(a: Int?) { - if (a != null) { - println(a + 5) - } else { - println(5) + when(a) { + is Int -> println(2 + a) + else -> println("a is null") } } """.trimIndent() assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } + } + } - @Test - fun `does not report when there are other expressions after the non-null check`() { - val code = """ - fun foo(a: Int?) { - if (a != null) { - println(a + 5) - } - val b = 5 + 2 + @Nested + inner class `if-statements` { + @Test + fun `does not report when the parameter is checked on nullity`() { + val code = """ + fun foo(a: Int?) { + if (a == null) { + println("'a' is null") } - """.trimIndent() - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + + fun fizz(a: Int?) { + if (null == a) { + println("'a' is null") + } + } + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `does not report when the if-check is in the else statement`() { + val code = """ + fun foo(num: Int, a: Int?) { + if (num % 2 == 0) { + println("'num' is even") + } else if (a == null) { + println("'a' is null") + } + } + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `does report when the parameter is only checked on non-nullity in a function`() { + val code = """ + fun foo(a: Int?) { + if (a != null) { + println(a + 5) + } + } + + fun fizz(a: Int?) { + if (null != a) { + println(a + 5) + } + } + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2) + } + + @Test + fun `does report when the parameter is only checked on non-nullity with multiple clauses`() { + val code = """ + fun foo(a: Int?, other: Int) { + if (a != null && other % 2 == 0) { + println(a + 5) + } + } + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } + + @Test + fun `does not report when the parameter is checked on non-nullity with an else statement`() { + val code = """ + fun foo(a: Int?) { + if (a != null) { + println(a + 5) + } else { + println(5) + } + } + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `does not report when there are other expressions after the non-null check`() { + val code = """ + fun foo(a: Int?) { + if (a != null) { + println(a + 5) + } + val b = 5 + 2 + } + """.trimIndent() + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ClassOrderingSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ClassOrderingSpec.kt index 1112b4a1c0f..ebd96ce817d 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ClassOrderingSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ClassOrderingSpec.kt @@ -3,275 +3,270 @@ package io.gitlab.arturbosch.detekt.rules.style import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ClassOrderingSpec { val subject = ClassOrdering(Config.empty) - @Nested - inner class `ClassOrdering rule` { + @Test + fun `does not report when class contents are in expected order with property first`() { + val code = """ + class InOrder(private val x: String) { + val y = x - @Test - fun `does not report when class contents are in expected order with property first`() { - val code = """ - class InOrder(private val x: String) { - val y = x - - init { - check(x == "yes") - } + init { + check(x == "yes") + } - constructor(z: Int): this(z.toString()) + constructor(z: Int): this(z.toString()) - fun returnX() = x + fun returnX() = x - companion object { - const val IMPORTANT_VALUE = 3 - } + companion object { + const val IMPORTANT_VALUE = 3 } - """ + } + """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report when class contents are in expected order with class initializer first`() { - val code = """ - class InOrder(private val x: String) { - init { - check(x == "yes") - } + @Test + fun `does not report when class contents are in expected order with class initializer first`() { + val code = """ + class InOrder(private val x: String) { + init { + check(x == "yes") + } - val y = x + val y = x - constructor(z: Int): this(z.toString()) + constructor(z: Int): this(z.toString()) - fun returnX() = x + fun returnX() = x - companion object { - const val IMPORTANT_VALUE = 3 - } + companion object { + const val IMPORTANT_VALUE = 3 } - """ + } + """ + + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `reports when class initializer block is out of order`() { + val code = """ + class OutOfOrder(private val x: String) { + val y = x + + constructor(z: Int): this(z.toString()) - assertThat(subject.compileAndLint(code)).isEmpty() - } + init { + check(x == "yes") + } - @Test - fun `reports when class initializer block is out of order`() { - val code = """ - class OutOfOrder(private val x: String) { - val y = x + fun returnX() = x - constructor(z: Int): this(z.toString()) + companion object { + const val IMPORTANT_VALUE = 3 + } + } + """ + + val findings = subject.compileAndLint(code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).isEqualTo( + "initializer blocks should be declared before secondary constructors." + ) + } - init { - check(x == "yes") - } + @Test + fun `reports when secondary constructor is out of order`() { + val code = """ + class OutOfOrder(private val x: String) { + constructor(z: Int): this(z.toString()) - fun returnX() = x + val y = x - companion object { - const val IMPORTANT_VALUE = 3 - } + init { + check(x == "yes") } - """ - val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).isEqualTo( - "initializer blocks should be declared before secondary constructors." - ) - } + fun returnX() = x + + companion object { + const val IMPORTANT_VALUE = 3 + } + } + """ + + val findings = subject.compileAndLint(code) + assertThat(findings).hasSize(2) + assertThat(findings[0].message).isEqualTo( + "property `y` should be declared before secondary constructors." + ) + assertThat(findings[1].message).isEqualTo( + "initializer blocks should be declared before secondary constructors." + ) + } - @Test - fun `reports when secondary constructor is out of order`() { - val code = """ - class OutOfOrder(private val x: String) { - constructor(z: Int): this(z.toString()) + @Test + fun `reports when method is out of order`() { + val code = """ + class OutOfOrder(private val x: String) { + fun returnX() = x - val y = x + val y = x - init { - check(x == "yes") - } + init { + check(x == "yes") + } - fun returnX() = x + constructor(z: Int): this(z.toString()) - companion object { - const val IMPORTANT_VALUE = 3 - } + companion object { + const val IMPORTANT_VALUE = 3 } - """ - - val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(2) - assertThat(findings[0].message).isEqualTo( - "property `y` should be declared before secondary constructors." - ) - assertThat(findings[1].message).isEqualTo( - "initializer blocks should be declared before secondary constructors." - ) - } - - @Test - fun `reports when method is out of order`() { - val code = """ - class OutOfOrder(private val x: String) { - fun returnX() = x - - val y = x - - init { - check(x == "yes") - } - - constructor(z: Int): this(z.toString()) - - companion object { - const val IMPORTANT_VALUE = 3 - } + } + """ + + val findings = subject.compileAndLint(code) + assertThat(findings).hasSize(3) + assertThat(findings[0].message) + .isEqualTo("property `y` should be declared before method declarations.") + assertThat(findings[1].message) + .isEqualTo("initializer blocks should be declared before method declarations.") + assertThat(findings[2].message) + .isEqualTo("secondary constructor should be declared before method declarations.") + } + + @Test + fun `reports when companion object is out of order`() { + val code = """ + class OutOfOrder(private val x: String) { + val y = x + + init { + check(x == "yes") } - """ - - val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(3) - assertThat(findings[0].message) - .isEqualTo("property `y` should be declared before method declarations.") - assertThat(findings[1].message) - .isEqualTo("initializer blocks should be declared before method declarations.") - assertThat(findings[2].message) - .isEqualTo("secondary constructor should be declared before method declarations.") - } - - @Test - fun `reports when companion object is out of order`() { - val code = """ - class OutOfOrder(private val x: String) { - val y = x - - init { - check(x == "yes") - } - - constructor(z: Int): this(z.toString()) - - companion object { - const val IMPORTANT_VALUE = 3 - } - - fun returnX() = x + + constructor(z: Int): this(z.toString()) + + companion object { + const val IMPORTANT_VALUE = 3 } - """ - val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).isEqualTo("method `returnX()` should be declared before companion object.") - } + fun returnX() = x + } + """ - @Test - fun `does not report nested class order`() { - val code = """ - class OutOfOrder(private val x: String) { - val y = x + val findings = subject.compileAndLint(code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).isEqualTo("method `returnX()` should be declared before companion object.") + } - init { - check(x == "yes") - } + @Test + fun `does not report nested class order`() { + val code = """ + class OutOfOrder(private val x: String) { + val y = x - constructor(z: Int): this(z.toString()) + init { + check(x == "yes") + } - class Nested { - fun foo() = 2 - } + constructor(z: Int): this(z.toString()) - fun returnX() = x + class Nested { + fun foo() = 2 } - """ - assertThat(subject.compileAndLint(code)).hasSize(0) - } + fun returnX() = x + } + """ + + assertThat(subject.compileAndLint(code)).hasSize(0) + } + + @Test + fun `does not report anonymous object order`() { + val code = """ + class OutOfOrder(private val x: String) { + val y = x + + init { + check(x == "yes") + } - @Test - fun `does not report anonymous object order`() { - val code = """ - class OutOfOrder(private val x: String) { - val y = x + constructor(z: Int): this(z.toString()) - init { - check(x == "yes") - } + object AnonymousObject { + fun foo() = 2 + } - constructor(z: Int): this(z.toString()) + fun returnX() = x + } + """ - object AnonymousObject { - fun foo() = 2 - } + assertThat(subject.compileAndLint(code)).hasSize(0) + } - fun returnX() = x + @Test + fun `report all issues with interleaving nested class`() { + val code = """ + class MultipleMisorders(private val x: String) { + companion object { + const val IMPORTANT_VALUE = 3 } - """ - assertThat(subject.compileAndLint(code)).hasSize(0) - } + class Nested { } - @Test - fun `report all issues with interleaving nested class`() { - val code = """ - class MultipleMisorders(private val x: String) { - companion object { - const val IMPORTANT_VALUE = 3 - } + fun returnX() = x - class Nested { } + class Nested2 { } - fun returnX() = x + constructor(z: Int): this(z.toString()) - class Nested2 { } + class Nested3 { } + + val y = x + } + """ - constructor(z: Int): this(z.toString()) + val findings = subject.compileAndLint(code) + assertThat(findings).hasSize(3) + assertThat(findings[0].message) + .isEqualTo("method `returnX()` should be declared before companion object.") + assertThat(findings[1].message) + .isEqualTo("secondary constructor should be declared before companion object.") + assertThat(findings[2].message) + .isEqualTo("property `y` should be declared before companion object.") + } - class Nested3 { } - - val y = x + @Test + fun `does report all issues in a class with multiple misorderings`() { + val code = """ + class MultipleMisorders(private val x: String) { + companion object { + const val IMPORTANT_VALUE = 3 } - """ - - val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(3) - assertThat(findings[0].message) - .isEqualTo("method `returnX()` should be declared before companion object.") - assertThat(findings[1].message) - .isEqualTo("secondary constructor should be declared before companion object.") - assertThat(findings[2].message) - .isEqualTo("property `y` should be declared before companion object.") - } - - @Test - fun `does report all issues in a class with multiple misorderings`() { - val code = """ - class MultipleMisorders(private val x: String) { - companion object { - const val IMPORTANT_VALUE = 3 - } - - fun returnX() = x - - constructor(z: Int): this(z.toString()) - - val y = x - } - """ - - val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(3) - assertThat(findings[0].message) - .isEqualTo("method `returnX()` should be declared before companion object.") - assertThat(findings[1].message) - .isEqualTo("secondary constructor should be declared before companion object.") - assertThat(findings[2].message) - .isEqualTo("property `y` should be declared before companion object.") - } + + fun returnX() = x + + constructor(z: Int): this(z.toString()) + + val y = x + } + """ + + val findings = subject.compileAndLint(code) + assertThat(findings).hasSize(3) + assertThat(findings[0].message) + .isEqualTo("method `returnX()` should be declared before companion object.") + assertThat(findings[1].message) + .isEqualTo("secondary constructor should be declared before companion object.") + assertThat(findings[2].message) + .isEqualTo("property `y` should be declared before companion object.") } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/CollapsibleIfStatementsSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/CollapsibleIfStatementsSpec.kt index cb35de8edfd..d8193d2c7a6 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/CollapsibleIfStatementsSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/CollapsibleIfStatementsSpec.kt @@ -3,118 +3,113 @@ package io.gitlab.arturbosch.detekt.rules.style import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class CollapsibleIfStatementsSpec { val subject = CollapsibleIfStatements(Config.empty) - @Nested - inner class `CollapsibleIfStatements rule` { - - @Test - fun `reports if statements which can be merged`() { - val code = """ - fun f() { - if (true) { - if (1 == 1) {} - // a comment - } + @Test + fun `reports if statements which can be merged`() { + val code = """ + fun f() { + if (true) { + if (1 == 1) {} + // a comment } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports nested if statements which can be merged`() { - val code = """ - fun f() { - if (true) { - if (1 == 1) { - if (2 == 2) {} - } - println() + @Test + fun `reports nested if statements which can be merged`() { + val code = """ + fun f() { + if (true) { + if (1 == 1) { + if (2 == 2) {} } + println() } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report else-if`() { - val code = """ - fun f() { + @Test + fun `does not report else-if`() { + val code = """ + fun f() { + if (true) {} + else if (1 == 1) { if (true) {} - else if (1 == 1) { - if (true) {} - } } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report if-else`() { - val code = """ - fun f() { - if (true) { - if (1 == 1) {} - } else {} - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report if-else`() { + val code = """ + fun f() { + if (true) { + if (1 == 1) {} + } else {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report if-elseif-else`() { - val code = """ - fun f() { - if (true) { - if (1 == 1) {} - } else if (false) {} - else {} - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report if-elseif-else`() { + val code = """ + fun f() { + if (true) { + if (1 == 1) {} + } else if (false) {} + else {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report if with statements in the if body`() { - val code = """ - fun f() { - if (true) { - if (1 == 1) ; - println() - } + @Test + fun `does not report if with statements in the if body`() { + val code = """ + fun f() { + if (true) { + if (1 == 1) ; + println() } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report nested if-else`() { - val code = """ - fun f() { - if (true) { - if (1 == 1) { - } else {} - } + @Test + fun `does not report nested if-else`() { + val code = """ + fun f() { + if (true) { + if (1 == 1) { + } else {} } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report nested if-elseif`() { - val code = """ - fun f() { - if (true) { - if (1 == 1) { - } else if (2 == 2) {} - } + @Test + fun `does not report nested if-elseif`() { + val code = """ + fun f() { + if (true) { + if (1 == 1) { + } else if (2 == 2) {} } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/DataClassContainsFunctionsSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/DataClassContainsFunctionsSpec.kt index 74d0761d279..d78b0e82f74 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/DataClassContainsFunctionsSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/DataClassContainsFunctionsSpec.kt @@ -12,68 +12,64 @@ class DataClassContainsFunctionsSpec { val subject = DataClassContainsFunctions() @Nested - inner class `DataClassContainsFunctions rule` { + inner class `flagged functions in data class` { + val code = """ + data class C(val s: String) { + fun f() {} - @Nested - inner class `flagged functions in data class` { - val code = """ - data class C(val s: String) { - fun f() {} - - data class Nested(val i: Int) { - fun toConversion() = C(i.toString()) - } + data class Nested(val i: Int) { + fun toConversion() = C(i.toString()) } - """ - - @Test - fun `reports valid data class with conversion function`() { - assertThat(subject.compileAndLint(code)).hasSize(1) } - - @Test - fun `reports valid data class without conversion function`() { - val config = TestConfig(mapOf(CONVERSION_FUNCTION_PREFIX to "")) - val rule = DataClassContainsFunctions(config) - assertThat(rule.compileAndLint(code)).hasSize(2) - } - } + """ @Test - fun `does not report a data class without a function`() { - val code = "data class C(val i: Int)" - assertThat(subject.compileAndLint(code)).isEmpty() + fun `reports valid data class with conversion function`() { + assertThat(subject.compileAndLint(code)).hasSize(1) } @Test - fun `does not report a non-data class without a function`() { - val code = """ - class C { - fun f() {} - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() + fun `reports valid data class without conversion function`() { + val config = TestConfig(mapOf(CONVERSION_FUNCTION_PREFIX to "")) + val rule = DataClassContainsFunctions(config) + assertThat(rule.compileAndLint(code)).hasSize(2) } + } - @Test - fun `does not report a data class with overridden functions`() { - val code = """ - data class C(val i: Int) { + @Test + fun `does not report a data class without a function`() { + val code = "data class C(val i: Int)" + assertThat(subject.compileAndLint(code)).isEmpty() + } - override fun hashCode(): Int { - return super.hashCode() - } + @Test + fun `does not report a non-data class without a function`() { + val code = """ + class C { + fun f() {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - override fun equals(other: Any?): Boolean { - return super.equals(other) - } + @Test + fun `does not report a data class with overridden functions`() { + val code = """ + data class C(val i: Int) { - override fun toString(): String { - return super.toString() - } + override fun hashCode(): Int { + return super.hashCode() } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + + override fun equals(other: Any?): Boolean { + return super.equals(other) + } + + override fun toString(): String { + return super.toString() + } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/DataClassShouldBeImmutableSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/DataClassShouldBeImmutableSpec.kt index 2696641127a..06da33906d5 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/DataClassShouldBeImmutableSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/DataClassShouldBeImmutableSpec.kt @@ -2,86 +2,81 @@ package io.gitlab.arturbosch.detekt.rules.style import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class DataClassShouldBeImmutableSpec { val subject = DataClassShouldBeImmutable() - @Nested - inner class `DataClassShouldBeImmutable rule` { - - @Test - fun `reports mutable variable in primary constructor`() { - val code = "data class C(var i: Int)" - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports mutable variable in primary constructor`() { + val code = "data class C(var i: Int)" + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports mutable property in class body`() { - val code = """ - data class C(val i: Int) { - var s: String? = null - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports mutable property in class body`() { + val code = """ + data class C(val i: Int) { + var s: String? = null + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports mutable private property in class body`() { - val code = """ - data class C(val i: Int) { - var s: String = "" - private set - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports mutable private property in class body`() { + val code = """ + data class C(val i: Int) { + var s: String = "" + private set + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports lateinit property in class body`() { - val code = """ - data class C(val i: Int) { - lateinit var s: String - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports lateinit property in class body`() { + val code = """ + data class C(val i: Int) { + lateinit var s: String + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report readonly variable in primary constructor`() { - val code = "data class C(val i: Int)" - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report readonly variable in primary constructor`() { + val code = "data class C(val i: Int)" + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report readonly property in class body`() { - val code = """ - data class C(val i: Int) { - val s: String? = null - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report readonly property in class body`() { + val code = """ + data class C(val i: Int) { + val s: String? = null + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report lazy property in class body`() { - val code = """ - data class C(val i: Int) { - val s: String by lazy { "" } - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report lazy property in class body`() { + val code = """ + data class C(val i: Int) { + val s: String by lazy { "" } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report mutable variables in non-data classes`() { - val code = """ - class C(var i: Int) { - val s: String by lazy { "" } - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report mutable variables in non-data classes`() { + val code = """ + class C(var i: Int) { + val s: String by lazy { "" } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/DestructuringDeclarationWithTooManyEntriesSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/DestructuringDeclarationWithTooManyEntriesSpec.kt index c1f487fd2dd..13b35539539 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/DestructuringDeclarationWithTooManyEntriesSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/DestructuringDeclarationWithTooManyEntriesSpec.kt @@ -12,110 +12,106 @@ class DestructuringDeclarationWithTooManyEntriesSpec { val subject = DestructuringDeclarationWithTooManyEntries() @Nested - inner class `DestructuringDeclarationWithTooManyEntries rule` { + inner class `default configuration` { + + @Test + fun `does not report destructuring declarations with 2 or 3 entries`() { + val code = """ + fun testFun() { + val (x, y) = Pair(3, 4) + println(x) + println(y) + + val (a, b, c) = Triple(1, 2, 3) + println(a) + println(b) + println(c) + } + """.trimIndent() + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Nested - inner class `default configuration` { + @Test + fun `reports destructuring declarations with more than 3 entries`() { + val code = """ + fun testFun() { + data class ManyElements(val a: Int, val b: Int, val c: Int, val d: Int) + + val (a, b, c, d) = ManyElements(1, 2, 3, 4) + println(a) + println(b) + println(c) + println(d) + } + """.trimIndent() + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report destructuring declarations with 2 or 3 entries`() { - val code = """ - fun testFun() { - val (x, y) = Pair(3, 4) - println(x) - println(y) - - val (a, b, c) = Triple(1, 2, 3) + @Test + fun `does not report destructuring declarations in lambdas with 2 or 3 entries`() { + val code = """ + fun testFun() { + val items = listOf(Pair(3, 4)) + + items.forEach { (a, b) -> println(a) println(b) - println(c) } - """.trimIndent() - assertThat(subject.compileAndLint(code)).isEmpty() } + """.trimIndent() + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports destructuring declarations with more than 3 entries`() { - val code = """ - fun testFun() { - data class ManyElements(val a: Int, val b: Int, val c: Int, val d: Int) + @Test + fun `reports destructuring declarations in lambdas with more than 3 entries`() { + val code = """ + fun testFun() { + data class ManyElements(val a: Int, val b: Int, val c: Int, val d: Int) - val (a, b, c, d) = ManyElements(1, 2, 3, 4) + val items = listOf(ManyElements(1, 2, 3, 4)) + items.forEach { (a, b, c, d) -> println(a) println(b) println(c) println(d) } - """.trimIndent() - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `does not report destructuring declarations in lambdas with 2 or 3 entries`() { - val code = """ - fun testFun() { - val items = listOf(Pair(3, 4)) - - items.forEach { (a, b) -> - println(a) - println(b) - } - } - """.trimIndent() - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `reports destructuring declarations in lambdas with more than 3 entries`() { - val code = """ - fun testFun() { - data class ManyElements(val a: Int, val b: Int, val c: Int, val d: Int) - - val items = listOf(ManyElements(1, 2, 3, 4)) - items.forEach { (a, b, c, d) -> - println(a) - println(b) - println(c) - println(d) - } - } - """.trimIndent() - assertThat(subject.compileAndLint(code)).hasSize(1) } + """.trimIndent() + assertThat(subject.compileAndLint(code)).hasSize(1) } + } - @Nested - inner class `maxDestructuringEntries = 2` { - - val configuredRule = - DestructuringDeclarationWithTooManyEntries( - TestConfig(mapOf(MAX_DESTRUCTURING_ENTRIES to "2")) - ) - - @Test - fun `does not report destructuring declarations with 2 entries`() { - val code = """ - fun testFun() { - val (x, y) = Pair(3, 4) - println(x) - println(y) - } - """.trimIndent() - assertThat(configuredRule.compileAndLint(code)).isEmpty() + @Nested + inner class `maxDestructuringEntries = 2` { + + val configuredRule = + DestructuringDeclarationWithTooManyEntries( + TestConfig(mapOf(MAX_DESTRUCTURING_ENTRIES to "2")) + ) + + @Test + fun `does not report destructuring declarations with 2 entries`() { + val code = """ + fun testFun() { + val (x, y) = Pair(3, 4) + println(x) + println(y) } + """.trimIndent() + assertThat(configuredRule.compileAndLint(code)).isEmpty() + } - @Test - fun `reports destructuring declarations with more than 2 entries`() { - val code = """ - fun testFun() { - val (a, b, c) = Triple(1, 2, 3) - println(a) - println(b) - println(c) - } - """.trimIndent() - assertThat(configuredRule.compileAndLint(code)).hasSize(1) + @Test + fun `reports destructuring declarations with more than 2 entries`() { + val code = """ + fun testFun() { + val (a, b, c) = Triple(1, 2, 3) + println(a) + println(b) + println(c) } + """.trimIndent() + assertThat(configuredRule.compileAndLint(code)).hasSize(1) } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/EqualsNullCallSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/EqualsNullCallSpec.kt index 74bad95baa7..67a42ffdecf 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/EqualsNullCallSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/EqualsNullCallSpec.kt @@ -3,43 +3,38 @@ package io.gitlab.arturbosch.detekt.rules.style import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class EqualsNullCallSpec { val subject = EqualsNullCall(Config.empty) - @Nested - inner class `EqualsNullCall rule` { - - @Test - fun `reports equals call with null as parameter`() { - val code = """ - fun x(a: String) { - a.equals(null) - } - """ - assertThat(subject.compileAndLint(code).size).isEqualTo(1) - } + @Test + fun `reports equals call with null as parameter`() { + val code = """ + fun x(a: String) { + a.equals(null) + } + """ + assertThat(subject.compileAndLint(code).size).isEqualTo(1) + } - @Test - fun `reports nested equals call with null as parameter`() { - val code = """ - fun x(a: String, b: String) { - a.equals(b.equals(null)) - } - """ - assertThat(subject.compileAndLint(code).size).isEqualTo(1) - } + @Test + fun `reports nested equals call with null as parameter`() { + val code = """ + fun x(a: String, b: String) { + a.equals(b.equals(null)) + } + """ + assertThat(subject.compileAndLint(code).size).isEqualTo(1) + } - @Test - fun `does not report equals call with parameter of type string`() { - val code = """ - fun x(a: String, b: String) { - a.equals(b) - } - """ - assertThat(subject.compileAndLint(code).size).isEqualTo(0) - } + @Test + fun `does not report equals call with parameter of type string`() { + val code = """ + fun x(a: String, b: String) { + a.equals(b) + } + """ + assertThat(subject.compileAndLint(code).size).isEqualTo(0) } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/EqualsOnSignatureLineSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/EqualsOnSignatureLineSpec.kt index 0bd708bffe0..6fce96b1cf0 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/EqualsOnSignatureLineSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/EqualsOnSignatureLineSpec.kt @@ -10,156 +10,152 @@ class EqualsOnSignatureLineSpec { val subject = EqualsOnSignatureLine(Config.empty) @Nested - inner class `EqualsOnSignatureLine rule` { - - @Nested - inner class `with expression syntax and without a return type` { - @Test - fun `reports when the equals is on a new line`() { - val findings = subject.compileAndLint( - """ - fun foo() - = 1 - """ - ) - assertThat(findings).hasSize(1) - } - - @Test - fun `does not report when the equals is on the same line`() { - val findings = subject.compileAndLint( - """ - fun foo() = 1 - - fun bar() = - 2 - """ - ) - assertThat(findings).isEmpty() - } + inner class `with expression syntax and without a return type` { + @Test + fun `reports when the equals is on a new line`() { + val findings = subject.compileAndLint( + """ + fun foo() + = 1 + """ + ) + assertThat(findings).hasSize(1) } - @Nested - inner class `with expression syntax and with a return type` { - @Test - fun `reports when the equals is on a new line`() { - val findings = subject.compileAndLint( - """ - fun one(): Int - = 1 + @Test + fun `does not report when the equals is on the same line`() { + val findings = subject.compileAndLint( + """ + fun foo() = 1 - fun two( - foo: String - ) - = 2 - - fun three( - foo: String - ): Int - = 3 - """ - ) - assertThat(findings).hasSize(3) - } - - @Test - fun `does not report when the equals is on the same line`() { - val findings = subject.compileAndLint( - """ - fun one(): Int = - 1 - - fun two() - : Int = - 2 - - fun three(): - Int = - 3 - - fun four( - foo: String - ): Int = - 4 - - fun five( - foo: String - ) + fun bar() = + 2 + """ + ) + assertThat(findings).isEmpty() + } + } + + @Nested + inner class `with expression syntax and with a return type` { + @Test + fun `reports when the equals is on a new line`() { + val findings = subject.compileAndLint( + """ + fun one(): Int + = 1 + + fun two( + foo: String + ) + = 2 + + fun three( + foo: String + ): Int + = 3 + """ + ) + assertThat(findings).hasSize(3) + } + + @Test + fun `does not report when the equals is on the same line`() { + val findings = subject.compileAndLint( + """ + fun one(): Int = + 1 + + fun two() : Int = - 5 + 2 - fun six( - foo: String - ) - : + fun three(): Int = - 6 - """ - ) - assertThat(findings).isEmpty() - } - } + 3 - @Nested - inner class `with expression syntax and with a where clause` { - @Test - fun `reports when the equals is on a new line`() { - val findings = subject.compileAndLint( - """ - fun one(): Int where V : Number - = 1 + fun four( + foo: String + ): Int = + 4 + + fun five( + foo: String + ) + : Int = + 5 + + fun six( + foo: String + ) + : + Int = + 6 + """ + ) + assertThat(findings).isEmpty() + } + } - fun two( - foo: String - ) where V : Number - = 2 - - fun three( - foo: String - ): Int - where V : Number - = 3 - """ - ) - assertThat(findings).hasSize(3) - } - - @Test - fun `does not report when the equals is on the same line`() { - val findings = subject.compileAndLint( - """ - fun one(): Int where V : Number = - 1 - - fun two() : Int - where V : Number = - 2 - - """ - ) - assertThat(findings).isEmpty() - } + @Nested + inner class `with expression syntax and with a where clause` { + @Test + fun `reports when the equals is on a new line`() { + val findings = subject.compileAndLint( + """ + fun one(): Int where V : Number + = 1 + + fun two( + foo: String + ) where V : Number + = 2 + + fun three( + foo: String + ): Int + where V : Number + = 3 + """ + ) + assertThat(findings).hasSize(3) } @Test - fun `does not report non-expression functions`() { + fun `does not report when the equals is on the same line`() { val findings = subject.compileAndLint( """ - fun foo() { - } + fun one(): Int where V : Number = + 1 - fun bar() - { - } + fun two() : Int + where V : Number = + 2 - fun baz() - : - Unit - { - } """ ) assertThat(findings).isEmpty() } } + + @Test + fun `does not report non-expression functions`() { + val findings = subject.compileAndLint( + """ + fun foo() { + } + + fun bar() + { + } + + fun baz() + : + Unit + { + } + """ + ) + assertThat(findings).isEmpty() + } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ExplicitItLambdaParameterSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ExplicitItLambdaParameterSpec.kt index 40ab8dedb37..ab3bc04bc41 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ExplicitItLambdaParameterSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ExplicitItLambdaParameterSpec.kt @@ -10,76 +10,73 @@ class ExplicitItLambdaParameterSpec { val subject = ExplicitItLambdaParameter(Config.empty) @Nested - inner class `ExplicitItLambdaParameter rule` { - @Nested - inner class `single parameter lambda with name 'it' declared explicitly` { - @Test - fun `reports when parameter type is not declared`() { - val findings = subject.compileAndLint( - """ - fun f() { - val digits = 1234.let { it -> listOf(it) } - } - """ - ) - assertThat(findings).hasSize(1) + inner class `single parameter lambda with name 'it' declared explicitly` { + @Test + fun `reports when parameter type is not declared`() { + val findings = subject.compileAndLint( + """ + fun f() { + val digits = 1234.let { it -> listOf(it) } } + """ + ) + assertThat(findings).hasSize(1) + } - @Test - fun `reports when parameter type is declared explicitly`() { - val findings = subject.compileAndLint( - """ - fun f() { - val lambda = { it: Int -> it.toString() } - } - """ - ) - assertThat(findings).hasSize(1) + @Test + fun `reports when parameter type is declared explicitly`() { + val findings = subject.compileAndLint( + """ + fun f() { + val lambda = { it: Int -> it.toString() } } + """ + ) + assertThat(findings).hasSize(1) } + } - @Nested - inner class `no parameter declared explicitly` { - @Test - fun `does not report implicit 'it' parameter usage`() { - val findings = subject.compileAndLint( - """ - fun f() { - val lambda = { i: Int -> i.toString() } - val digits = 1234.let { lambda(it) }.toList() - val flat = listOf(listOf(1), listOf(2)).flatMap { it } - } - """ - ) - assertThat(findings).isEmpty() + @Nested + inner class `no parameter declared explicitly` { + @Test + fun `does not report implicit 'it' parameter usage`() { + val findings = subject.compileAndLint( + """ + fun f() { + val lambda = { i: Int -> i.toString() } + val digits = 1234.let { lambda(it) }.toList() + val flat = listOf(listOf(1), listOf(2)).flatMap { it } } + """ + ) + assertThat(findings).isEmpty() } + } - @Nested - inner class `multiple parameters one of which with name 'it' declared explicitly` { - @Test - fun `reports when parameter types are not declared`() { - val findings = subject.compileAndLint( - """ - fun f() { - val flat = listOf(listOf(1), listOf(2)).mapIndexed { index, it -> it + index } - } - """ - ) - assertThat(findings).hasSize(1) + @Nested + inner class `multiple parameters one of which with name 'it' declared explicitly` { + @Test + fun `reports when parameter types are not declared`() { + val findings = subject.compileAndLint( + """ + fun f() { + val flat = listOf(listOf(1), listOf(2)).mapIndexed { index, it -> it + index } } + """ + ) + assertThat(findings).hasSize(1) + } - @Test - fun `reports when parameter types are declared explicitly`() { - val findings = subject.compileAndLint( - """ - fun f() { - val lambda = { it: Int, that: String -> it.toString() + that } - } - """ - ) - assertThat(findings).hasSize(1) + @Test + fun `reports when parameter types are declared explicitly`() { + val findings = subject.compileAndLint( + """ + fun f() { + val lambda = { it: Int, that: String -> it.toString() + that } } + """ + ) + assertThat(findings).hasSize(1) } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ExpressionBodySyntaxSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ExpressionBodySyntaxSpec.kt index cfc8fa20b7d..27564a265ab 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ExpressionBodySyntaxSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ExpressionBodySyntaxSpec.kt @@ -13,150 +13,146 @@ class ExpressionBodySyntaxSpec { val subject = ExpressionBodySyntax(Config.empty) @Nested - inner class `ExpressionBodySyntax rule` { - - @Nested - inner class `several return statements` { - - @Test - fun `reports constant return`() { - assertThat( - subject.compileAndLint( - """ - fun stuff(): Int { - return 5 - } - """ - ) - ).hasSize(1) - } - - @Test - fun `reports return statement with method chain`() { - assertThat( - subject.compileAndLint( - """ - fun stuff(): String { - return StringBuilder().append(0).toString() - } - """ - ) - ).hasSize(1) - } - - @Test - fun `reports return statements with conditionals`() { - assertThat( - subject.compileAndLint( - """ - fun stuff(): Int { - return if (true) return 5 else return 3 - } - fun stuff(): Int { - return try { return 5 } catch (e: Exception) { return 3 } - } - """ - ) - ).hasSize(2) - } + inner class `several return statements` { + + @Test + fun `reports constant return`() { + assertThat( + subject.compileAndLint( + """ + fun stuff(): Int { + return 5 + } + """ + ) + ).hasSize(1) + } - @Test - fun `does not report multiple if statements`() { - assertThat( - subject.compileAndLint( - """ - fun stuff(): Boolean { - if (true) return true - return false - } - """ - ) - ).isEmpty() - } + @Test + fun `reports return statement with method chain`() { + assertThat( + subject.compileAndLint( + """ + fun stuff(): String { + return StringBuilder().append(0).toString() + } + """ + ) + ).hasSize(1) + } - @Test - fun `does not report when using shortcut return`() { - assertThat( - subject.compileAndLint( - """ - fun caller(): String { - return callee("" as String? ?: return "") - } - - fun callee(a: String): String = "" - """ - ) - ).isEmpty() - } + @Test + fun `reports return statements with conditionals`() { + assertThat( + subject.compileAndLint( + """ + fun stuff(): Int { + return if (true) return 5 else return 3 + } + fun stuff(): Int { + return try { return 5 } catch (e: Exception) { return 3 } + } + """ + ) + ).hasSize(2) } - @Nested - inner class `several return statements with multiline method chain` { + @Test + fun `does not report multiple if statements`() { + assertThat( + subject.compileAndLint( + """ + fun stuff(): Boolean { + if (true) return true + return false + } + """ + ) + ).isEmpty() + } - val code = """ - fun stuff(): String { - return StringBuilder() - .append(1) - .toString() + @Test + fun `does not report when using shortcut return`() { + assertThat( + subject.compileAndLint( + """ + fun caller(): String { + return callee("" as String? ?: return "") } - """ - @Test - fun `does not report with the default configuration`() { - assertThat(subject.compileAndLint(code)).isEmpty() - } + fun callee(a: String): String = "" + """ + ) + ).isEmpty() + } + } - @Test - fun `reports with includeLineWrapping = true configuration`() { - val config = TestConfig(mapOf(INCLUDE_LINE_WRAPPING to "true")) - assertThat(ExpressionBodySyntax(config).compileAndLint(code)).hasSize(1) + @Nested + inner class `several return statements with multiline method chain` { + + val code = """ + fun stuff(): String { + return StringBuilder() + .append(1) + .toString() } + """ + + @Test + fun `does not report with the default configuration`() { + assertThat(subject.compileAndLint(code)).isEmpty() } - @Nested - inner class `several return statements with multiline when expression` { + @Test + fun `reports with includeLineWrapping = true configuration`() { + val config = TestConfig(mapOf(INCLUDE_LINE_WRAPPING to "true")) + assertThat(ExpressionBodySyntax(config).compileAndLint(code)).hasSize(1) + } + } - val code = """ - fun stuff(arg: Int): Int { - return when(arg) { - 0 -> 0 - else -> 1 - } - } - """ + @Nested + inner class `several return statements with multiline when expression` { - @Test - fun `does not report with the default configuration`() { - assertThat(subject.compileAndLint(code)).isEmpty() + val code = """ + fun stuff(arg: Int): Int { + return when(arg) { + 0 -> 0 + else -> 1 + } } + """ - @Test - fun `reports with includeLineWrapping = true configuration`() { - val config = TestConfig(mapOf(INCLUDE_LINE_WRAPPING to "true")) - assertThat(ExpressionBodySyntax(config).compileAndLint(code)).hasSize(1) - } + @Test + fun `does not report with the default configuration`() { + assertThat(subject.compileAndLint(code)).isEmpty() } - @Nested - inner class `several return statements with multiline if expression` { + @Test + fun `reports with includeLineWrapping = true configuration`() { + val config = TestConfig(mapOf(INCLUDE_LINE_WRAPPING to "true")) + assertThat(ExpressionBodySyntax(config).compileAndLint(code)).hasSize(1) + } + } - val code = """ - fun stuff(arg: Int): Int { - return if (arg == 0) 0 - else 1 - } - """ + @Nested + inner class `several return statements with multiline if expression` { - @Test - fun `does not report with the default configuration`() { - assertThat(subject.compileAndLint(code)).isEmpty() + val code = """ + fun stuff(arg: Int): Int { + return if (arg == 0) 0 + else 1 } + """ - @Test - fun `reports with includeLineWrapping = true configuration`() { - val config = TestConfig(mapOf(INCLUDE_LINE_WRAPPING to "true")) - assertThat(ExpressionBodySyntax(config).compileAndLint(code)).hasSize(1) - } + @Test + fun `does not report with the default configuration`() { + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `reports with includeLineWrapping = true configuration`() { + val config = TestConfig(mapOf(INCLUDE_LINE_WRAPPING to "true")) + assertThat(ExpressionBodySyntax(config).compileAndLint(code)).hasSize(1) } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenCommentSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenCommentSpec.kt index ef9d2c18cf0..c1c1b7e0f55 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenCommentSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenCommentSpec.kt @@ -23,231 +23,227 @@ class ForbiddenCommentSpec { val stopShip = "// STOPSHIP I need to fix this." @Nested - inner class `ForbiddenComment rule` { + inner class `the default values are configured` { - @Nested - inner class `the default values are configured` { + @Test + @DisplayName("should report TODO: usages") + fun reportTodoColon() { + val findings = ForbiddenComment().compileAndLint(todoColon) + assertThat(findings).hasSize(1) + } - @Test - @DisplayName("should report TODO: usages") - fun reportTodoColon() { - val findings = ForbiddenComment().compileAndLint(todoColon) - assertThat(findings).hasSize(1) - } + @Test + fun `should not report TODO usages`() { + val findings = ForbiddenComment().compileAndLint(todo) + assertThat(findings).isEmpty() + } - @Test - fun `should not report TODO usages`() { - val findings = ForbiddenComment().compileAndLint(todo) - assertThat(findings).isEmpty() - } + @Test + @DisplayName("should report FIXME: usages") + fun reportFixMe() { + val findings = ForbiddenComment().compileAndLint(fixmeColon) + assertThat(findings).hasSize(1) + } - @Test - @DisplayName("should report FIXME: usages") - fun reportFixMe() { - val findings = ForbiddenComment().compileAndLint(fixmeColon) - assertThat(findings).hasSize(1) - } + @Test + fun `should not report FIXME usages`() { + val findings = ForbiddenComment().compileAndLint(fixme) + assertThat(findings).isEmpty() + } + + @Test + @DisplayName("should report STOPSHIP: usages") + fun reportStopShipColon() { + val findings = ForbiddenComment().compileAndLint(stopShipColon) + assertThat(findings).hasSize(1) + } + + @Test + fun `should not report STOPSHIP usages`() { + val findings = ForbiddenComment().compileAndLint(stopShip) + assertThat(findings).isEmpty() + } + + @Test + fun `should report violation in multiline comment`() { + val code = """ + /* + TODO: I need to fix this. + */ + """ + val findings = ForbiddenComment().compileAndLint(code) + assertThat(findings).hasSize(1) + } + + @Test + fun `should report violation in KDoc`() { + val code = """ + /** + * TODO: I need to fix this. + */ + class A { + /** + * TODO: I need to fix this. + */ + } + """ + val findings = ForbiddenComment().compileAndLint(code) + assertThat(findings).hasSize(2) + } + } + + @Nested + inner class `custom default values are configured` { + val banana = "// Banana." + + @Nested + inner class `when given Banana` { + val config = TestConfig(mapOf(VALUES to "Banana")) @Test - fun `should not report FIXME usages`() { - val findings = ForbiddenComment().compileAndLint(fixme) + @DisplayName("should not report TODO: usages") + fun todoColon() { + val findings = ForbiddenComment(config).compileAndLint(todoColon) assertThat(findings).isEmpty() } @Test - @DisplayName("should report STOPSHIP: usages") - fun reportStopShipColon() { - val findings = ForbiddenComment().compileAndLint(stopShipColon) - assertThat(findings).hasSize(1) + @DisplayName("should not report FIXME: usages") + fun fixmeColon() { + val findings = ForbiddenComment(config).compileAndLint(fixmeColon) + assertThat(findings).isEmpty() } @Test - fun `should not report STOPSHIP usages`() { - val findings = ForbiddenComment().compileAndLint(stopShip) + @DisplayName("should not report STOPME: usages") + fun stopShipColon() { + val findings = ForbiddenComment(config).compileAndLint(stopShipColon) assertThat(findings).isEmpty() } @Test - fun `should report violation in multiline comment`() { - val code = """ - /* - TODO: I need to fix this. - */ - """ - val findings = ForbiddenComment().compileAndLint(code) + fun `should report Banana usages`() { + val findings = ForbiddenComment(config).compileAndLint(banana) assertThat(findings).hasSize(1) } @Test - fun `should report violation in KDoc`() { - val code = """ - /** - * TODO: I need to fix this. - */ - class A { - /** - * TODO: I need to fix this. - */ - } - """ - val findings = ForbiddenComment().compileAndLint(code) - assertThat(findings).hasSize(2) + fun `should report Banana usages regardless of case sensitive`() { + val forbiddenComment = ForbiddenComment(TestConfig(mapOf(VALUES to "bAnAnA"))) + val findings = forbiddenComment.compileAndLint(banana) + assertThat(findings).hasSize(1) } } @Nested - inner class `custom default values are configured` { - val banana = "// Banana." - - @Nested - inner class `when given Banana` { - val config = TestConfig(mapOf(VALUES to "Banana")) - - @Test - @DisplayName("should not report TODO: usages") - fun todoColon() { - val findings = ForbiddenComment(config).compileAndLint(todoColon) - assertThat(findings).isEmpty() - } - - @Test - @DisplayName("should not report FIXME: usages") - fun fixmeColon() { - val findings = ForbiddenComment(config).compileAndLint(fixmeColon) - assertThat(findings).isEmpty() - } + @DisplayName("when given listOf(\"banana\")") + inner class ListOfBanana { + val config = TestConfig(mapOf(VALUES to listOf("Banana"))) - @Test - @DisplayName("should not report STOPME: usages") - fun stopShipColon() { - val findings = ForbiddenComment(config).compileAndLint(stopShipColon) - assertThat(findings).isEmpty() - } - - @Test - fun `should report Banana usages`() { - val findings = ForbiddenComment(config).compileAndLint(banana) - assertThat(findings).hasSize(1) - } - - @Test - fun `should report Banana usages regardless of case sensitive`() { - val forbiddenComment = ForbiddenComment(TestConfig(mapOf(VALUES to "bAnAnA"))) - val findings = forbiddenComment.compileAndLint(banana) - assertThat(findings).hasSize(1) - } + @Test + @DisplayName("should not report TODO: usages") + fun todoColon() { + val findings = ForbiddenComment(config).compileAndLint(todoColon) + assertThat(findings).isEmpty() } - @Nested - @DisplayName("when given listOf(\"banana\")") - inner class ListOfBanana { - val config = TestConfig(mapOf(VALUES to listOf("Banana"))) - - @Test - @DisplayName("should not report TODO: usages") - fun todoColon() { - val findings = ForbiddenComment(config).compileAndLint(todoColon) - assertThat(findings).isEmpty() - } - - @Test - @DisplayName("should not report FIXME: usages") - fun fixmeColon() { - val findings = ForbiddenComment(config).compileAndLint(fixmeColon) - assertThat(findings).isEmpty() - } - - @Test - @DisplayName("should not report STOPME: usages") - fun stopShipColon() { - val findings = ForbiddenComment(config).compileAndLint(stopShipColon) - assertThat(findings).isEmpty() - } - - @Test - fun `should report Banana usages`() { - val findings = ForbiddenComment(config).compileAndLint(banana) - assertThat(findings).hasSize(1) - } - - @Test - fun `should report Banana usages regardless of case sensitive`() { - val forbiddenComment = ForbiddenComment(TestConfig(mapOf(VALUES to "bAnAnA"))) - val findings = forbiddenComment.compileAndLint(banana) - assertThat(findings).hasSize(1) - } + @Test + @DisplayName("should not report FIXME: usages") + fun fixmeColon() { + val findings = ForbiddenComment(config).compileAndLint(fixmeColon) + assertThat(findings).isEmpty() } - } - - @Nested - inner class `custom default values with allowed patterns are configured` { - - val patternsConfig = - TestConfig( - mapOf( - VALUES to "Comment", - ALLOWED_PATTERNS to "Ticket|Task" - ) - ) @Test - fun `should report Comment usages when regex does not match`() { - val comment = "// Comment is added here." - val findings = ForbiddenComment(patternsConfig).compileAndLint(comment) - assertThat(findings).hasSize(1) + @DisplayName("should not report STOPME: usages") + fun stopShipColon() { + val findings = ForbiddenComment(config).compileAndLint(stopShipColon) + assertThat(findings).isEmpty() } @Test - fun `should not report Comment usages when any one pattern is present`() { - val comment = "// Comment Ticket:234." - val findings = ForbiddenComment(patternsConfig).compileAndLint(comment) - assertThat(findings).isEmpty() + fun `should report Banana usages`() { + val findings = ForbiddenComment(config).compileAndLint(banana) + assertThat(findings).hasSize(1) } @Test - fun `should not report Comment usages when all patterns are present`() { - val comment = "// Comment Ticket:123 Task:456 comment." - val findings = ForbiddenComment(patternsConfig).compileAndLint(comment) - assertThat(findings).isEmpty() + fun `should report Banana usages regardless of case sensitive`() { + val forbiddenComment = ForbiddenComment(TestConfig(mapOf(VALUES to "bAnAnA"))) + val findings = forbiddenComment.compileAndLint(banana) + assertThat(findings).hasSize(1) } } + } - @Nested - inner class `custom message is configured` { - val messageConfig = - TestConfig( - mapOf( - VALUES to "Comment", - MESSAGE to "Custom Message" - ) + @Nested + inner class `custom default values with allowed patterns are configured` { + + val patternsConfig = + TestConfig( + mapOf( + VALUES to "Comment", + ALLOWED_PATTERNS to "Ticket|Task" ) + ) - @Test - fun `should report a Finding with message 'Custom Message'`() { - val comment = "// Comment" - val findings = ForbiddenComment(messageConfig).compileAndLint(comment) - assertThat(findings).hasSize(1) - assertThat(findings.first().message).isEqualTo("Custom Message") - } + @Test + fun `should report Comment usages when regex does not match`() { + val comment = "// Comment is added here." + val findings = ForbiddenComment(patternsConfig).compileAndLint(comment) + assertThat(findings).hasSize(1) } - @Nested - inner class `custom message is not configured` { - val messageConfig = - TestConfig( - mapOf( - VALUES to "Comment" - ) + @Test + fun `should not report Comment usages when any one pattern is present`() { + val comment = "// Comment Ticket:234." + val findings = ForbiddenComment(patternsConfig).compileAndLint(comment) + assertThat(findings).isEmpty() + } + + @Test + fun `should not report Comment usages when all patterns are present`() { + val comment = "// Comment Ticket:123 Task:456 comment." + val findings = ForbiddenComment(patternsConfig).compileAndLint(comment) + assertThat(findings).isEmpty() + } + } + + @Nested + inner class `custom message is configured` { + val messageConfig = + TestConfig( + mapOf( + VALUES to "Comment", + MESSAGE to "Custom Message" ) + ) + + @Test + fun `should report a Finding with message 'Custom Message'`() { + val comment = "// Comment" + val findings = ForbiddenComment(messageConfig).compileAndLint(comment) + assertThat(findings).hasSize(1) + assertThat(findings.first().message).isEqualTo("Custom Message") + } + } - @Test - fun `should report a Finding with default Message`() { - val comment = "// Comment" - val findings = ForbiddenComment(messageConfig).compileAndLint(comment) - val expectedMessage = String.format(ForbiddenComment.DEFAULT_ERROR_MESSAGE, "Comment") - assertThat(findings).hasSize(1) - assertThat(findings.first().message).isEqualTo(expectedMessage) - } + @Nested + inner class `custom message is not configured` { + val messageConfig = + TestConfig( + mapOf( + VALUES to "Comment" + ) + ) + + @Test + fun `should report a Finding with default Message`() { + val comment = "// Comment" + val findings = ForbiddenComment(messageConfig).compileAndLint(comment) + val expectedMessage = String.format(ForbiddenComment.DEFAULT_ERROR_MESSAGE, "Comment") + assertThat(findings).hasSize(1) + assertThat(findings.first().message).isEqualTo(expectedMessage) } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenImportSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenImportSpec.kt index 59e48431c76..4e89ca8ef30 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenImportSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenImportSpec.kt @@ -4,117 +4,113 @@ import io.gitlab.arturbosch.detekt.test.TestConfig import io.gitlab.arturbosch.detekt.test.lint import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test private const val IMPORTS = "imports" private const val FORBIDDEN_PATTERNS = "forbiddenPatterns" class ForbiddenImportSpec { - @Nested - inner class `ForbiddenImport rule` { - val code = """ - package foo - - import kotlin.jvm.JvmField - import kotlin.SinceKotlin - - import com.example.R.string - import net.example.R.dimen - import net.example.R.dimension - """ - - @Test - fun `should report nothing by default`() { - val findings = ForbiddenImport().lint(code) - assertThat(findings).isEmpty() - } - - @Test - fun `should report nothing when imports are blank`() { - val findings = ForbiddenImport(TestConfig(mapOf(IMPORTS to " "))).lint(code) - assertThat(findings).isEmpty() - } - - @Test - fun `should report nothing when imports do not match`() { - val findings = ForbiddenImport(TestConfig(mapOf(IMPORTS to "org.*"))).lint(code) - assertThat(findings).isEmpty() - } - - @Test - @DisplayName("should report kotlin.* when imports are kotlin.*") - fun reportKotlinWildcardImports() { - val findings = ForbiddenImport(TestConfig(mapOf(IMPORTS to "kotlin.*"))).lint(code) - assertThat(findings).hasSize(2) - } - - @Test - @DisplayName("should report kotlin.SinceKotlin when specified via fully qualified name") - fun reportKotlinSinceKotlinWhenFqdnSpecified() { - val findings = - ForbiddenImport(TestConfig(mapOf(IMPORTS to "kotlin.SinceKotlin"))).lint(code) - assertThat(findings).hasSize(1) - } - - @Test - @DisplayName("should report kotlin.SinceKotlin and kotlin.jvm.JvmField when specified via fully qualified names") - fun reportMultipleConfiguredImportsCommaSeparated() { - val findings = - ForbiddenImport(TestConfig(mapOf(IMPORTS to "kotlin.SinceKotlin,kotlin.jvm.JvmField"))).lint( - code - ) - assertThat(findings).hasSize(2) - } - - @Test - @DisplayName("should report kotlin.SinceKotlin and kotlin.jvm.JvmField when specified via fully qualified names list") - fun reportMultipleConfiguredImportsInList() { - val findings = - ForbiddenImport( - TestConfig( - mapOf( - IMPORTS to listOf("kotlin.SinceKotlin", "kotlin.jvm.JvmField") - ) + val code = """ + package foo + + import kotlin.jvm.JvmField + import kotlin.SinceKotlin + + import com.example.R.string + import net.example.R.dimen + import net.example.R.dimension + """ + + @Test + fun `should report nothing by default`() { + val findings = ForbiddenImport().lint(code) + assertThat(findings).isEmpty() + } + + @Test + fun `should report nothing when imports are blank`() { + val findings = ForbiddenImport(TestConfig(mapOf(IMPORTS to " "))).lint(code) + assertThat(findings).isEmpty() + } + + @Test + fun `should report nothing when imports do not match`() { + val findings = ForbiddenImport(TestConfig(mapOf(IMPORTS to "org.*"))).lint(code) + assertThat(findings).isEmpty() + } + + @Test + @DisplayName("should report kotlin.* when imports are kotlin.*") + fun reportKotlinWildcardImports() { + val findings = ForbiddenImport(TestConfig(mapOf(IMPORTS to "kotlin.*"))).lint(code) + assertThat(findings).hasSize(2) + } + + @Test + @DisplayName("should report kotlin.SinceKotlin when specified via fully qualified name") + fun reportKotlinSinceKotlinWhenFqdnSpecified() { + val findings = + ForbiddenImport(TestConfig(mapOf(IMPORTS to "kotlin.SinceKotlin"))).lint(code) + assertThat(findings).hasSize(1) + } + + @Test + @DisplayName("should report kotlin.SinceKotlin and kotlin.jvm.JvmField when specified via fully qualified names") + fun reportMultipleConfiguredImportsCommaSeparated() { + val findings = + ForbiddenImport(TestConfig(mapOf(IMPORTS to "kotlin.SinceKotlin,kotlin.jvm.JvmField"))).lint( + code + ) + assertThat(findings).hasSize(2) + } + + @Test + @DisplayName("should report kotlin.SinceKotlin and kotlin.jvm.JvmField when specified via fully qualified names list") + fun reportMultipleConfiguredImportsInList() { + val findings = + ForbiddenImport( + TestConfig( + mapOf( + IMPORTS to listOf("kotlin.SinceKotlin", "kotlin.jvm.JvmField") ) - ).lint(code) - assertThat(findings).hasSize(2) - } - - @Test - @DisplayName("should report kotlin.SinceKotlin when specified via kotlin.Since*") - fun reportsKotlinSinceKotlinWhenSpecifiedWithWildcard() { - val findings = ForbiddenImport(TestConfig(mapOf(IMPORTS to "kotlin.Since*"))).lint(code) - assertThat(findings).hasSize(1) - } - - @Test - @DisplayName("should report all of com.example.R.string, net.example.R.dimen, and net.example.R.dimension") - fun preAndPostWildcard() { - val findings = ForbiddenImport(TestConfig(mapOf(IMPORTS to "*.R.*"))).lint(code) - assertThat(findings).hasSize(3) - } - - @Test - @DisplayName("should report net.example.R.dimen but not net.example.R.dimension") - fun doNotReportSubstringOfFqdn() { - val findings = - ForbiddenImport(TestConfig(mapOf(IMPORTS to "net.example.R.dimen"))).lint(code) - assertThat(findings).hasSize(1) - } - - @Test - fun `should not report import when it does not match any pattern`() { - val findings = - ForbiddenImport(TestConfig(mapOf(FORBIDDEN_PATTERNS to "nets.*R"))).lint(code) - assertThat(findings).isEmpty() - } - - @Test - fun `should report import when it matches the forbidden pattern`() { - val findings = - ForbiddenImport(TestConfig(mapOf(FORBIDDEN_PATTERNS to "net.*R|com.*expiremental"))).lint(code) - assertThat(findings).hasSize(2) - } + ) + ).lint(code) + assertThat(findings).hasSize(2) + } + + @Test + @DisplayName("should report kotlin.SinceKotlin when specified via kotlin.Since*") + fun reportsKotlinSinceKotlinWhenSpecifiedWithWildcard() { + val findings = ForbiddenImport(TestConfig(mapOf(IMPORTS to "kotlin.Since*"))).lint(code) + assertThat(findings).hasSize(1) + } + + @Test + @DisplayName("should report all of com.example.R.string, net.example.R.dimen, and net.example.R.dimension") + fun preAndPostWildcard() { + val findings = ForbiddenImport(TestConfig(mapOf(IMPORTS to "*.R.*"))).lint(code) + assertThat(findings).hasSize(3) + } + + @Test + @DisplayName("should report net.example.R.dimen but not net.example.R.dimension") + fun doNotReportSubstringOfFqdn() { + val findings = + ForbiddenImport(TestConfig(mapOf(IMPORTS to "net.example.R.dimen"))).lint(code) + assertThat(findings).hasSize(1) + } + + @Test + fun `should not report import when it does not match any pattern`() { + val findings = + ForbiddenImport(TestConfig(mapOf(FORBIDDEN_PATTERNS to "nets.*R"))).lint(code) + assertThat(findings).isEmpty() + } + + @Test + fun `should report import when it matches the forbidden pattern`() { + val findings = + ForbiddenImport(TestConfig(mapOf(FORBIDDEN_PATTERNS to "net.*R|com.*expiremental"))).lint(code) + assertThat(findings).hasSize(2) } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenMethodCallSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenMethodCallSpec.kt index 3820c5902aa..0edded78698 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenMethodCallSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenMethodCallSpec.kt @@ -14,436 +14,432 @@ private const val METHODS = "methods" @KotlinCoreEnvironmentTest class ForbiddenMethodCallSpec(val env: KotlinCoreEnvironment) { - @Nested - inner class `ForbiddenMethodCall rule` { + @Test + fun `should report kotlin print usages by default`() { + val code = """ + fun main() { + print("3") + println("4") + } + """ + val findings = ForbiddenMethodCall(TestConfig()).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(2) + assertThat(findings).hasSourceLocations( + SourceLocation(2, 5), + SourceLocation(3, 5) + ) + } - @Test - fun `should report kotlin print usages by default`() { - val code = """ - fun main() { - print("3") - println("4") - } - """ - val findings = ForbiddenMethodCall(TestConfig()).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(2) - assertThat(findings).hasSourceLocations( - SourceLocation(2, 5), - SourceLocation(3, 5) + @Test + fun `should report nothing when methods are blank`() { + val code = """ + import java.lang.System + fun main() { + System.out.println("hello") + } + """ + val findings = + ForbiddenMethodCall(TestConfig(mapOf(METHODS to " "))).compileAndLintWithContext( + env, + code ) + assertThat(findings).isEmpty() + } + + @Test + fun `should report nothing when methods do not match`() { + val code = """ + import java.lang.System + fun main() { + System.out.println("hello") + } + """ + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to listOf("java.lang.System.gc"))) + ).compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } + + @Test + fun `should report method call when using the fully qualified name`() { + val code = """ + fun main() { + java.lang.System.out.println("hello") } + """ + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to listOf("java.io.PrintStream.println"))) + ).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings).hasTextLocations(38 to 54) + } - @Test - fun `should report nothing when methods are blank`() { - val code = """ - import java.lang.System - fun main() { - System.out.println("hello") - } - """ - val findings = - ForbiddenMethodCall(TestConfig(mapOf(METHODS to " "))).compileAndLintWithContext( - env, - code + @Test + fun `should report method call when not using the fully qualified name`() { + val code = """ + import java.lang.System.out + fun main() { + out.println("hello") + } + """ + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to listOf("java.io.PrintStream.println"))) + ).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings).hasTextLocations(49 to 65) + } + + @Test + fun `should report multiple different methods`() { + val code = """ + import java.lang.System + fun main() { + System.out.println("hello") + System.gc() + } + """ + val findings = ForbiddenMethodCall( + TestConfig( + mapOf( + METHODS to listOf( + "java.io.PrintStream.println", + "java.lang.System.gc" + ) ) - assertThat(findings).isEmpty() + ) + ).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(2) + assertThat(findings).hasTextLocations(48 to 64, 76 to 80) + } + + @Test + fun `should report multiple different methods config with sting`() { + val code = """ + import java.lang.System + fun main() { + System.out.println("hello") + System.gc() } + """ + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to "java.io.PrintStream.println, java.lang.System.gc")) + ).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(2) + assertThat(findings).hasTextLocations(48 to 64, 76 to 80) + } - @Test - fun `should report nothing when methods do not match`() { - val code = """ - import java.lang.System + @Test + fun `should report equals operator`() { + val code = """ fun main() { - System.out.println("hello") + java.math.BigDecimal(5.5) == java.math.BigDecimal(5.5) } - """ - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("java.lang.System.gc"))) - ).compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + """ + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to listOf("java.math.BigDecimal.equals"))) + ).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } - @Test - fun `should report method call when using the fully qualified name`() { - val code = """ - fun main() { - java.lang.System.out.println("hello") + @Test + fun `should report prefix operator`() { + val code = """ + fun test() { + var i = 1 + ++i } - """ - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("java.io.PrintStream.println"))) - ).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings).hasTextLocations(38 to 54) - } + """ + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to listOf("kotlin.Int.inc"))) + ).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } - @Test - fun `should report method call when not using the fully qualified name`() { - val code = """ - import java.lang.System.out - fun main() { - out.println("hello") + @Test + fun `should report postfix operator`() { + val code = """ + fun test() { + var i = 1 + i-- } - """ - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("java.io.PrintStream.println"))) - ).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings).hasTextLocations(49 to 65) - } + """ + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to listOf("kotlin.Int.dec"))) + ).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } - @Test - fun `should report multiple different methods`() { - val code = """ - import java.lang.System - fun main() { - System.out.println("hello") - System.gc() + @Test + fun `should report both methods when using just method name without full signature`() { + val code = """ + import java.time.Clock + import java.time.LocalDate + fun test() { + val clock = Clock.systemUTC() + val date = LocalDate.now() + val date2 = LocalDate.now(clock) } - """ - val findings = ForbiddenMethodCall( - TestConfig( - mapOf( - METHODS to listOf( - "java.io.PrintStream.println", - "java.lang.System.gc" - ) - ) + """ + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to listOf("java.time.LocalDate.now"))) + ).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(2) + } + + @Test + fun `should report parameterless method when full signature matches`() { + val code = """ + import java.time.Clock + import java.time.LocalDate + fun test() { + val clock = Clock.systemUTC() + val date = LocalDate.now() + val date2 = LocalDate.now(clock) + } + """ + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to listOf("java.time.LocalDate.now()"))) + ).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings).hasSourceLocation(5, 26) + } + + @Test + fun `should report method with param when full signature matches`() { + val code = """ + import java.time.Clock + import java.time.LocalDate + fun test() { + val clock = Clock.systemUTC() + val date = LocalDate.now() + val date2 = LocalDate.now(clock) + } + """ + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to listOf("java.time.LocalDate.now(java.time.Clock)"))) + ).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings).hasSourceLocation(6, 27) + } + + @Test + fun `should report method with multiple params when full signature matches`() { + val code = """ + import java.time.LocalDate + fun test() { + val date = LocalDate.of(2020, 1, 1) + } + """ + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to listOf("java.time.LocalDate.of(kotlin.Int, kotlin.Int, kotlin.Int)"))) + ).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings).hasSourceLocation(3, 26) + } + + @Test + fun `should report method with multiple params when full signature matches with additional spacing`() { + val code = """ + import java.time.LocalDate + fun test() { + val date = LocalDate.of(2020, 1, 1) + } + """ + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to listOf("java.time.LocalDate.of(kotlin.Int,kotlin.Int,kotlin.Int)"))) + ).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings).hasSourceLocation(3, 26) + } + + @Test + fun `should report method with multiple params when method has spaces and commas`() { + val code = """ + package io.gitlab.arturbosch.detekt.rules.style + + fun `some, test`() = "String" + + fun test() { + val s = `some, test`() + } + """ + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to listOf("io.gitlab.arturbosch.detekt.rules.style.`some, test`()"))) + ).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings).hasSourceLocation(6, 13) + } + + @Test + fun `should report method with default params`() { + val code = """ + package io.gitlab.arturbosch.detekt.rules.style + + fun defaultParamsMethod(s:String, i:Int = 0) = s + i + + fun test() { + val s = defaultParamsMethod("test") + } + """ + val findings = ForbiddenMethodCall( + TestConfig( + mapOf( + METHODS to + listOf("io.gitlab.arturbosch.detekt.rules.style.defaultParamsMethod(kotlin.String,kotlin.Int)") ) - ).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(2) - assertThat(findings).hasTextLocations(48 to 64, 76 to 80) - } + ) + ).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings).hasSourceLocation(6, 13) + } - @Test - fun `should report multiple different methods config with sting`() { - val code = """ - import java.lang.System - fun main() { - System.out.println("hello") - System.gc() + @Test + fun `should report overriding method calls`() { + val code = """ + package org.example.com + + interface I { + fun f() } - """ - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to "java.io.PrintStream.println, java.lang.System.gc")) - ).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(2) - assertThat(findings).hasTextLocations(48 to 64, 76 to 80) - } + + class C : I { + override fun f() {} + } + + fun foo(i: I, c: C) { + i.f() + c.f() + } + """ + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to listOf("org.example.com.I.f"))) + ).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(2) + } - @Test - fun `should report equals operator`() { - val code = """ - fun main() { - java.math.BigDecimal(5.5) == java.math.BigDecimal(5.5) - } - """ - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("java.math.BigDecimal.equals"))) - ).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + @Test + fun `should report functions with lambda params`() { + val code = """ + package org.example - @Test - fun `should report prefix operator`() { - val code = """ - fun test() { - var i = 1 - ++i - } - """ - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("kotlin.Int.inc"))) - ).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + fun bar(b: (String) -> String) = Unit - @Test - fun `should report postfix operator`() { - val code = """ - fun test() { - var i = 1 - i-- - } - """ - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("kotlin.Int.dec"))) - ).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + fun foo() { + bar { "" } + } + """ + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to listOf("org.example.bar((kotlin.String) -> kotlin.String)"))) + ).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } - @Test - fun `should report both methods when using just method name without full signature`() { - val code = """ - import java.time.Clock - import java.time.LocalDate - fun test() { - val clock = Clock.systemUTC() - val date = LocalDate.now() - val date2 = LocalDate.now(clock) - } - """ - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("java.time.LocalDate.now"))) - ).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(2) - } + @Test + fun `should report extension functions`() { + val code = """ + package org.example - @Test - fun `should report parameterless method when full signature matches`() { - val code = """ - import java.time.Clock - import java.time.LocalDate - fun test() { - val clock = Clock.systemUTC() - val date = LocalDate.now() - val date2 = LocalDate.now(clock) - } - """ - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("java.time.LocalDate.now()"))) - ).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings).hasSourceLocation(5, 26) - } + fun String.bar() = Unit - @Test - fun `should report method with param when full signature matches`() { - val code = """ - import java.time.Clock - import java.time.LocalDate - fun test() { - val clock = Clock.systemUTC() - val date = LocalDate.now() - val date2 = LocalDate.now(clock) - } - """ - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("java.time.LocalDate.now(java.time.Clock)"))) - ).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings).hasSourceLocation(6, 27) - } + fun foo() { + "".bar() + } + """ + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to listOf("org.example.bar(kotlin.String)"))) + ).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } - @Test - fun `should report method with multiple params when full signature matches`() { - val code = """ - import java.time.LocalDate - fun test() { - val date = LocalDate.of(2020, 1, 1) - } - """ - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("java.time.LocalDate.of(kotlin.Int, kotlin.Int, kotlin.Int)"))) - ).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings).hasSourceLocation(3, 26) - } + @Nested + inner class `work with generics` { + val code = """ + package org.example - @Test - fun `should report method with multiple params when full signature matches with additional spacing`() { - val code = """ - import java.time.LocalDate - fun test() { - val date = LocalDate.of(2020, 1, 1) - } - """ - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("java.time.LocalDate.of(kotlin.Int,kotlin.Int,kotlin.Int)"))) - ).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings).hasSourceLocation(3, 26) - } + fun bar(a: T, b: U, c: String) = Unit - @Test - fun `should report method with multiple params when method has spaces and commas`() { - val code = """ - package io.gitlab.arturbosch.detekt.rules.style - - fun `some, test`() = "String" - - fun test() { - val s = `some, test`() - } - """ - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("io.gitlab.arturbosch.detekt.rules.style.`some, test`()"))) - ).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings).hasSourceLocation(6, 13) - } + fun foo() { + bar(1, "", "") + } + """ @Test - fun `should report method with default params`() { - val code = """ - package io.gitlab.arturbosch.detekt.rules.style - - fun defaultParamsMethod(s:String, i:Int = 0) = s + i - - fun test() { - val s = defaultParamsMethod("test") - } - """ + fun `raise the issue`() { val findings = ForbiddenMethodCall( - TestConfig( - mapOf( - METHODS to - listOf("io.gitlab.arturbosch.detekt.rules.style.defaultParamsMethod(kotlin.String,kotlin.Int)") - ) - ) + TestConfig(mapOf(METHODS to listOf("org.example.bar(T, U, kotlin.String)"))) ).compileAndLintWithContext(env, code) assertThat(findings).hasSize(1) - assertThat(findings).hasSourceLocation(6, 13) } @Test - fun `should report overriding method calls`() { - val code = """ - package org.example.com - - interface I { - fun f() - } - - class C : I { - override fun f() {} - } - - fun foo(i: I, c: C) { - i.f() - c.f() - } - """ + fun `It doesn't raise any issue because the generics don't match`() { val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("org.example.com.I.f"))) + TestConfig(mapOf(METHODS to listOf("org.example.bar(U, T, kotlin.String)"))) ).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(2) + assertThat(findings).isEmpty() } + } - @Test - fun `should report functions with lambda params`() { - val code = """ - package org.example + @Nested + inner class `work with generic extensions` { + val code = """ + package org.example - fun bar(b: (String) -> String) = Unit + fun R.bar(a: String) = Unit - fun foo() { - bar { "" } - } - """ + fun foo() { + 1.bar("") + } + """ + + @Test + fun `raise the issue`() { val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("org.example.bar((kotlin.String) -> kotlin.String)"))) + TestConfig(mapOf(METHODS to listOf("org.example.bar(R, kotlin.String)"))) ).compileAndLintWithContext(env, code) assertThat(findings).hasSize(1) } @Test - fun `should report extension functions`() { - val code = """ - package org.example - - fun String.bar() = Unit - - fun foo() { - "".bar() - } - """ + fun `It doesn't raise any issue because the type doesn't match`() { val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("org.example.bar(kotlin.String)"))) + TestConfig(mapOf(METHODS to listOf("org.example.bar(kotlin.Int, kotlin.String)"))) ).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } - - @Nested - inner class `work with generics` { - val code = """ - package org.example - - fun bar(a: T, b: U, c: String) = Unit - - fun foo() { - bar(1, "", "") - } - """ - - @Test - fun `raise the issue`() { - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("org.example.bar(T, U, kotlin.String)"))) - ).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } - - @Test - fun `It doesn't raise any issue because the generics don't match`() { - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("org.example.bar(U, T, kotlin.String)"))) - ).compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() } + } - @Nested - inner class `work with generic extensions` { - val code = """ - package org.example - - fun R.bar(a: String) = Unit + @Nested + inner class `Should distinguish between runCatching - #4448` { + val code = """ + package org.example + class A { fun foo() { - 1.bar("") + kotlin.runCatching {} + runCatching {} } - """ - - @Test - fun `raise the issue`() { - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("org.example.bar(R, kotlin.String)"))) - ).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) } + """ - @Test - fun `It doesn't raise any issue because the type doesn't match`() { - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("org.example.bar(kotlin.Int, kotlin.String)"))) - ).compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + @Test + fun `forbid the one without receiver`() { + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to listOf("kotlin.runCatching(() -> R)"))) + ).compileAndLintWithContext(env, code) + assertThat(findings) + .hasSize(1) + .hasSourceLocation(5, 16) } - @Nested - inner class `Should distinguish between runCatching - #4448` { - val code = """ - package org.example - - class A { - fun foo() { - kotlin.runCatching {} - runCatching {} - } - } - """ - - @Test - fun `forbid the one without receiver`() { - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("kotlin.runCatching(() -> R)"))) - ).compileAndLintWithContext(env, code) - assertThat(findings) - .hasSize(1) - .hasSourceLocation(5, 16) - } - - @Test - fun `forbid the one with receiver`() { - val findings = ForbiddenMethodCall( - TestConfig(mapOf(METHODS to listOf("kotlin.runCatching(T, (T) -> R)"))) - ).compileAndLintWithContext(env, code) - assertThat(findings) - .hasSize(1) - .hasSourceLocation(6, 9) - } + @Test + fun `forbid the one with receiver`() { + val findings = ForbiddenMethodCall( + TestConfig(mapOf(METHODS to listOf("kotlin.runCatching(T, (T) -> R)"))) + ).compileAndLintWithContext(env, code) + assertThat(findings) + .hasSize(1) + .hasSourceLocation(6, 9) } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenPublicDataClassSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenPublicDataClassSpec.kt index f036fd0079c..08a54f92025 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenPublicDataClassSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenPublicDataClassSpec.kt @@ -4,169 +4,165 @@ import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.test.TestConfig import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class ForbiddenPublicDataClassSpec { - @Nested - inner class `ForbiddenPublicDataClass rule` { - val subject = ForbiddenPublicDataClass() - - @Test - fun `public data class should pass without explicit filters set`() { - val code = """ - data class C(val a: String) - """ - - assertThat(ForbiddenPublicDataClass(TestConfig(Config.EXCLUDES_KEY to "**")).compileAndLint(code)).isEmpty() - } - - @Test - fun `public data class should fail`() { - val code = """ - data class C(val a: String) - """ - - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `private data class should pass`() { - val code = """ - private data class C(val a: String) - """ - - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `internal data class should pass`() { - val code = """ - internal data class C(val a: String) - """ - - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `public class should pass`() { - val code = """ - class C(val a: String) - """ - - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `private data class inside a public class should pass`() { - val code = """ - class C { - private data class D(val a: String) - } - """ - - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `public data class inside a public class should fail`() { - val code = """ - class C { - data class D(val a: String) - } - """ - - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `protected data class inside a public class should fail`() { - val code = """ - open class C { - protected data class D(val a: String) - } - """ - - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `public data class inside an internal class should pass`() { - val code = """ - internal class C { - data class D(val a: String) - } - """ - - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `public data class inside an internal package should pass`() { - val code = """ - package com.example.internal - - data class C(val a: String) - """ - - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `public data class inside an internal subpackage should pass`() { - val code = """ - package com.example.internal.other - - data class C(val a: String) - """ - - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `public data class inside an internalise package should fail`() { - val code = """ - package com.example.internalise - - data class C(val a: String) - """ - - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `public data class inside a random package should fail`() { - val code = """ - package com.random - - data class C(val a: String) - """ - - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `public data class inside an ignored package should pass`() { - val code = """ - package com.example - - data class C(val a: String) - """ - - val config = TestConfig("ignorePackages" to listOf("*.hello", "com.example")) - assertThat(ForbiddenPublicDataClass(config).compileAndLint(code)).isEmpty() - } - - @Test - fun `public data class inside an ignored package should pass config as string`() { - val code = """ - package org.example - - data class C(val a: String) - """ - - val config = TestConfig("ignorePackages" to "*.hello,org.example") - assertThat(ForbiddenPublicDataClass(config).compileAndLint(code)).isEmpty() - } + val subject = ForbiddenPublicDataClass() + + @Test + fun `public data class should pass without explicit filters set`() { + val code = """ + data class C(val a: String) + """ + + assertThat(ForbiddenPublicDataClass(TestConfig(Config.EXCLUDES_KEY to "**")).compileAndLint(code)).isEmpty() + } + + @Test + fun `public data class should fail`() { + val code = """ + data class C(val a: String) + """ + + assertThat(subject.compileAndLint(code)).hasSize(1) + } + + @Test + fun `private data class should pass`() { + val code = """ + private data class C(val a: String) + """ + + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `internal data class should pass`() { + val code = """ + internal data class C(val a: String) + """ + + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `public class should pass`() { + val code = """ + class C(val a: String) + """ + + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `private data class inside a public class should pass`() { + val code = """ + class C { + private data class D(val a: String) + } + """ + + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `public data class inside a public class should fail`() { + val code = """ + class C { + data class D(val a: String) + } + """ + + assertThat(subject.compileAndLint(code)).hasSize(1) + } + + @Test + fun `protected data class inside a public class should fail`() { + val code = """ + open class C { + protected data class D(val a: String) + } + """ + + assertThat(subject.compileAndLint(code)).hasSize(1) + } + + @Test + fun `public data class inside an internal class should pass`() { + val code = """ + internal class C { + data class D(val a: String) + } + """ + + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `public data class inside an internal package should pass`() { + val code = """ + package com.example.internal + + data class C(val a: String) + """ + + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `public data class inside an internal subpackage should pass`() { + val code = """ + package com.example.internal.other + + data class C(val a: String) + """ + + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `public data class inside an internalise package should fail`() { + val code = """ + package com.example.internalise + + data class C(val a: String) + """ + + assertThat(subject.compileAndLint(code)).hasSize(1) + } + + @Test + fun `public data class inside a random package should fail`() { + val code = """ + package com.random + + data class C(val a: String) + """ + + assertThat(subject.compileAndLint(code)).hasSize(1) + } + + @Test + fun `public data class inside an ignored package should pass`() { + val code = """ + package com.example + + data class C(val a: String) + """ + + val config = TestConfig("ignorePackages" to listOf("*.hello", "com.example")) + assertThat(ForbiddenPublicDataClass(config).compileAndLint(code)).isEmpty() + } + + @Test + fun `public data class inside an ignored package should pass config as string`() { + val code = """ + package org.example + + data class C(val a: String) + """ + + val config = TestConfig("ignorePackages" to "*.hello,org.example") + assertThat(ForbiddenPublicDataClass(config).compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenVoidSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenVoidSpec.kt index 5e5e11bdd08..096cd1e0acd 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenVoidSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenVoidSpec.kt @@ -17,189 +17,186 @@ private const val IGNORE_USAGE_IN_GENERICS = "ignoreUsageInGenerics" class ForbiddenVoidSpec(val env: KotlinCoreEnvironment) { val subject = ForbiddenVoid(Config.empty) + @Test + fun `should report all Void type usage`() { + val code = """ + lateinit var c: () -> Void + + fun method(param: Void) { + val a: Void? = null + val b: Void = null!! + } + """ + + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(4) + } + + @Test + fun `should not report Void class literal`() { + val code = """ + val clazz = java.lang.Void::class + val klass = Void::class + """ + + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report when functions or classes are called 'Void'`() { + val code = """ + class Void { + fun void() {} + val void = "string" + } + enum class E { + Void; + } + abstract class Test { + fun myFun2(): E = E.Void + abstract fun myFun(): Void + } + """ + + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + @Nested - inner class `ForbiddenVoid rule` { + inner class `ignoreOverridden is enabled` { + + val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to "true")) + @Test - fun `should report all Void type usage`() { + fun `should not report Void in overriding function declarations`() { val code = """ - lateinit var c: () -> Void + abstract class A { + @Suppress("ForbiddenVoid") + abstract fun method(param: Void) : Void + } - fun method(param: Void) { - val a: Void? = null - val b: Void = null!! + class B : A() { + override fun method(param: Void) : Void { + throw IllegalStateException() + } } """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(4) + val findings = ForbiddenVoid(config).compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() } @Test - fun `should not report Void class literal`() { + fun `should not report Void in overriding function declarations with parameterized types`() { val code = """ - val clazz = java.lang.Void::class - val klass = Void::class + class Foo {} + + abstract class A { + @Suppress("ForbiddenVoid") + abstract fun method(param: Foo) : Foo + } + + class B : A() { + override fun method(param: Foo) : Foo { + throw IllegalStateException() + } + } """ - assertThat(subject.compileAndLint(code)).isEmpty() + val findings = ForbiddenVoid(config).compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() } @Test - fun `does not report when functions or classes are called 'Void'`() { + fun `should report Void in body of overriding function even`() { val code = """ - class Void { - fun void() {} - val void = "string" - } - enum class E { - Void; + abstract class A { + abstract fun method(param: String) } - abstract class Test { - fun myFun2(): E = E.Void - abstract fun myFun(): Void + + class B : A() { + override fun method(param: String) { + val a: Void? = null + } } """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + val findings = ForbiddenVoid(config).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) } - @Nested - inner class `ignoreOverridden is enabled` { - - val config = TestConfig(mapOf(IGNORE_OVERRIDDEN to "true")) - - @Test - fun `should not report Void in overriding function declarations`() { - val code = """ - abstract class A { - @Suppress("ForbiddenVoid") - abstract fun method(param: Void) : Void - } - - class B : A() { - override fun method(param: Void) : Void { - throw IllegalStateException() - } - } - """ - - val findings = ForbiddenVoid(config).compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } - - @Test - fun `should not report Void in overriding function declarations with parameterized types`() { - val code = """ - class Foo {} - - abstract class A { - @Suppress("ForbiddenVoid") - abstract fun method(param: Foo) : Foo - } - - class B : A() { - override fun method(param: Foo) : Foo { - throw IllegalStateException() - } - } - """ - - val findings = ForbiddenVoid(config).compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } - - @Test - fun `should report Void in body of overriding function even`() { - val code = """ - abstract class A { - abstract fun method(param: String) - } - - class B : A() { - override fun method(param: String) { - val a: Void? = null - } - } - """ - - val findings = ForbiddenVoid(config).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } - - @Test - fun `should report Void in not overridden function declarations`() { - val code = """ - fun method(param: Void) : Void { - return param - } - """ + @Test + fun `should report Void in not overridden function declarations`() { + val code = """ + fun method(param: Void) : Void { + return param + } + """ - val findings = ForbiddenVoid(config).compileAndLintWithContext(env, code) - assertThat(findings).hasSize(2) - } + val findings = ForbiddenVoid(config).compileAndLintWithContext(env, code) + assertThat(findings).hasSize(2) } + } - @Nested - inner class `ignoreUsageInGenerics is enabled` { + @Nested + inner class `ignoreUsageInGenerics is enabled` { - val config = TestConfig(mapOf(IGNORE_USAGE_IN_GENERICS to "true")) + val config = TestConfig(mapOf(IGNORE_USAGE_IN_GENERICS to "true")) - @Test - fun `should not report Void in generic type declaration`() { - val code = """ - interface A + @Test + fun `should not report Void in generic type declaration`() { + val code = """ + interface A - class B { - fun method(): A? = null - } + class B { + fun method(): A? = null + } - class C(private val b: B) { - fun method() { - val a: A? = b.method() - } + class C(private val b: B) { + fun method() { + val a: A? = b.method() } + } - class D : A - """ + class D : A + """ - val findings = ForbiddenVoid(config).compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + val findings = ForbiddenVoid(config).compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `should not report Void in nested generic type definition`() { - val code = """ - interface A - interface B - class C : A> - """ + @Test + fun `should not report Void in nested generic type definition`() { + val code = """ + interface A + interface B + class C : A> + """ - val findings = ForbiddenVoid(config).compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + val findings = ForbiddenVoid(config).compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `should not report Void in definition with multiple generic parameters`() { - val code = """ - val foo = mutableMapOf() - """ + @Test + fun `should not report Void in definition with multiple generic parameters`() { + val code = """ + val foo = mutableMapOf() + """ - val findings = ForbiddenVoid(config).compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + val findings = ForbiddenVoid(config).compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `should report non-generic Void type usage`() { - val code = """ - lateinit var c: () -> Void + @Test + fun `should report non-generic Void type usage`() { + val code = """ + lateinit var c: () -> Void - fun method(param: Void) { - val a: Void? = null - val b: Void = null!! - } - """ + fun method(param: Void) { + val a: Void? = null + val b: Void = null!! + } + """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(4) - } + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(4) } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/LibraryCodeMustSpecifyReturnTypeSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/LibraryCodeMustSpecifyReturnTypeSpec.kt index cc816662431..44267b2056e 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/LibraryCodeMustSpecifyReturnTypeSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/LibraryCodeMustSpecifyReturnTypeSpec.kt @@ -13,203 +13,199 @@ import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class LibraryCodeMustSpecifyReturnTypeSpec(val env: KotlinCoreEnvironment) { + @Test + fun `should not report without explicit filters set`() { + val subject = LibraryCodeMustSpecifyReturnType(TestConfig(Config.EXCLUDES_KEY to "**")) + assertThat( + subject.compileAndLintWithContext( + env, + """ + fun foo() = 5 + val bar = 5 + class A { + fun b() = 2 + val c = 2 + } + """ + ) + ).isEmpty() + } + @Nested - inner class `library code must have explicit return types` { + inner class `positive cases` { + val subject = LibraryCodeMustSpecifyReturnType() @Test - fun `should not report without explicit filters set`() { - val subject = LibraryCodeMustSpecifyReturnType(TestConfig(Config.EXCLUDES_KEY to "**")) + fun `should report a top level function`() { assertThat( subject.compileAndLintWithContext( env, """ fun foo() = 5 - val bar = 5 - class A { - fun b() = 2 - val c = 2 - } """ ) - ).isEmpty() + ).hasSize(1) } - @Nested - inner class `positive cases` { - val subject = LibraryCodeMustSpecifyReturnType() - - @Test - fun `should report a top level function`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - fun foo() = 5 - """ - ) - ).hasSize(1) - } + @Test + fun `should report a top level property`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + val foo = 5 + """ + ) + ).hasSize(1) + } - @Test - fun `should report a top level property`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ + @Test + fun `should report a public class with public members`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + class A { val foo = 5 - """ - ) - ).hasSize(1) - } + fun bar() = 5 + } + """ + ) + ).hasSize(2) + } - @Test - fun `should report a public class with public members`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - class A { - val foo = 5 - fun bar() = 5 - } - """ - ) - ).hasSize(2) - } + @Test + fun `should report a public class with protected members`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + open class A { + protected val foo = 5 + protected fun bar() = 5 + } + """ + ) + ).hasSize(2) + } + } - @Test - fun `should report a public class with protected members`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - open class A { - protected val foo = 5 - protected fun bar() = 5 - } - """ - ) - ).hasSize(2) - } + @Nested + inner class `negative cases with public scope` { + val subject = LibraryCodeMustSpecifyReturnType() + + @Test + fun `should not report a top level function`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + fun foo(): Int = 5 + """ + ) + ).isEmpty() } - @Nested - inner class `negative cases with public scope` { - val subject = LibraryCodeMustSpecifyReturnType() - - @Test - fun `should not report a top level function`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - fun foo(): Int = 5 - """ - ) - ).isEmpty() - } + @Test + fun `should not report a non expression function`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + fun foo() {} + """ + ) + ).isEmpty() + } - @Test - fun `should not report a non expression function`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - fun foo() {} - """ - ) - ).isEmpty() - } + @Test + fun `should not report a top level property`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + val foo: Int = 5 + """ + ) + ).isEmpty() + } - @Test - fun `should not report a top level property`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ + @Test + fun `should not report a public class with public members`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + class A { val foo: Int = 5 - """ - ) - ).isEmpty() - } + fun bar(): Int = 5 + } + """ + ) + ).isEmpty() + } + } - @Test - fun `should not report a public class with public members`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - class A { - val foo: Int = 5 - fun bar(): Int = 5 - } - """ - ) - ).isEmpty() - } + @Nested + inner class `negative cases with no public scope` { + val subject = LibraryCodeMustSpecifyReturnType() + + @Test + fun `should not report a private top level function`() { + assertThat( + subject.lintWithContext( + env, + """ + internal fun bar() = 5 + private fun foo() = 5 + """ + ) + ).isEmpty() } - @Nested - inner class `negative cases with no public scope` { - val subject = LibraryCodeMustSpecifyReturnType() - - @Test - fun `should not report a private top level function`() { - assertThat( - subject.lintWithContext( - env, - """ - internal fun bar() = 5 - private fun foo() = 5 - """ - ) - ).isEmpty() - } + @Test + fun `should not report a internal top level property`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + internal val foo = 5 + """ + ) + ).isEmpty() + } - @Test - fun `should not report a internal top level property`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ + @Test + fun `should not report members and local variables`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + internal class A { internal val foo = 5 - """ - ) - ).isEmpty() - } - - @Test - fun `should not report members and local variables`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - internal class A { - internal val foo = 5 - private fun bar() { - fun stuff() = Unit - val a = 5 - } + private fun bar() { + fun stuff() = Unit + val a = 5 } - """ - ) - ).isEmpty() - } + } + """ + ) + ).isEmpty() + } - @Test - fun `should not report effectively private properties and functions`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - internal class A { - fun baz() = 5 - val qux = 5 - } - """ - ) - ).isEmpty() - } + @Test + fun `should not report effectively private properties and functions`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + internal class A { + fun baz() = 5 + val qux = 5 + } + """ + ) + ).isEmpty() } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/LibraryEntitiesShouldNotBePublicSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/LibraryEntitiesShouldNotBePublicSpec.kt index 0e1662b7cc4..0d2860f7171 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/LibraryEntitiesShouldNotBePublicSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/LibraryEntitiesShouldNotBePublicSpec.kt @@ -9,125 +9,122 @@ import org.junit.jupiter.api.Test class LibraryEntitiesShouldNotBePublicSpec { + @Test + fun `should not report without explicit filters set`() { + val subject = LibraryEntitiesShouldNotBePublic(TestConfig(Config.EXCLUDES_KEY to "**")) + assertThat( + subject.compileAndLint( + """ + class A + """ + ) + ).isEmpty() + } + @Nested - inner class `Library class cannot be public` { + inner class `positive cases` { + val subject = LibraryEntitiesShouldNotBePublic() + @Test - fun `should not report without explicit filters set`() { - val subject = LibraryEntitiesShouldNotBePublic(TestConfig(Config.EXCLUDES_KEY to "**")) + fun `should report a class`() { assertThat( subject.compileAndLint( """ - class A + class A """ ) - ).isEmpty() + ).hasSize(1) } - @Nested - inner class `positive cases` { - val subject = LibraryEntitiesShouldNotBePublic() - - @Test - fun `should report a class`() { - assertThat( - subject.compileAndLint( - """ - class A - """ - ) - ).hasSize(1) - } - - @Test - fun `should report a class with function`() { - assertThat( - subject.compileAndLint( - """ - class A { - fun foo(): Int{ - return 1 - } + @Test + fun `should report a class with function`() { + assertThat( + subject.compileAndLint( + """ + class A { + fun foo(): Int{ + return 1 } - """ - ) - ).hasSize(1) - } + } + """ + ) + ).hasSize(1) + } - @Test - fun `should report a typealias`() { - assertThat( - subject.compileAndLint( - """ - typealias A = List - """ - ) - ).hasSize(1) - } + @Test + fun `should report a typealias`() { + assertThat( + subject.compileAndLint( + """ + typealias A = List + """ + ) + ).hasSize(1) + } - @Test - fun `should report a typealias and a function`() { - assertThat( - subject.compileAndLint( - """ - typealias A = List - fun foo() = Unit - """ - ) - ).hasSize(2) - } + @Test + fun `should report a typealias and a function`() { + assertThat( + subject.compileAndLint( + """ + typealias A = List + fun foo() = Unit + """ + ) + ).hasSize(2) + } - @Test - fun `should report a function`() { - assertThat( - subject.compileAndLint( - """ - fun foo() = Unit - """ - ) - ).hasSize(1) - } + @Test + fun `should report a function`() { + assertThat( + subject.compileAndLint( + """ + fun foo() = Unit + """ + ) + ).hasSize(1) } + } - @Nested - inner class `negative cases` { - val subject = LibraryEntitiesShouldNotBePublic() + @Nested + inner class `negative cases` { + val subject = LibraryEntitiesShouldNotBePublic() - @Test - fun `should not report a class`() { - assertThat( - subject.compileAndLint( - """ - internal class A { - fun foo(): Int{ - return 1 - } + @Test + fun `should not report a class`() { + assertThat( + subject.compileAndLint( + """ + internal class A { + fun foo(): Int{ + return 1 } - """ - ) - ).isEmpty() - } + } + """ + ) + ).isEmpty() + } - @Test - fun `should not report a class with function`() { - assertThat( - subject.compileAndLint( - """ - internal class A - """ - ) - ).isEmpty() - } + @Test + fun `should not report a class with function`() { + assertThat( + subject.compileAndLint( + """ + internal class A + """ + ) + ).isEmpty() + } - @Test - fun `should not report a typealias`() { - assertThat( - subject.compileAndLint( - """ - internal typealias A = List - """ - ) - ).isEmpty() - } + @Test + fun `should not report a typealias`() { + assertThat( + subject.compileAndLint( + """ + internal typealias A = List + """ + ) + ).isEmpty() } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/LoopWithTooManyJumpStatementsSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/LoopWithTooManyJumpStatementsSpec.kt index ecfb1f69899..904458b119c 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/LoopWithTooManyJumpStatementsSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/LoopWithTooManyJumpStatementsSpec.kt @@ -4,35 +4,29 @@ import io.gitlab.arturbosch.detekt.rules.Case import io.gitlab.arturbosch.detekt.test.TestConfig import io.gitlab.arturbosch.detekt.test.lint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test private const val MAX_JUMP_COUNT = "maxJumpCount" class LoopWithTooManyJumpStatementsSpec { val subject = LoopWithTooManyJumpStatements() + val path = Case.LoopWithTooManyJumpStatementsPositive.path() - @Nested - inner class `LoopWithTooManyJumpStatements rule` { - - val path = Case.LoopWithTooManyJumpStatementsPositive.path() - - @Test - fun `reports loops with more than 1 break or continue statement`() { - assertThat(subject.lint(path)).hasSize(3) - } + @Test + fun `reports loops with more than 1 break or continue statement`() { + assertThat(subject.lint(path)).hasSize(3) + } - @Test - fun `does not report when max count configuration is set to 2`() { - val config = TestConfig(mapOf(MAX_JUMP_COUNT to "2")) - val findings = LoopWithTooManyJumpStatements(config).lint(path) - assertThat(findings).isEmpty() - } + @Test + fun `does not report when max count configuration is set to 2`() { + val config = TestConfig(mapOf(MAX_JUMP_COUNT to "2")) + val findings = LoopWithTooManyJumpStatements(config).lint(path) + assertThat(findings).isEmpty() + } - @Test - fun `does not report loop with less than 1 break or continue statement`() { - val findings = subject.lint(Case.LoopWithTooManyJumpStatementsNegative.path()) - assertThat(findings).isEmpty() - } + @Test + fun `does not report loop with less than 1 break or continue statement`() { + val findings = subject.lint(Case.LoopWithTooManyJumpStatementsNegative.path()) + assertThat(findings).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MagicNumberSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MagicNumberSpec.kt index de6f338a665..3075bed107d 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MagicNumberSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MagicNumberSpec.kt @@ -27,1002 +27,999 @@ private const val IGNORE_EXTENSION_FUNCTIONS = "ignoreExtensionFunctions" class MagicNumberSpec { @Nested - inner class `Magic Number rule` { + inner class `a float of 1` { + val code = "val myFloat = 1.0f" - @Nested - inner class `a float of 1` { - val code = "val myFloat = 1.0f" - - @Test - fun `should not be reported by default`() { - val findings = MagicNumber().lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported by default`() { + val findings = MagicNumber().lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should be reported when ignoredNumbers is empty`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) - assertThat(findings).hasSourceLocation(1, 15) - } + @Test + fun `should be reported when ignoredNumbers is empty`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) + assertThat(findings).hasSourceLocation(1, 15) } + } - @Nested - inner class `a const float of 1` { - val code = "const val MY_FLOAT = 1.0f" + @Nested + inner class `a const float of 1` { + val code = "const val MY_FLOAT = 1.0f" - @Test - fun `should not be reported by default`() { - val findings = MagicNumber().lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported by default`() { + val findings = MagicNumber().lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should not be reported when ignoredNumbers is empty`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported when ignoredNumbers is empty`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `an integer of 1` { - val code = "val myInt = 1" + @Nested + inner class `an integer of 1` { + val code = "val myInt = 1" - @Test - fun `should not be reported by default`() { - val findings = MagicNumber().lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported by default`() { + val findings = MagicNumber().lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should be reported when ignoredNumbers is empty`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) - assertThat(findings).hasSourceLocation(1, 13) - } + @Test + fun `should be reported when ignoredNumbers is empty`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) + assertThat(findings).hasSourceLocation(1, 13) } + } - @Nested - inner class `a const integer of 1` { - val code = "const val MY_INT = 1" + @Nested + inner class `a const integer of 1` { + val code = "const val MY_INT = 1" - @Test - fun `should not be reported by default`() { - val findings = MagicNumber().lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported by default`() { + val findings = MagicNumber().lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should not be reported when ignoredNumbers is empty`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported when ignoredNumbers is empty`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `a long of 1` { - val code = "val myLong = 1L" + @Nested + inner class `a long of 1` { + val code = "val myLong = 1L" - @Test - fun `should not be reported by default`() { - val findings = MagicNumber().lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported by default`() { + val findings = MagicNumber().lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should be reported when ignoredNumbers is empty`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) - assertThat(findings).hasSourceLocation(1, 14) - } + @Test + fun `should be reported when ignoredNumbers is empty`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) + assertThat(findings).hasSourceLocation(1, 14) } + } - @Nested - inner class `a long of -1` { - val code = "val myLong = -1L" + @Nested + inner class `a long of -1` { + val code = "val myLong = -1L" - @Test - fun `should not be reported by default`() { - val findings = MagicNumber().lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported by default`() { + val findings = MagicNumber().lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should be reported when ignoredNumbers is empty`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) - assertThat(findings).hasSourceLocation(1, 15) - } + @Test + fun `should be reported when ignoredNumbers is empty`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) + assertThat(findings).hasSourceLocation(1, 15) } + } - @Nested - inner class `a long of -2` { - val code = "val myLong = -2L" + @Nested + inner class `a long of -2` { + val code = "val myLong = -2L" - @Test - fun `should be reported by default`() { - val findings = MagicNumber().lint(code) - assertThat(findings).hasSourceLocation(1, 15) - } + @Test + fun `should be reported by default`() { + val findings = MagicNumber().lint(code) + assertThat(findings).hasSourceLocation(1, 15) + } - @Test - fun `should be ignored when ignoredNumbers contains it verbatim`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("-2L")))).lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should be ignored when ignoredNumbers contains it verbatim`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("-2L")))).lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should be ignored when ignoredNumbers contains it as floating point`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("-2f")))).lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should be ignored when ignoredNumbers contains it as floating point`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("-2f")))).lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should not be ignored when ignoredNumbers contains 2 but not -2`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("1", "2", "3", "-1", "0")))) - .lint(code) - assertThat(findings).hasSourceLocation(1, 15) - } + @Test + fun `should not be ignored when ignoredNumbers contains 2 but not -2`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("1", "2", "3", "-1", "0")))) + .lint(code) + assertThat(findings).hasSourceLocation(1, 15) + } - @Test - fun `should not be ignored when ignoredNumbers contains 2 but not -2 config with string`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to "1,2,3,-1,0"))) - .lint(code) - assertThat(findings).hasSourceLocation(1, 15) - } + @Test + fun `should not be ignored when ignoredNumbers contains 2 but not -2 config with string`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to "1,2,3,-1,0"))) + .lint(code) + assertThat(findings).hasSourceLocation(1, 15) } + } - @Nested - inner class `a const long of 1` { - val code = "const val MY_LONG = 1L" + @Nested + inner class `a const long of 1` { + val code = "const val MY_LONG = 1L" - @Test - fun `should not be reported by default`() { - val findings = MagicNumber().lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported by default`() { + val findings = MagicNumber().lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should not be reported when ignoredNumbers is empty`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported when ignoredNumbers is empty`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `a double of 1` { - val code = "val myDouble = 1.0" + @Nested + inner class `a double of 1` { + val code = "val myDouble = 1.0" - @Test - fun `should not be reported by default`() { - val findings = MagicNumber().lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported by default`() { + val findings = MagicNumber().lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should be reported when ignoredNumbers is empty`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) - assertThat(findings).hasSourceLocation(1, 16) - } + @Test + fun `should be reported when ignoredNumbers is empty`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) + assertThat(findings).hasSourceLocation(1, 16) } + } - @Nested - inner class `a const double of 1` { - val code = "const val MY_DOUBLE = 1.0" + @Nested + inner class `a const double of 1` { + val code = "const val MY_DOUBLE = 1.0" - @Test - fun `should not be reported by default`() { - val findings = MagicNumber().lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported by default`() { + val findings = MagicNumber().lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should not be reported when ignoredNumbers is empty`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported when ignoredNumbers is empty`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `a hex of 1` { - val code = "val myHex = 0x1" + @Nested + inner class `a hex of 1` { + val code = "val myHex = 0x1" - @Test - fun `should not be reported by default`() { - val findings = MagicNumber().lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported by default`() { + val findings = MagicNumber().lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should be reported when ignoredNumbers is empty`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) - assertThat(findings).hasSourceLocation(1, 13) - } + @Test + fun `should be reported when ignoredNumbers is empty`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) + assertThat(findings).hasSourceLocation(1, 13) } + } - @Nested - inner class `a const hex of 1` { - val code = "const val MY_HEX = 0x1" + @Nested + inner class `a const hex of 1` { + val code = "const val MY_HEX = 0x1" - @Test - fun `should not be reported by default`() { - val findings = MagicNumber().lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported by default`() { + val findings = MagicNumber().lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should not be reported when ignoredNumbers is empty`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported when ignoredNumbers is empty`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))).lint(code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `an integer of 300` { - val code = "val myInt = 300" + @Nested + inner class `an integer of 300` { + val code = "val myInt = 300" - @Test - fun `should not be reported when ignoredNumbers contains 300`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("300")))).lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported when ignoredNumbers contains 300`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("300")))).lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should not be reported when ignoredNumbers contains a floating point 300`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("300.0")))).lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported when ignoredNumbers contains a floating point 300`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("300.0")))).lint(code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `a binary literal` { - val code = "val myBinary = 0b01001" + @Nested + inner class `a binary literal` { + val code = "val myBinary = 0b01001" - @Test - fun `should not be reported`() { - val findings = MagicNumber().lint(code) - assertThat(findings).hasSize(1) - } + @Test + fun `should not be reported`() { + val findings = MagicNumber().lint(code) + assertThat(findings).hasSize(1) + } - @Test - fun `should not be reported when ignoredNumbers contains a binary literal 0b01001`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("0b01001")))).lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported when ignoredNumbers contains a binary literal 0b01001`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("0b01001")))).lint(code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `an integer literal with underscores` { - val code = "val myInt = 100_000" + @Nested + inner class `an integer literal with underscores` { + val code = "val myInt = 100_000" - @Test - fun `should be reported by default`() { - val findings = MagicNumber().lint(code) - assertThat(findings).hasSourceLocation(1, 13) - } + @Test + fun `should be reported by default`() { + val findings = MagicNumber().lint(code) + assertThat(findings).hasSourceLocation(1, 13) + } - @Test - fun `should not be reported when ignored verbatim`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("100_000")))).lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported when ignored verbatim`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("100_000")))).lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should not be reported when ignored with different underscores`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("10_00_00")))).lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported when ignored with different underscores`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("10_00_00")))).lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should not be reported when ignored without underscores`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("100000")))).lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported when ignored without underscores`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("100000")))).lint(code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `an if statement with magic numbers` { - val code = "val myInt = if (5 < 6) 7 else 8" + @Nested + inner class `an if statement with magic numbers` { + val code = "val myInt = if (5 < 6) 7 else 8" + + @Test + fun `should be reported`() { + val findings = MagicNumber().lint(code) + assertThat(findings) + .hasSourceLocations( + SourceLocation(1, 17), + SourceLocation(1, 21), + SourceLocation(1, 24), + SourceLocation(1, 31) + ) + } + } - @Test - fun `should be reported`() { - val findings = MagicNumber().lint(code) - assertThat(findings) - .hasSourceLocations( - SourceLocation(1, 17), - SourceLocation(1, 21), - SourceLocation(1, 24), - SourceLocation(1, 31) - ) + @Nested + inner class `a when statement with magic numbers` { + val code = """ + fun test(x: Int) { + when (x) { + 5 -> return 5 + 4 -> return 4 + 3 -> return 3 } } + """ + + @Test + fun `should be reported`() { + val findings = MagicNumber().lint(code) + assertThat(findings).hasSourceLocations( + SourceLocation(3, 9), + SourceLocation(3, 21), + SourceLocation(4, 9), + SourceLocation(4, 21), + SourceLocation(5, 9), + SourceLocation(5, 21) + ) + } + } - @Nested - inner class `a when statement with magic numbers` { - val code = """ - fun test(x: Int) { - when (x) { - 5 -> return 5 - 4 -> return 4 - 3 -> return 3 - } - } - """ + @Nested + inner class `a method containing variables with magic numbers` { + val code = """ + fun test(x: Int) { + val i = 5 + } + """ - @Test - fun `should be reported`() { - val findings = MagicNumber().lint(code) - assertThat(findings).hasSourceLocations( - SourceLocation(3, 9), - SourceLocation(3, 21), - SourceLocation(4, 9), - SourceLocation(4, 21), - SourceLocation(5, 9), - SourceLocation(5, 21) - ) - } + @Test + fun `should be reported`() { + val findings = MagicNumber().lint(code) + assertThat(findings).hasSize(1) } + } - @Nested - inner class `a method containing variables with magic numbers` { - val code = """ - fun test(x: Int) { - val i = 5 - } - """ + @Nested + inner class `a boolean value` { + val code = """ + fun test() : Boolean { + return true; + } + """ - @Test - fun `should be reported`() { - val findings = MagicNumber().lint(code) - assertThat(findings).hasSize(1) - } + @Test + fun `should not be reported`() { + val findings = MagicNumber().lint(code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `a boolean value` { - val code = """ - fun test() : Boolean { - return true; - } - """ + @Nested + inner class `a non-numeric constant expression` { + val code = "val surprise = true" - @Test - fun `should not be reported`() { - val findings = MagicNumber().lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not be reported`() { + val findings = MagicNumber().lint(code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `a non-numeric constant expression` { - val code = "val surprise = true" - - @Test - fun `should not be reported`() { - val findings = MagicNumber().lint(code) - assertThat(findings).isEmpty() - } + @Nested + @DisplayName("a float of 0.5") + inner class Float { + val code = "val test = 0.5f" + + @Test + fun `should be reported by default`() { + val findings = MagicNumber().lint(code) + assertThat(findings).hasSourceLocation(1, 12) } - @Nested - @DisplayName("a float of 0.5") - inner class Float { - val code = "val test = 0.5f" + @Test + fun `should not be reported when ignoredNumbers contains it`() { + val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf(".5")))).lint(code) + assertThat(findings).isEmpty() + } + } - @Test - fun `should be reported by default`() { - val findings = MagicNumber().lint(code) - assertThat(findings).hasSourceLocation(1, 12) - } + @Nested + inner class `a magic number number in a constructor call` { - @Test - fun `should not be reported when ignoredNumbers contains it`() { - val findings = MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf(".5")))).lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should report`() { + val code = "val file = Array(42) { null }" + val findings = MagicNumber().compileAndLint(code) + assertThat(findings).hasSize(1) } + } - @Nested - inner class `a magic number number in a constructor call` { + @Nested + inner class `an invalid ignoredNumber` { - @Test - fun `should report`() { - val code = "val file = Array(42) { null }" - val findings = MagicNumber().compileAndLint(code) - assertThat(findings).hasSize(1) + @Test + fun `throws a NumberFormatException`() { + assertThatExceptionOfType(NumberFormatException::class.java).isThrownBy { + MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("banana")))).compileAndLint("val i = 0") } } + } - @Nested - inner class `an invalid ignoredNumber` { + @Nested + inner class `an empty ignoredNumber` { - @Test - fun `throws a NumberFormatException`() { - assertThatExceptionOfType(NumberFormatException::class.java).isThrownBy { - MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to listOf("banana")))).compileAndLint("val i = 0") - } - } + @Test + fun `doesn't throw an exception`() { + MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))) } + } - @Nested - inner class `an empty ignoredNumber` { + @Nested + inner class `ignoring properties` { + val code = """ + @Magic(number = 69) + class A { + val boringNumber = 42 + const val BORING_CONSTANT = 93871 + val duration = Duration.seconds(10) + val durationWithStdlibFunction = 10.toDuration(DurationUnit.MILLISECONDS) - @Test - fun `doesn't throw an exception`() { - MagicNumber(TestConfig(mapOf(IGNORE_NUMBERS to emptyList()))) + override fun hashCode(): Int { + val iAmSoMagic = 7328672 } - } - @Nested - inner class `ignoring properties` { - val code = """ - @Magic(number = 69) - class A { - val boringNumber = 42 - const val BORING_CONSTANT = 93871 - val duration = Duration.seconds(10) - val durationWithStdlibFunction = 10.toDuration(DurationUnit.MILLISECONDS) - - override fun hashCode(): Int { - val iAmSoMagic = 7328672 - } - - companion object { - val anotherBoringNumber = 43 - const val anotherBoringConstant = 93872 - val color = Color(0x66000000) - val colorWithExplicitParameter = Color(color = 0x66000000) - } + companion object { + val anotherBoringNumber = 43 + const val anotherBoringConstant = 93872 + val color = Color(0x66000000) + val colorWithExplicitParameter = Color(color = 0x66000000) } + } - data class Color(val color: Int) - """ - - @Test - fun `should report all without ignore flags`() { - val config = TestConfig( - mapOf( - IGNORE_PROPERTY_DECLARATION to "false", - IGNORE_ANNOTATION to "false", - IGNORE_NAMED_ARGUMENT to "false", - IGNORE_HASH_CODE to "false", - IGNORE_CONSTANT_DECLARATION to "false", - IGNORE_COMPANION_OBJECT_PROPERTY_DECLARATION to "false" - ) + data class Color(val color: Int) + """ + + @Test + fun `should report all without ignore flags`() { + val config = TestConfig( + mapOf( + IGNORE_PROPERTY_DECLARATION to "false", + IGNORE_ANNOTATION to "false", + IGNORE_NAMED_ARGUMENT to "false", + IGNORE_HASH_CODE to "false", + IGNORE_CONSTANT_DECLARATION to "false", + IGNORE_COMPANION_OBJECT_PROPERTY_DECLARATION to "false" ) + ) - val findings = MagicNumber(config).lint(code) - assertThat(findings) - .hasSourceLocations( - SourceLocation(1, 17), - SourceLocation(3, 24), - SourceLocation(4, 33), - SourceLocation(5, 37), - SourceLocation(9, 26), - SourceLocation(13, 35), - SourceLocation(14, 43), - SourceLocation(15, 27), - SourceLocation(16, 56) - ) - } + val findings = MagicNumber(config).lint(code) + assertThat(findings) + .hasSourceLocations( + SourceLocation(1, 17), + SourceLocation(3, 24), + SourceLocation(4, 33), + SourceLocation(5, 37), + SourceLocation(9, 26), + SourceLocation(13, 35), + SourceLocation(14, 43), + SourceLocation(15, 27), + SourceLocation(16, 56) + ) + } - @Test - fun `should not report any issues with all ignore flags`() { - val config = TestConfig( - mapOf( - IGNORE_PROPERTY_DECLARATION to "true", - IGNORE_ANNOTATION to "true", - IGNORE_HASH_CODE to "true", - IGNORE_CONSTANT_DECLARATION to "true", - IGNORE_COMPANION_OBJECT_PROPERTY_DECLARATION to "true" - ) + @Test + fun `should not report any issues with all ignore flags`() { + val config = TestConfig( + mapOf( + IGNORE_PROPERTY_DECLARATION to "true", + IGNORE_ANNOTATION to "true", + IGNORE_HASH_CODE to "true", + IGNORE_CONSTANT_DECLARATION to "true", + IGNORE_COMPANION_OBJECT_PROPERTY_DECLARATION to "true" ) + ) - val findings = MagicNumber(config).lint(code) - assertThat(findings).isEmpty() - } + val findings = MagicNumber(config).lint(code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `magic numbers in companion object property assignments` { - val code = """ - class A { + @Nested + inner class `magic numbers in companion object property assignments` { + val code = """ + class A { - companion object { - val anotherBoringNumber = 43 - const val anotherBoringConstant = 93872 - } + companion object { + val anotherBoringNumber = 43 + const val anotherBoringConstant = 93872 } - """ + } + """ - @Test - fun `should not report any issues by default`() { - val findings = MagicNumber().lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not report any issues by default`() { + val findings = MagicNumber().lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should not report any issues when ignoring properties but not constants nor companion objects`() { - val config = TestConfig( - mapOf( - IGNORE_PROPERTY_DECLARATION to "true", - IGNORE_CONSTANT_DECLARATION to "false", - IGNORE_COMPANION_OBJECT_PROPERTY_DECLARATION to "false" - ) + @Test + fun `should not report any issues when ignoring properties but not constants nor companion objects`() { + val config = TestConfig( + mapOf( + IGNORE_PROPERTY_DECLARATION to "true", + IGNORE_CONSTANT_DECLARATION to "false", + IGNORE_COMPANION_OBJECT_PROPERTY_DECLARATION to "false" ) + ) - val findings = MagicNumber(config).lint(code) - assertThat(findings).isEmpty() - } + val findings = MagicNumber(config).lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should not report any issues when ignoring properties and constants but not companion objects`() { - val config = TestConfig( - mapOf( - IGNORE_PROPERTY_DECLARATION to "true", - IGNORE_CONSTANT_DECLARATION to "true", - IGNORE_COMPANION_OBJECT_PROPERTY_DECLARATION to "false" - ) + @Test + fun `should not report any issues when ignoring properties and constants but not companion objects`() { + val config = TestConfig( + mapOf( + IGNORE_PROPERTY_DECLARATION to "true", + IGNORE_CONSTANT_DECLARATION to "true", + IGNORE_COMPANION_OBJECT_PROPERTY_DECLARATION to "false" ) + ) - val findings = MagicNumber(config).lint(code) - assertThat(findings).isEmpty() - } + val findings = MagicNumber(config).lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should not report any issues when ignoring properties, constants and companion objects`() { - val config = TestConfig( - mapOf( - IGNORE_PROPERTY_DECLARATION to "true", - IGNORE_CONSTANT_DECLARATION to "true", - IGNORE_COMPANION_OBJECT_PROPERTY_DECLARATION to "true" - ) + @Test + fun `should not report any issues when ignoring properties, constants and companion objects`() { + val config = TestConfig( + mapOf( + IGNORE_PROPERTY_DECLARATION to "true", + IGNORE_CONSTANT_DECLARATION to "true", + IGNORE_COMPANION_OBJECT_PROPERTY_DECLARATION to "true" ) + ) - val findings = MagicNumber(config).lint(code) - assertThat(findings).isEmpty() - } + val findings = MagicNumber(config).lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should not report any issues when ignoring companion objects but not properties and constants`() { - val config = TestConfig( - mapOf( - IGNORE_PROPERTY_DECLARATION to "false", - IGNORE_CONSTANT_DECLARATION to "false", - IGNORE_COMPANION_OBJECT_PROPERTY_DECLARATION to "true" - ) + @Test + fun `should not report any issues when ignoring companion objects but not properties and constants`() { + val config = TestConfig( + mapOf( + IGNORE_PROPERTY_DECLARATION to "false", + IGNORE_CONSTANT_DECLARATION to "false", + IGNORE_COMPANION_OBJECT_PROPERTY_DECLARATION to "true" ) + ) - val findings = MagicNumber(config).lint(code) - assertThat(findings).isEmpty() - } + val findings = MagicNumber(config).lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should report property when ignoring constants but not properties and companion objects`() { - val config = TestConfig( - mapOf( - IGNORE_PROPERTY_DECLARATION to "false", - IGNORE_CONSTANT_DECLARATION to "true", - IGNORE_COMPANION_OBJECT_PROPERTY_DECLARATION to "false" - ) + @Test + fun `should report property when ignoring constants but not properties and companion objects`() { + val config = TestConfig( + mapOf( + IGNORE_PROPERTY_DECLARATION to "false", + IGNORE_CONSTANT_DECLARATION to "true", + IGNORE_COMPANION_OBJECT_PROPERTY_DECLARATION to "false" ) + ) - val findings = MagicNumber(config).lint(code) - assertThat(findings).hasSourceLocation(4, 35) - } + val findings = MagicNumber(config).lint(code) + assertThat(findings).hasSourceLocation(4, 35) + } - @Test - fun `should report property and constant when not ignoring properties, constants nor companion objects`() { - val config = TestConfig( - mapOf( - IGNORE_PROPERTY_DECLARATION to "false", - IGNORE_CONSTANT_DECLARATION to "false", - IGNORE_COMPANION_OBJECT_PROPERTY_DECLARATION to "false" - ) + @Test + fun `should report property and constant when not ignoring properties, constants nor companion objects`() { + val config = TestConfig( + mapOf( + IGNORE_PROPERTY_DECLARATION to "false", + IGNORE_CONSTANT_DECLARATION to "false", + IGNORE_COMPANION_OBJECT_PROPERTY_DECLARATION to "false" ) + ) - val findings = MagicNumber(config).lint(code) - assertThat(findings) - .hasSourceLocations( - SourceLocation(4, 35), - SourceLocation(5, 43) - ) - } + val findings = MagicNumber(config).lint(code) + assertThat(findings) + .hasSourceLocations( + SourceLocation(4, 35), + SourceLocation(5, 43) + ) } + } - @Nested - inner class `a property without number` { - val code = "private var pair: Pair? = null" + @Nested + inner class `a property without number` { + val code = "private var pair: Pair? = null" - @Test - fun `should not lead to a crash #276`() { - val findings = MagicNumber().lint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not lead to a crash #276`() { + val findings = MagicNumber().lint(code) + assertThat(findings).isEmpty() } + } + @Nested + inner class `ignoring named arguments` { @Nested - inner class `ignoring named arguments` { - @Nested - inner class `in constructor invocation` { - fun code(numberString: String) = """ - data class Model( - val someVal: Int, - val other: String = "default" - ) + inner class `in constructor invocation` { + private fun code(numberString: String) = """ + data class Model( + val someVal: Int, + val other: String = "default" + ) - var model = Model(someVal = $numberString) - """ + var model = Model(someVal = $numberString) + """ - @Test - fun `should not ignore int`() { - val rule = MagicNumber(TestConfig(mapOf(IGNORE_NAMED_ARGUMENT to "false"))) - assertThat(rule.lint(code("53"))).hasSize(1) - } - - @Test - fun `should not ignore float`() { - val rule = MagicNumber(TestConfig(mapOf(IGNORE_NAMED_ARGUMENT to "false"))) - assertThat(rule.lint(code("53f"))).hasSize(1) - } - - @Test - fun `should not ignore binary`() { - val rule = MagicNumber(TestConfig(mapOf(IGNORE_NAMED_ARGUMENT to "false"))) - assertThat(rule.lint(code("0b01001"))).hasSize(1) - } - - @Test - fun `should ignore integer with underscores`() { - val rule = MagicNumber(TestConfig(mapOf(IGNORE_NAMED_ARGUMENT to "false"))) - assertThat(rule.lint(code("101_000"))).hasSize(1) - } - - @Test - fun `should ignore numbers by default`() { - assertThat(MagicNumber().lint(code("53"))).isEmpty() - } - - @Test - fun `should ignore negative numbers by default`() { - assertThat(MagicNumber().lint(code("-53"))).isEmpty() - } - - @Test - fun `should ignore named arguments in inheritance - #992`() { - val code = """ - abstract class A(n: Int) - - object B : A(n = 5) - """ - assertThat(MagicNumber().compileAndLint(code)).isEmpty() - } - - @Test - fun `should ignore named arguments in parameter annotations - #1115`() { - val code = - "@JvmStatic fun setCustomDimension(@IntRange(from = 0, to = 19) index: Int, value: String?) {}" - assertThat(MagicNumber().lint(code)).isEmpty() - } + @Test + fun `should not ignore int`() { + val rule = MagicNumber(TestConfig(mapOf(IGNORE_NAMED_ARGUMENT to "false"))) + assertThat(rule.lint(code("53"))).hasSize(1) } - @Nested - inner class `Issue#659 - false-negative reporting on unnamed argument when ignore is true` { - - fun code(numberString: String) = """ - data class Model( - val someVal: Int, - val other: String = "default" - ) - - var model = Model($numberString) - """ - - @Test - fun `should detect the argument by default`() { - assertThat(MagicNumber().lint(code("53"))).hasSize(1) - } + @Test + fun `should not ignore float`() { + val rule = MagicNumber(TestConfig(mapOf(IGNORE_NAMED_ARGUMENT to "false"))) + assertThat(rule.lint(code("53f"))).hasSize(1) } - @Nested - inner class `in function invocation` { - fun code(number: Number) = """ - fun tested(someVal: Int, other: String = "default") - - val t = tested(someVal = $number) - """ - - @Test - fun `should ignore int by default`() { - assertThat(MagicNumber().lint(code(53))).isEmpty() - } - - @Test - fun `should ignore float by default`() { - assertThat(MagicNumber().lint(code(53f))).isEmpty() - } - - @Test - fun `should ignore binary by default`() { - assertThat(MagicNumber().lint(code(0b01001))).isEmpty() - } - - @Test - fun `should ignore integer with underscores`() { - assertThat(MagicNumber().lint(code(101_000))).isEmpty() - } + @Test + fun `should not ignore binary`() { + val rule = MagicNumber(TestConfig(mapOf(IGNORE_NAMED_ARGUMENT to "false"))) + assertThat(rule.lint(code("0b01001"))).hasSize(1) } - @Nested - inner class `in enum constructor argument` { - val code = """ - enum class Bag(id: Int) { - SMALL(1), - EXTRA_LARGE(5) - } - """ - - @Test - fun `should be reported by default`() { - assertThat(MagicNumber().lint(code)).hasSize(1) - } - - @Test - fun `numbers when 'ignoreEnums' is set to true`() { - val rule = MagicNumber(TestConfig(mapOf(IGNORE_ENUMS to "true"))) - assertThat(rule.lint(code)).isEmpty() - } + @Test + fun `should ignore integer with underscores`() { + val rule = MagicNumber(TestConfig(mapOf(IGNORE_NAMED_ARGUMENT to "false"))) + assertThat(rule.lint(code("101_000"))).hasSize(1) } - @Nested - inner class `in enum constructor as named argument` { - val code = """ - enum class Bag(id: Int) { - SMALL(id = 1), - EXTRA_LARGE(id = 5) - } - """ - - @Test - fun `should be reported`() { - val rule = MagicNumber(TestConfig(mapOf(IGNORE_NAMED_ARGUMENT to "false"))) - assertThat(rule.lint(code)).hasSize(1) - } - - @Test - fun `numbers when 'ignoreEnums' is set to true`() { - val rule = MagicNumber( - TestConfig( - mapOf( - IGNORE_NAMED_ARGUMENT to "false", - IGNORE_ENUMS to "true" - ) - ) - ) - assertThat(rule.lint(code)).isEmpty() - } + @Test + fun `should ignore numbers by default`() { + assertThat(MagicNumber().lint(code("53"))).isEmpty() } - } - @Nested - inner class `functions with and without braces which return values` { + @Test + fun `should ignore negative numbers by default`() { + assertThat(MagicNumber().lint(code("-53"))).isEmpty() + } @Test - fun `does not report functions that always returns a constant value`() { + fun `should ignore named arguments in inheritance - #992`() { val code = """ - fun x() = 9 - fun y(): Int { return 9 } + abstract class A(n: Int) + + object B : A(n = 5) """ assertThat(MagicNumber().compileAndLint(code)).isEmpty() } @Test - fun `reports functions that does not return a constant value`() { - val code = """ - fun x() = 9 + 1 - fun y(): Int { return 9 + 1 } - """ - assertThat(MagicNumber().compileAndLint(code)).hasSize(2) + fun `should ignore named arguments in parameter annotations - #1115`() { + val code = + "@JvmStatic fun setCustomDimension(@IntRange(from = 0, to = 19) index: Int, value: String?) {}" + assertThat(MagicNumber().lint(code)).isEmpty() } } @Nested - inner class `in-class declaration with default parameters` { + inner class `Issue#659 - false-negative reporting on unnamed argument when ignore is true` { - @Test - fun `reports no finding`() { - val code = "class SomeClassWithDefault(val defaultValue: Int = 10)" - assertThat(MagicNumber().lint(code)).isEmpty() - } + private fun code(numberString: String) = """ + data class Model( + val someVal: Int, + val other: String = "default" + ) - @Test - fun `reports no finding for an explicit declaration`() { - val code = "class SomeClassWithDefault constructor(val defaultValue: Int = 10)" - assertThat(MagicNumber().lint(code)).isEmpty() - } + var model = Model($numberString) + """ @Test - fun `reports no finding for a function expression`() { - val code = - "class SomeClassWithDefault constructor(val defaultValue: Duration = 10.toDuration(DurationUnit.MILLISECONDS))" - assertThat(MagicNumber().lint(code)).isEmpty() + fun `should detect the argument by default`() { + assertThat(MagicNumber().lint(code("53"))).hasSize(1) } } @Nested - inner class `default parameters in secondary constructor` { + inner class `in function invocation` { + private fun code(number: Number) = """ + fun tested(someVal: Int, other: String = "default") + + val t = tested(someVal = $number) + """ @Test - fun `reports no finding`() { - val code = """ - class SomeClassWithDefault { - constructor(val defaultValue: Int = 10) { } - } - """ - assertThat(MagicNumber().lint(code)).isEmpty() + fun `should ignore int by default`() { + assertThat(MagicNumber().lint(code(53))).isEmpty() } @Test - fun `reports no finding for a function expression`() { - val code = """ - class SomeClassWithDefault { - constructor(val defaultValue: Duration = 10.toDuration(DurationUnit.MILLISECONDS)) { } - } - """ - assertThat(MagicNumber().lint(code)).isEmpty() + fun `should ignore float by default`() { + assertThat(MagicNumber().lint(code(53f))).isEmpty() } - } - - @Nested - inner class `default parameters in function` { @Test - fun `reports no finding`() { - val code = "fun f(p: Int = 100)" - assertThat(MagicNumber().lint(code)).isEmpty() + fun `should ignore binary by default`() { + assertThat(MagicNumber().lint(code(0b01001))).isEmpty() } @Test - fun `reports no finding for a function expression`() { - val code = "fun f(p: Duration = 10.toDuration(DurationUnit.MILLISECONDS))" - assertThat(MagicNumber().lint(code)).isEmpty() + fun `should ignore integer with underscores`() { + assertThat(MagicNumber().lint(code(101_000))).isEmpty() } } @Nested - inner class `a number as part of a range` { - - fun cases() = listOf( - "val range = 1..27", - "val range = (1..27)", - "val range = 27 downTo 1", - "val range = 1 until 27 step 1", - "val inRange = 1 in 1..27", - "val inRange = (1 in 27 downTo 0 step 1)", - "val inRange = (1..27 step 1).last" - ) + inner class `in enum constructor argument` { + val code = """ + enum class Bag(id: Int) { + SMALL(1), + EXTRA_LARGE(5) + } + """ - @ParameterizedTest - @MethodSource("cases") - fun `reports a code smell by default`(code: String) { + @Test + fun `should be reported by default`() { assertThat(MagicNumber().lint(code)).hasSize(1) } - @ParameterizedTest - @MethodSource("cases") - fun `reports a code smell if ranges are not ignored`(code: String) { - assertThat(MagicNumber(TestConfig(mapOf(IGNORE_RANGES to "false"))).lint(code)) - .hasSize(1) + @Test + fun `numbers when 'ignoreEnums' is set to true`() { + val rule = MagicNumber(TestConfig(mapOf(IGNORE_ENUMS to "true"))) + assertThat(rule.lint(code)).isEmpty() } + } - @ParameterizedTest - @MethodSource("cases") - fun `reports no finding if ranges are ignored`(code: String) { - assertThat(MagicNumber(TestConfig(mapOf(IGNORE_RANGES to "true"))).lint(code)) - .isEmpty() + @Nested + inner class `in enum constructor as named argument` { + val code = """ + enum class Bag(id: Int) { + SMALL(id = 1), + EXTRA_LARGE(id = 5) } + """ @Test - fun `reports a finding for a parenthesized number if ranges are ignored`() { - val code = "val foo : Int = (127)" - assertThat(MagicNumber(TestConfig(mapOf(IGNORE_RANGES to "true"))).lint(code)).hasSize(1) + fun `should be reported`() { + val rule = MagicNumber(TestConfig(mapOf(IGNORE_NAMED_ARGUMENT to "false"))) + assertThat(rule.lint(code)).hasSize(1) } @Test - fun `reports a finding for an addition if ranges are ignored`() { - val code = "val foo : Int = 1 + 27" - assertThat(MagicNumber(TestConfig(mapOf(IGNORE_RANGES to "true"))).lint(code)).hasSize(1) + fun `numbers when 'ignoreEnums' is set to true`() { + val rule = MagicNumber( + TestConfig( + mapOf( + IGNORE_NAMED_ARGUMENT to "false", + IGNORE_ENUMS to "true" + ) + ) + ) + assertThat(rule.lint(code)).isEmpty() } } + } - @Nested - inner class `a number assigned to a local variable` { + @Nested + inner class `functions with and without braces which return values` { - val code = """fun f() { val a = 3; }""" + @Test + fun `does not report functions that always returns a constant value`() { + val code = """ + fun x() = 9 + fun y(): Int { return 9 } + """ + assertThat(MagicNumber().compileAndLint(code)).isEmpty() + } - @Test - fun `reports 3 due to the assignment to a local variable`() { - val rule = MagicNumber(TestConfig(mapOf(IGNORE_LOCAL_VARIABLES to "false"))) - assertThat(rule.compileAndLint(code)).hasSize(1) + @Test + fun `reports functions that does not return a constant value`() { + val code = """ + fun x() = 9 + 1 + fun y(): Int { return 9 + 1 } + """ + assertThat(MagicNumber().compileAndLint(code)).hasSize(2) + } + } + + @Nested + inner class `in-class declaration with default parameters` { + + @Test + fun `reports no finding`() { + val code = "class SomeClassWithDefault(val defaultValue: Int = 10)" + assertThat(MagicNumber().lint(code)).isEmpty() + } + + @Test + fun `reports no finding for an explicit declaration`() { + val code = "class SomeClassWithDefault constructor(val defaultValue: Int = 10)" + assertThat(MagicNumber().lint(code)).isEmpty() + } + + @Test + fun `reports no finding for a function expression`() { + val code = + "class SomeClassWithDefault constructor(val defaultValue: Duration = 10.toDuration(DurationUnit.MILLISECONDS))" + assertThat(MagicNumber().lint(code)).isEmpty() + } + } + + @Nested + inner class `default parameters in secondary constructor` { + + @Test + fun `reports no finding`() { + val code = """ + class SomeClassWithDefault { + constructor(val defaultValue: Int = 10) { } } + """ + assertThat(MagicNumber().lint(code)).isEmpty() + } - @Test - fun `should not report 3 due to the ignored local variable config`() { - val rule = MagicNumber(TestConfig(mapOf(IGNORE_LOCAL_VARIABLES to "true"))) - assertThat(rule.compileAndLint(code)).isEmpty() + @Test + fun `reports no finding for a function expression`() { + val code = """ + class SomeClassWithDefault { + constructor(val defaultValue: Duration = 10.toDuration(DurationUnit.MILLISECONDS)) { } } + """ + assertThat(MagicNumber().lint(code)).isEmpty() + } + } + + @Nested + inner class `default parameters in function` { + + @Test + fun `reports no finding`() { + val code = "fun f(p: Int = 100)" + assertThat(MagicNumber().lint(code)).isEmpty() } - @Nested - inner class `meaningful variables - #1536` { + @Test + fun `reports no finding for a function expression`() { + val code = "fun f(p: Duration = 10.toDuration(DurationUnit.MILLISECONDS))" + assertThat(MagicNumber().lint(code)).isEmpty() + } + } - val rule = - MagicNumber( - TestConfig( - mapOf( - IGNORE_LOCAL_VARIABLES to "true", - IGNORE_NAMED_ARGUMENT to "true" - ) + @Nested + inner class `a number as part of a range` { + + @Suppress("UnusedPrivateMember") + private fun cases() = listOf( + "val range = 1..27", + "val range = (1..27)", + "val range = 27 downTo 1", + "val range = 1 until 27 step 1", + "val inRange = 1 in 1..27", + "val inRange = (1 in 27 downTo 0 step 1)", + "val inRange = (1..27 step 1).last" + ) + + @ParameterizedTest + @MethodSource("cases") + fun `reports a code smell by default`(code: String) { + assertThat(MagicNumber().lint(code)).hasSize(1) + } + + @ParameterizedTest + @MethodSource("cases") + fun `reports a code smell if ranges are not ignored`(code: String) { + assertThat(MagicNumber(TestConfig(mapOf(IGNORE_RANGES to "false"))).lint(code)) + .hasSize(1) + } + + @ParameterizedTest + @MethodSource("cases") + fun `reports no finding if ranges are ignored`(code: String) { + assertThat(MagicNumber(TestConfig(mapOf(IGNORE_RANGES to "true"))).lint(code)) + .isEmpty() + } + + @Test + fun `reports a finding for a parenthesized number if ranges are ignored`() { + val code = "val foo : Int = (127)" + assertThat(MagicNumber(TestConfig(mapOf(IGNORE_RANGES to "true"))).lint(code)).hasSize(1) + } + + @Test + fun `reports a finding for an addition if ranges are ignored`() { + val code = "val foo : Int = 1 + 27" + assertThat(MagicNumber(TestConfig(mapOf(IGNORE_RANGES to "true"))).lint(code)).hasSize(1) + } + } + + @Nested + inner class `a number assigned to a local variable` { + + val code = """fun f() { val a = 3; }""" + + @Test + fun `reports 3 due to the assignment to a local variable`() { + val rule = MagicNumber(TestConfig(mapOf(IGNORE_LOCAL_VARIABLES to "false"))) + assertThat(rule.compileAndLint(code)).hasSize(1) + } + + @Test + fun `should not report 3 due to the ignored local variable config`() { + val rule = MagicNumber(TestConfig(mapOf(IGNORE_LOCAL_VARIABLES to "true"))) + assertThat(rule.compileAndLint(code)).isEmpty() + } + } + + @Nested + inner class `meaningful variables - #1536` { + + val rule = + MagicNumber( + TestConfig( + mapOf( + IGNORE_LOCAL_VARIABLES to "true", + IGNORE_NAMED_ARGUMENT to "true" ) ) + ) - @Test - fun `should report 3`() { - assertThat(rule.compileAndLint("""fun bar() { foo(3) }; fun foo(n: Int) {}""")).hasSize(1) - } + @Test + fun `should report 3`() { + assertThat(rule.compileAndLint("""fun bar() { foo(3) }; fun foo(n: Int) {}""")).hasSize(1) + } - @Test - fun `should not report named 3`() { - assertThat(rule.compileAndLint("""fun bar() { foo(param=3) }; fun foo(param: Int) {}""")).isEmpty() - } + @Test + fun `should not report named 3`() { + assertThat(rule.compileAndLint("""fun bar() { foo(param=3) }; fun foo(param: Int) {}""")).isEmpty() + } - @Test - fun `should not report 3 due to scoped describing variable`() { - assertThat(rule.compileAndLint("""fun bar() { val a = 3; foo(a) }; fun foo(n: Int) {}""")).isEmpty() - } + @Test + fun `should not report 3 due to scoped describing variable`() { + assertThat(rule.compileAndLint("""fun bar() { val a = 3; foo(a) }; fun foo(n: Int) {}""")).isEmpty() } + } - @Nested - inner class `with extension function` { + @Nested + inner class `with extension function` { - val rule = - MagicNumber( - TestConfig( - mapOf( - IGNORE_EXTENSION_FUNCTIONS to "true" - ) + val rule = + MagicNumber( + TestConfig( + mapOf( + IGNORE_EXTENSION_FUNCTIONS to "true" ) ) + ) - @Test - fun `should not report when function`() { - val code = """ - fun Int.dp() = this + 1 + @Test + fun `should not report when function`() { + val code = """ + fun Int.dp() = this + 1 - val a = 500.dp() - """ + val a = 500.dp() + """ - assertThat(rule.compileAndLint(code)).isEmpty() - } + assertThat(rule.compileAndLint(code)).isEmpty() + } - @Test - fun `should not report when property`() { - val code = """ - val Int.dp: Int - get() = this + 1 + @Test + fun `should not report when property`() { + val code = """ + val Int.dp: Int + get() = this + 1 - val a = 500.dp - """ + val a = 500.dp + """ - assertThat(rule.compileAndLint(code)).isEmpty() - } + assertThat(rule.compileAndLint(code)).isEmpty() + } - @Test - fun `should report the argument`() { - val code = """ - fun Int.dp(a: Int) = this + a + @Test + fun `should report the argument`() { + val code = """ + fun Int.dp(a: Int) = this + a - val a = 500.dp(400) - """ + val a = 500.dp(400) + """ - assertThat(rule.compileAndLint(code)).hasSize(1) - } + assertThat(rule.compileAndLint(code)).hasSize(1) } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MaxLineLengthSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MaxLineLengthSpec.kt index aa310f8959f..fb2abb65d99 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MaxLineLengthSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MaxLineLengthSpec.kt @@ -18,251 +18,247 @@ private const val EXCLUDE_COMMENT_STATEMENTS = "excludeCommentStatements" class MaxLineLengthSpec { @Nested - inner class `MaxLineLength rule` { + inner class `a kt file with some long lines` { - @Nested - inner class `a kt file with some long lines` { + val file = compileForTest(Case.MaxLineLength.path()) + val lines = file.text.splitToSequence("\n") + val fileContent = KtFileContent(file, lines) - val file = compileForTest(Case.MaxLineLength.path()) - val lines = file.text.splitToSequence("\n") - val fileContent = KtFileContent(file, lines) + @Test + fun `should report no errors when maxLineLength is set to 200`() { + val rule = MaxLineLength(TestConfig(mapOf(MAX_LINE_LENGTH to "200"))) - @Test - fun `should report no errors when maxLineLength is set to 200`() { - val rule = MaxLineLength(TestConfig(mapOf(MAX_LINE_LENGTH to "200"))) - - rule.visit(fileContent) - assertThat(rule.findings).isEmpty() - } + rule.visit(fileContent) + assertThat(rule.findings).isEmpty() + } - @Test - fun `should report all errors with default maxLineLength`() { - val rule = MaxLineLength() + @Test + fun `should report all errors with default maxLineLength`() { + val rule = MaxLineLength() - rule.visit(fileContent) - assertThat(rule.findings).hasSize(7) - } + rule.visit(fileContent) + assertThat(rule.findings).hasSize(7) + } - @Test - fun `should report meaningful signature for all violations`() { - val rule = MaxLineLength() + @Test + fun `should report meaningful signature for all violations`() { + val rule = MaxLineLength() - rule.visit(fileContent) - val locations = rule.findings.map { it.signature.substringAfterLast('$') } - doAssert(locations).allSatisfy { doAssert(it).isNotBlank() } - } + rule.visit(fileContent) + val locations = rule.findings.map { it.signature.substringAfterLast('$') } + doAssert(locations).allSatisfy { doAssert(it).isNotBlank() } } + } - @Nested - inner class `a kt file with long but suppressed lines` { + @Nested + inner class `a kt file with long but suppressed lines` { - val file = compileForTest(Case.MaxLineLengthSuppressed.path()) - val lines = file.text.splitToSequence("\n") - val fileContent = KtFileContent(file, lines) + val file = compileForTest(Case.MaxLineLengthSuppressed.path()) + val lines = file.text.splitToSequence("\n") + val fileContent = KtFileContent(file, lines) - @Test - fun `should not report as lines are suppressed`() { - val rule = MaxLineLength() + @Test + fun `should not report as lines are suppressed`() { + val rule = MaxLineLength() - rule.visit(fileContent) - assertThat(rule.findings).isEmpty() - } + rule.visit(fileContent) + assertThat(rule.findings).isEmpty() } + } - @Nested - inner class `a kt file with a long package name and long import statements` { - val code = """ - package anIncrediblyLongAndComplexPackageNameThatProbablyShouldBeMuchShorterButForTheSakeOfTheTestItsNot - - import anIncrediblyLongAndComplexImportNameThatProbablyShouldBeMuchShorterButForTheSakeOfTheTestItsNot - - class Test { - } - """ + @Nested + inner class `a kt file with a long package name and long import statements` { + val code = """ + package anIncrediblyLongAndComplexPackageNameThatProbablyShouldBeMuchShorterButForTheSakeOfTheTestItsNot - val file = compileContentForTest(code) - val lines = file.text.splitToSequence("\n") - val fileContent = KtFileContent(file, lines) + import anIncrediblyLongAndComplexImportNameThatProbablyShouldBeMuchShorterButForTheSakeOfTheTestItsNot - @Test - fun `should not report the package statement and import statements by default`() { - val rule = MaxLineLength( - TestConfig( - mapOf( - MAX_LINE_LENGTH to "60" - ) + class Test { + } + """ + + val file = compileContentForTest(code) + val lines = file.text.splitToSequence("\n") + val fileContent = KtFileContent(file, lines) + + @Test + fun `should not report the package statement and import statements by default`() { + val rule = MaxLineLength( + TestConfig( + mapOf( + MAX_LINE_LENGTH to "60" ) ) + ) - rule.visit(fileContent) - assertThat(rule.findings).isEmpty() - } - - @Test - fun `should report the package statement and import statements if they're enabled`() { - val rule = MaxLineLength( - TestConfig( - mapOf( - MAX_LINE_LENGTH to "60", - EXCLUDE_PACKAGE_STATEMENTS to "false", - EXCLUDE_IMPORT_STATEMENTS to "false" - ) - ) - ) + rule.visit(fileContent) + assertThat(rule.findings).isEmpty() + } - rule.visit(fileContent) - assertThat(rule.findings).hasSize(2) - } - - @Test - fun `should not report anything if both package and import statements are disabled`() { - val rule = MaxLineLength( - TestConfig( - mapOf( - MAX_LINE_LENGTH to "60", - EXCLUDE_PACKAGE_STATEMENTS to "true", - EXCLUDE_IMPORT_STATEMENTS to "true" - ) + @Test + fun `should report the package statement and import statements if they're enabled`() { + val rule = MaxLineLength( + TestConfig( + mapOf( + MAX_LINE_LENGTH to "60", + EXCLUDE_PACKAGE_STATEMENTS to "false", + EXCLUDE_IMPORT_STATEMENTS to "false" ) ) + ) - rule.visit(fileContent) - assertThat(rule.findings).isEmpty() - } + rule.visit(fileContent) + assertThat(rule.findings).hasSize(2) } - @Nested - inner class `a kt file with a long package name, long import statements, a long line and long comments` { + @Test + fun `should not report anything if both package and import statements are disabled`() { + val rule = MaxLineLength( + TestConfig( + mapOf( + MAX_LINE_LENGTH to "60", + EXCLUDE_PACKAGE_STATEMENTS to "true", + EXCLUDE_IMPORT_STATEMENTS to "true" + ) + ) + ) - val file = compileForTest(Case.MaxLineLengthWithLongComments.path()) - val lines = file.text.splitToSequence("\n") - val fileContent = KtFileContent(file, lines) + rule.visit(fileContent) + assertThat(rule.findings).isEmpty() + } + } - @Test - fun `should report the package statement, import statements, line and comments by default`() { - val rule = MaxLineLength( - TestConfig( - mapOf( - MAX_LINE_LENGTH to "60" - ) + @Nested + inner class `a kt file with a long package name, long import statements, a long line and long comments` { + + val file = compileForTest(Case.MaxLineLengthWithLongComments.path()) + val lines = file.text.splitToSequence("\n") + val fileContent = KtFileContent(file, lines) + + @Test + fun `should report the package statement, import statements, line and comments by default`() { + val rule = MaxLineLength( + TestConfig( + mapOf( + MAX_LINE_LENGTH to "60" ) ) + ) + + rule.visit(fileContent) + assertThat(rule.findings).hasSize(8) + } - rule.visit(fileContent) - assertThat(rule.findings).hasSize(8) - } - - @Test - fun `should report the package statement, import statements, line and comments if they're enabled`() { - val rule = MaxLineLength( - TestConfig( - mapOf( - MAX_LINE_LENGTH to "60", - EXCLUDE_PACKAGE_STATEMENTS to "false", - EXCLUDE_IMPORT_STATEMENTS to "false", - EXCLUDE_COMMENT_STATEMENTS to "false" - ) + @Test + fun `should report the package statement, import statements, line and comments if they're enabled`() { + val rule = MaxLineLength( + TestConfig( + mapOf( + MAX_LINE_LENGTH to "60", + EXCLUDE_PACKAGE_STATEMENTS to "false", + EXCLUDE_IMPORT_STATEMENTS to "false", + EXCLUDE_COMMENT_STATEMENTS to "false" ) ) + ) + + rule.visit(fileContent) + assertThat(rule.findings).hasSize(8) + } - rule.visit(fileContent) - assertThat(rule.findings).hasSize(8) - } - - @Test - fun `should not report comments if they're disabled`() { - val rule = MaxLineLength( - TestConfig( - mapOf( - MAX_LINE_LENGTH to "60", - EXCLUDE_COMMENT_STATEMENTS to "true" - ) + @Test + fun `should not report comments if they're disabled`() { + val rule = MaxLineLength( + TestConfig( + mapOf( + MAX_LINE_LENGTH to "60", + EXCLUDE_COMMENT_STATEMENTS to "true" ) ) + ) - rule.visit(fileContent) - assertThat(rule.findings).hasSize(5) - } + rule.visit(fileContent) + assertThat(rule.findings).hasSize(5) } + } + + @Nested + inner class `a kt file with a long package name, long import statements and a long line` { + val code = """ + package anIncrediblyLongAndComplexPackageNameThatProbablyShouldBeMuchShorterButForTheSakeOfTheTestItsNot - @Nested - inner class `a kt file with a long package name, long import statements and a long line` { - val code = """ - package anIncrediblyLongAndComplexPackageNameThatProbablyShouldBeMuchShorterButForTheSakeOfTheTestItsNot - - import anIncrediblyLongAndComplexImportNameThatProbablyShouldBeMuchShorterButForTheSakeOfTheTestItsNot - - class Test { - fun anIncrediblyLongAndComplexMethodNameThatProbablyShouldBeMuchShorterButForTheSakeOfTheTestItsNot() {} - } - """.trim() - - val file = compileContentForTest(code) - val lines = file.text.splitToSequence("\n") - val fileContent = KtFileContent(file, lines) - - @Test - fun `should only the function line by default`() { - val rule = MaxLineLength( - TestConfig( - mapOf( - MAX_LINE_LENGTH to "60" - ) + import anIncrediblyLongAndComplexImportNameThatProbablyShouldBeMuchShorterButForTheSakeOfTheTestItsNot + + class Test { + fun anIncrediblyLongAndComplexMethodNameThatProbablyShouldBeMuchShorterButForTheSakeOfTheTestItsNot() {} + } + """.trimIndent() + + val file = compileContentForTest(code) + val lines = file.text.splitToSequence("\n") + val fileContent = KtFileContent(file, lines) + + @Test + fun `should only the function line by default`() { + val rule = MaxLineLength( + TestConfig( + mapOf( + MAX_LINE_LENGTH to "60" ) ) + ) + + rule.visit(fileContent) + assertThat(rule.findings).hasSize(1) + } - rule.visit(fileContent) - assertThat(rule.findings).hasSize(1) - } - - @Test - fun `should report the package statement, import statements and line if they're not excluded`() { - val rule = MaxLineLength( - TestConfig( - mapOf( - MAX_LINE_LENGTH to "60", - EXCLUDE_PACKAGE_STATEMENTS to "false", - EXCLUDE_IMPORT_STATEMENTS to "false" - ) + @Test + fun `should report the package statement, import statements and line if they're not excluded`() { + val rule = MaxLineLength( + TestConfig( + mapOf( + MAX_LINE_LENGTH to "60", + EXCLUDE_PACKAGE_STATEMENTS to "false", + EXCLUDE_IMPORT_STATEMENTS to "false" ) ) + ) - rule.visit(fileContent) - assertThat(rule.findings).hasSize(3) - } - - @Test - fun `should report only method if both package and import statements are disabled`() { - val rule = MaxLineLength( - TestConfig( - mapOf( - MAX_LINE_LENGTH to "60", - EXCLUDE_PACKAGE_STATEMENTS to "true", - EXCLUDE_IMPORT_STATEMENTS to "true" - ) + rule.visit(fileContent) + assertThat(rule.findings).hasSize(3) + } + + @Test + fun `should report only method if both package and import statements are disabled`() { + val rule = MaxLineLength( + TestConfig( + mapOf( + MAX_LINE_LENGTH to "60", + EXCLUDE_PACKAGE_STATEMENTS to "true", + EXCLUDE_IMPORT_STATEMENTS to "true" ) ) + ) + + rule.visit(fileContent) + assertThat(rule.findings).hasSize(1) + } - rule.visit(fileContent) - assertThat(rule.findings).hasSize(1) - } - - @Test - fun `should report correct line and column for function with excessive length`() { - val rule = MaxLineLength( - TestConfig( - mapOf( - MAX_LINE_LENGTH to "60", - EXCLUDE_PACKAGE_STATEMENTS to "true", - EXCLUDE_IMPORT_STATEMENTS to "true" - ) + @Test + fun `should report correct line and column for function with excessive length`() { + val rule = MaxLineLength( + TestConfig( + mapOf( + MAX_LINE_LENGTH to "60", + EXCLUDE_PACKAGE_STATEMENTS to "true", + EXCLUDE_IMPORT_STATEMENTS to "true" ) ) + ) - rule.visit(fileContent) - assertThat(rule.findings).hasSize(1) - assertThat(rule.findings).hasSourceLocations(SourceLocation(6, 17)) - } + rule.visit(fileContent) + assertThat(rule.findings).hasSize(1) + assertThat(rule.findings).hasSourceLocations(SourceLocation(6, 5)) } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MayBeConstSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MayBeConstSpec.kt index 2ce511fb6b0..f3786d258b5 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MayBeConstSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MayBeConstSpec.kt @@ -12,366 +12,362 @@ class MayBeConstSpec { val subject = MayBeConst() @Nested - inner class `MayBeConst rule` { - - @Nested - inner class `some valid constants` { - @Test - fun `is a valid constant`() { - val code = """ - object Something { - const val X = 42 - } - """ - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() - } - - @Test - fun `is const vals in object`() { - val code = """ - object Test { - const val TEST = "Test" + inner class `some valid constants` { + @Test + fun `is a valid constant`() { + val code = """ + object Something { + const val X = 42 } - """ - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() - } + """ + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } - @Test - fun `isconst vals in companion objects`() { - val code = """ - class Test { - companion object { - const val B = 1 - } - } - """ - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() + @Test + fun `is const vals in object`() { + val code = """ + object Test { + const val TEST = "Test" } + """ + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } - @Test - fun `does not report const vals that use other const vals`() { - val code = """ - object Something { - const val A = 0 + @Test + fun `isconst vals in companion objects`() { + val code = """ + class Test { + companion object { + const val B = 1 } + } + """ + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } - class Test { - companion object { - const val B = Something.A + 1 - } - } - """ - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() + @Test + fun `does not report const vals that use other const vals`() { + val code = """ + object Something { + const val A = 0 } - @Test - fun `does not report none const val candidates`() { - val code = """ - object Something { - const val a = 0 + class Test { + companion object { + const val B = Something.A + 1 } - val p = Pair(Something.a, Something.a + Something.a) - val p2 = emptyList().plus(Something.a) - """ - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() } + """ + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() } - @Nested - inner class `some vals that could be constants` { - @Test - fun `is a simple val`() { - val code = """ - val x = 1 - """ - subject.compileAndLint(code) - assertThat(subject.findings).hasSize(1).hasSourceLocations( - SourceLocation(1, 5) - ) + @Test + fun `does not report none const val candidates`() { + val code = """ + object Something { + const val a = 0 } + val p = Pair(Something.a, Something.a + Something.a) + val p2 = emptyList().plus(Something.a) + """ + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } + } - @Test - fun `is a simple JvmField val`() { - val code = """ - @JvmField val x = 1 - """ - subject.compileAndLint(code) - assertThat(subject.findings).hasSize(1).hasSourceLocations( - SourceLocation(1, 15) - ) + @Nested + inner class `some vals that could be constants` { + @Test + fun `is a simple val`() { + val code = """ + val x = 1 + """ + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(1).hasSourceLocations( + SourceLocation(1, 5) + ) + } + + @Test + fun `is a simple JvmField val`() { + val code = """ + @JvmField val x = 1 + """ + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(1).hasSourceLocations( + SourceLocation(1, 15) + ) + } + + @Test + fun `is a field in an object`() { + val code = """ + object Test { + @JvmField val test = "Test" } + """ + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(1).hasSourceLocations( + SourceLocation(2, 19) + ) + } - @Test - fun `is a field in an object`() { - val code = """ - object Test { - @JvmField val test = "Test" + @Test + fun `reports vals in companion objects`() { + val code = """ + class Test { + companion object { + val b = 1 } - """ - subject.compileAndLint(code) - assertThat(subject.findings).hasSize(1).hasSourceLocations( - SourceLocation(2, 19) - ) } + """ + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(1).hasSourceLocations( + SourceLocation(3, 13) + ) + } + } - @Test - fun `reports vals in companion objects`() { - val code = """ - class Test { - companion object { - val b = 1 - } - } - """ - subject.compileAndLint(code) - assertThat(subject.findings).hasSize(1).hasSourceLocations( - SourceLocation(3, 13) - ) + @Nested + inner class `vals that can be constants but detekt doesn't handle yet` { + @Test + fun `is a constant binary expression`() { + val code = """ + object Something { + const val one = 1 + val two = one * 2 } + """ + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(1).hasSourceLocations( + SourceLocation(3, 9) + ) } - @Nested - inner class `vals that can be constants but detekt doesn't handle yet` { - @Test - fun `is a constant binary expression`() { - val code = """ - object Something { + @Test + fun `is a constant binary expression in a companion object`() { + val code = """ + class Test { + companion object { const val one = 1 val two = one * 2 } - """ - subject.compileAndLint(code) - assertThat(subject.findings).hasSize(1).hasSourceLocations( - SourceLocation(3, 9) - ) } + """ + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(1).hasSourceLocations( + SourceLocation(4, 13) + ) + } - @Test - fun `is a constant binary expression in a companion object`() { - val code = """ - class Test { - companion object { - const val one = 1 - val two = one * 2 - } - } - """ - subject.compileAndLint(code) - assertThat(subject.findings).hasSize(1).hasSourceLocations( - SourceLocation(4, 13) - ) + @Test + fun `is a nested constant binary expression`() { + val code = """ + object Something { + const val one = 1 + val two = one * 2 + 1 } + """ + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(1).hasSourceLocations( + SourceLocation(3, 9) + ) + } - @Test - fun `is a nested constant binary expression`() { - val code = """ - object Something { - const val one = 1 - val two = one * 2 + 1 - } - """ - subject.compileAndLint(code) - assertThat(subject.findings).hasSize(1).hasSourceLocations( - SourceLocation(3, 9) - ) + @Test + fun `is a nested constant parenthesised expression`() { + val code = """ + object Something { + const val one = 1 + val two = one * (2 + 1) } + """ + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(1).hasSourceLocations( + SourceLocation(3, 9) + ) + } - @Test - fun `is a nested constant parenthesised expression`() { - val code = """ - object Something { - const val one = 1 - val two = one * (2 + 1) - } - """ - subject.compileAndLint(code) - assertThat(subject.findings).hasSize(1).hasSourceLocations( - SourceLocation(3, 9) - ) + @Test + fun `reports vals that use other const vals`() { + val code = """ + object Something { + const val a = 0 + + @JvmField + val b = a + 1 } + """ + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(1).hasSourceLocations( + SourceLocation(5, 9) + ) + } - @Test - fun `reports vals that use other const vals`() { - val code = """ - object Something { - const val a = 0 - - @JvmField - val b = a + 1 - } - """ - subject.compileAndLint(code) - assertThat(subject.findings).hasSize(1).hasSourceLocations( - SourceLocation(5, 9) - ) + @Test + fun `reports concatenated string vals`() { + val code = """ + object Something { + private const val A = "a" + private val B = A + "b" } + """ + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(1).hasSourceLocations( + SourceLocation(3, 17) + ) + } + } - @Test - fun `reports concatenated string vals`() { - val code = """ - object Something { - private const val A = "a" - private val B = A + "b" - } - """ - subject.compileAndLint(code) - assertThat(subject.findings).hasSize(1).hasSourceLocations( - SourceLocation(3, 17) - ) - } + @Nested + inner class `vals that cannot be constants` { + @Test + fun `does not report arrays`() { + val code = "val arr = arrayOf(\"a\", \"b\")" + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() } - @Nested - inner class `vals that cannot be constants` { - @Test - fun `does not report arrays`() { - val code = "val arr = arrayOf(\"a\", \"b\")" - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() - } + @Test + fun `is a var`() { + val code = "var test = 1" + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } - @Test - fun `is a var`() { - val code = "var test = 1" - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() - } + @Test + fun `has a getter`() { + val code = "val withGetter get() = 42" + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } - @Test - fun `has a getter`() { - val code = "val withGetter get() = 42" - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() - } + @Test + fun `is initialized to null`() { + val code = "val test = null" + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } - @Test - fun `is initialized to null`() { - val code = "val test = null" - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() + @Test + fun `is a JvmField in a class`() { + val code = """ + class Test { + @JvmField val a = 3 } + """ + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } - @Test - fun `is a JvmField in a class`() { - val code = """ - class Test { - @JvmField val a = 3 - } - """ - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() - } + @Test + fun `has some annotation`() { + val code = """ + annotation class A - @Test - fun `has some annotation`() { - val code = """ - annotation class A + @A val a = 55 + """ + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } - @A val a = 55 - """ - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() + @Test + fun `overrides something`() { + val code = """ + interface Base { + val property: Int } - @Test - fun `overrides something`() { - val code = """ - interface Base { - val property: Int - } - - object Derived : Base { - override val property = 1 - } - """ - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() + object Derived : Base { + override val property = 1 } + """ + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } - @Test - fun `does not detect just a dollar as interpolation`() { - val code = """ val hasDollar = "$" """ - subject.compileAndLint(code) - assertThat(subject.findings).hasSize(1) - } + @Test + fun `does not detect just a dollar as interpolation`() { + val code = """ val hasDollar = "$" """ + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(1) + } - @Test - fun `does not report interpolated strings`() { - val innerCode = "\"\"\"object Test { val TEST = \"Test \$test_var\"}\"\"\"" - val classReference = "\${AnotherClass::class.java.name}" - val staticReference = "\${AnotherClass.staticVariable}" - val code = """ - class AnotherClass { - companion object { - const val staticVariable = "" - } - } - object Something { - val const = "$classReference.EXTRA_DETAILS" - private val A = "asdf=$staticReference" + @Test + fun `does not report interpolated strings`() { + val innerCode = "\"\"\"object Test { val TEST = \"Test \$test_var\"}\"\"\"" + val classReference = "\${AnotherClass::class.java.name}" + val staticReference = "\${AnotherClass.staticVariable}" + val code = """ + class AnotherClass { + companion object { + const val staticVariable = "" } - var test_var = "test" - var code = $innerCode - """ - subject.compileAndLint(code) - assertThat(subject.findings).isEmpty() - } + } + object Something { + val const = "$classReference.EXTRA_DETAILS" + private val A = "asdf=$staticReference" + } + var test_var = "test" + var code = $innerCode + """ + subject.compileAndLint(code) + assertThat(subject.findings).isEmpty() + } - @Test - fun `does not report vals inside anonymous object declaration`() { - subject.compileAndLint( - """ - fun main() { - val versions = object { - val prop = "" - } + @Test + fun `does not report vals inside anonymous object declaration`() { + subject.compileAndLint( + """ + fun main() { + val versions = object { + val prop = "" } - """ - ) + } + """ + ) - assertThat(subject.findings).isEmpty() - } + assertThat(subject.findings).isEmpty() + } - @Test - fun `does not report actual vals`() { - // Until the [KotlinScriptEngine] can compile KMP, we will only lint. - subject.lint("""actual val abc123 = "abc123" """) - assertThat(subject.findings).isEmpty() - } + @Test + fun `does not report actual vals`() { + // Until the [KotlinScriptEngine] can compile KMP, we will only lint. + subject.lint("""actual val abc123 = "abc123" """) + assertThat(subject.findings).isEmpty() } + } - @Nested - inner class `some const val candidates in nested objects` { - - @Test - fun `reports the const val candidates`() { - val code = """ - object Root { - const val ROOT_CONST = 1 - object A1 { - val ACONST = ROOT_CONST + 1 - const val ACONST_1 = 1 - object B1 { - val BCONST = ACONST_1 + 1 - } - } - object A2 { - val ACONST = ROOT_CONST + 1 + @Nested + inner class `some const val candidates in nested objects` { + + @Test + fun `reports the const val candidates`() { + val code = """ + object Root { + const val ROOT_CONST = 1 + object A1 { + val ACONST = ROOT_CONST + 1 + const val ACONST_1 = 1 + object B1 { + val BCONST = ACONST_1 + 1 } } - """ - subject.compileAndLint(code) - assertThat(subject.findings).hasSize(3).hasSourceLocations( - SourceLocation(4, 13), - SourceLocation(7, 17), - SourceLocation(11, 13) - ) - } + object A2 { + val ACONST = ROOT_CONST + 1 + } + } + """ + subject.compileAndLint(code) + assertThat(subject.findings).hasSize(3).hasSourceLocations( + SourceLocation(4, 13), + SourceLocation(7, 17), + SourceLocation(11, 13) + ) } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ModifierOrderSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ModifierOrderSpec.kt index b0c219a07d4..af049d6a8df 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ModifierOrderSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ModifierOrderSpec.kt @@ -12,148 +12,144 @@ class ModifierOrderSpec { val subject = ModifierOrder(Config.empty) @Nested - inner class `ModifierOrder rule` { - - @Nested - inner class `kt classes with modifiers` { - val bad1 = "data internal class Test(val test: String)" - val bad2 = "actual private class Test(val test: String)" - val bad3 = "annotation expect class Test" - - @Test - fun `should report incorrectly ordered modifiers`() { - assertThat(subject.compileAndLint(bad1)).hasSize(1) - assertThat(subject.lint(bad2)).hasSize(1) - assertThat(subject.lint(bad3)).hasSize(1) - } - - @Test - fun `does not report correctly ordered modifiers`() { - assertThat(subject.compileAndLint("internal data class Test(val test: String)")).isEmpty() - assertThat(subject.lint("private actual class Test(val test: String)")).isEmpty() - assertThat(subject.lint("expect annotation class Test")).isEmpty() - } - - @Test - fun `should not report issues if inactive`() { - val rule = ModifierOrder(TestConfig(mapOf(Config.ACTIVE_KEY to "false"))) - assertThat(rule.compileAndLint(bad1)).isEmpty() - assertThat(rule.lint(bad2)).isEmpty() - assertThat(rule.lint(bad3)).isEmpty() - } + inner class `kt classes with modifiers` { + val bad1 = "data internal class Test(val test: String)" + val bad2 = "actual private class Test(val test: String)" + val bad3 = "annotation expect class Test" + + @Test + fun `should report incorrectly ordered modifiers`() { + assertThat(subject.compileAndLint(bad1)).hasSize(1) + assertThat(subject.lint(bad2)).hasSize(1) + assertThat(subject.lint(bad3)).hasSize(1) } - @Nested - inner class `a kt parameter with modifiers` { + @Test + fun `does not report correctly ordered modifiers`() { + assertThat(subject.compileAndLint("internal data class Test(val test: String)")).isEmpty() + assertThat(subject.lint("private actual class Test(val test: String)")).isEmpty() + assertThat(subject.lint("expect annotation class Test")).isEmpty() + } + + @Test + fun `should not report issues if inactive`() { + val rule = ModifierOrder(TestConfig(mapOf(Config.ACTIVE_KEY to "false"))) + assertThat(rule.compileAndLint(bad1)).isEmpty() + assertThat(rule.lint(bad2)).isEmpty() + assertThat(rule.lint(bad3)).isEmpty() + } + } + + @Nested + inner class `a kt parameter with modifiers` { + + @Test + fun `should report wrongly ordered modifiers`() { + val code = "lateinit internal var test: String" + assertThat(subject.compileAndLint(code)).hasSize(1) + } + + @Test + fun `should not report correctly ordered modifiers`() { + val code = "internal lateinit var test: String" + assertThat(subject.compileAndLint(code)).isEmpty() + } + } - @Test - fun `should report wrongly ordered modifiers`() { - val code = "lateinit internal var test: String" - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Nested + inner class `an overridden function` { + + @Test + fun `should report incorrectly ordered modifiers`() { + val code = """ + abstract class A { + abstract fun test() + } + abstract class Test : A() { + override open fun test() {} + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `should not report correctly ordered modifiers`() { - val code = "internal lateinit var test: String" - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `should not report correctly ordered modifiers`() { + val code = """ + abstract class A { + abstract fun test() + } + abstract class Test : A() { + override fun test() {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } + } - @Nested - inner class `an overridden function` { - - @Test - fun `should report incorrectly ordered modifiers`() { - val code = """ - abstract class A { - abstract fun test() - } - abstract class Test : A() { - override open fun test() {} - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `should not report correctly ordered modifiers`() { - val code = """ - abstract class A { - abstract fun test() - } - abstract class Test : A() { - override fun test() {} - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Nested + inner class `a tailrec function` { + + @Test + fun `should report incorrectly ordered modifiers`() { + val code = """ + public class A { + tailrec private fun foo(x: Double = 1.0): Double = 1.0 + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) } - @Nested - inner class `a tailrec function` { - - @Test - fun `should report incorrectly ordered modifiers`() { - val code = """ - public class A { - tailrec private fun foo(x: Double = 1.0): Double = 1.0 - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `should not report correctly ordered modifiers`() { - val code = """ - public class A { - private tailrec fun foo(x: Double = 1.0): Double = 1.0 - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `should not report correctly ordered modifiers`() { + val code = """ + public class A { + private tailrec fun foo(x: Double = 1.0): Double = 1.0 + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } + } - @Nested - inner class `a vararg argument` { + @Nested + inner class `a vararg argument` { - @Test - fun `should report incorrectly ordered modifiers`() { - val code = "class Foo(vararg private val strings: String) {}" - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `should report incorrectly ordered modifiers`() { + val code = "class Foo(vararg private val strings: String) {}" + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `should not report correctly ordered modifiers`() { - val code = "class Foo(private vararg val strings: String) {}" - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `should not report correctly ordered modifiers`() { + val code = "class Foo(private vararg val strings: String) {}" + assertThat(subject.compileAndLint(code)).isEmpty() } + } - @Nested - inner class `fun interface` { - - @Test - fun `should not report correctly ordered modifiers`() { - val code = """ - private fun interface LoadMoreCallback { - fun loadMore(): Boolean - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Nested + inner class `fun interface` { + + @Test + fun `should not report correctly ordered modifiers`() { + val code = """ + private fun interface LoadMoreCallback { + fun loadMore(): Boolean + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } + } - @Nested - inner class `value class` { - - @Test - fun `should not report correctly ordered modifiers`() { - val code = """ - @JvmInline - private value class Foo(val bar: Int) - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Nested + inner class `value class` { + + @Test + fun `should not report correctly ordered modifiers`() { + val code = """ + @JvmInline + private value class Foo(val bar: Int) + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineLambdaItParameterSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineLambdaItParameterSpec.kt index 010e6e14bac..9d9a5b5dda4 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineLambdaItParameterSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/MultilineLambdaItParameterSpec.kt @@ -13,204 +13,201 @@ class MultilineLambdaItParameterSpec(val env: KotlinCoreEnvironment) { val subject = MultilineLambdaItParameter(Config.empty) @Nested - inner class `MultilineLambdaItParameter rule` { - @Nested - inner class `single parameter, multiline lambda with multiple statements` { - @Test - fun `reports when parameter name is implicit 'it'`() { - val code = """ - fun f() { - val digits = 1234.let { - listOf(it) - println(it) - } + inner class `single parameter, multiline lambda with multiple statements` { + @Test + fun `reports when parameter name is implicit 'it'`() { + val code = """ + fun f() { + val digits = 1234.let { + listOf(it) + println(it) } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } - @Test - fun `reports when parameter name is explicit 'it'`() { - val code = """ - fun f() { - val digits = 1234.let { it -> - listOf(it) - println(it) - } + @Test + fun `reports when parameter name is explicit 'it'`() { + val code = """ + fun f() { + val digits = 1234.let { it -> + listOf(it) + println(it) } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } - @Test - fun `does not report when parameter name is explicit and not 'it'`() { - val code = """ - fun f() { - val digits = 1234.let { param -> - listOf(param) - println(param) - } + @Test + fun `does not report when parameter name is explicit and not 'it'`() { + val code = """ + fun f() { + val digits = 1234.let { param -> + listOf(param) + println(param) } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `does not report when lambda has no implicit parameter references`() { - val code = """ - fun foo(f: (Int) -> Unit) {} - fun main() { - foo { - println(1) - println(2) - val it = 3 - println(it) - } + @Test + fun `does not report when lambda has no implicit parameter references`() { + val code = """ + fun foo(f: (Int) -> Unit) {} + fun main() { + foo { + println(1) + println(2) + val it = 3 + println(it) } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `single parameter, multiline lambda with a single statement` { - @Test - fun `does not report when parameter name is an implicit 'it'`() { - val code = """ - fun f() { - val digits = 1234.let { - listOf(it) - } + @Nested + inner class `single parameter, multiline lambda with a single statement` { + @Test + fun `does not report when parameter name is an implicit 'it'`() { + val code = """ + fun f() { + val digits = 1234.let { + listOf(it) } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `does not report when parameter name is an explicit 'it'`() { - val code = """ - fun f() { - val digits = 1234.let { it -> - listOf(it) - } + @Test + fun `does not report when parameter name is an explicit 'it'`() { + val code = """ + fun f() { + val digits = 1234.let { it -> + listOf(it) } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `does not report when parameter name is explicit and not 'it'`() { - val code = """ - fun f() { - val digits = 1234.let { param -> - listOf(param) - } + @Test + fun `does not report when parameter name is explicit and not 'it'`() { + val code = """ + fun f() { + val digits = 1234.let { param -> + listOf(param) } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `single parameter, single-line lambda` { - @Test - fun `does not report when parameter name is an implicit 'it' with type resolution`() { - val code = """ - fun f() { - val digits = 1234.let { listOf(it) } - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() + @Nested + inner class `single parameter, single-line lambda` { + @Test + fun `does not report when parameter name is an implicit 'it' with type resolution`() { + val code = """ + fun f() { + val digits = 1234.let { listOf(it) } } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `does not report when parameter name is an implicit 'it'`() { - val code = """ - fun f() { - val digits = 1234.let { listOf(it) } - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() + @Test + fun `does not report when parameter name is an implicit 'it'`() { + val code = """ + fun f() { + val digits = 1234.let { listOf(it) } } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `does not report when parameter name is an explicit 'it'`() { - val code = """ - fun f() { - val digits = 1234.let { it -> listOf(it) } - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() + @Test + fun `does not report when parameter name is an explicit 'it'`() { + val code = """ + fun f() { + val digits = 1234.let { it -> listOf(it) } } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `does not report when parameter name is explicit and not 'it'`() { - val code = """ - fun f() { - val digits = 1234.let { param -> listOf(param) } - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() + @Test + fun `does not report when parameter name is explicit and not 'it'`() { + val code = """ + fun f() { + val digits = 1234.let { param -> listOf(param) } } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `multiple parameters, multiline lambda` { - @Test - fun `reports when one of the explicit parameters is an 'it'`() { - val code = """ - fun f() { - val flat = listOf(listOf(1), listOf(2)).mapIndexed { index, it -> - println(it) - it + index - } + @Nested + inner class `multiple parameters, multiline lambda` { + @Test + fun `reports when one of the explicit parameters is an 'it'`() { + val code = """ + fun f() { + val flat = listOf(listOf(1), listOf(2)).mapIndexed { index, it -> + println(it) + it + index } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } - @Test - fun `does not report when none of the explicit parameters is an 'it'`() { - val code = """ - fun f() { - val lambda = { item: Int, that: String -> - println(item) - item.toString() + that - } + @Test + fun `does not report when none of the explicit parameters is an 'it'`() { + val code = """ + fun f() { + val lambda = { item: Int, that: String -> + println(item) + item.toString() + that } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `no parameter, multiline lambda with multiple statements` { - @Test - fun `does not report when there is no parameter`() { - val code = """ - fun f() { - val string = StringBuilder().apply { - append("a") - append("b") - } + @Nested + inner class `no parameter, multiline lambda with multiple statements` { + @Test + fun `does not report when there is no parameter`() { + val code = """ + fun f() { + val string = StringBuilder().apply { + append("a") + append("b") } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/NestedClassesVisibilitySpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/NestedClassesVisibilitySpec.kt index a8371c171ff..792b0628a97 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/NestedClassesVisibilitySpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/NestedClassesVisibilitySpec.kt @@ -2,121 +2,116 @@ package io.gitlab.arturbosch.detekt.rules.style import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class NestedClassesVisibilitySpec { val subject = NestedClassesVisibility() - @Nested - inner class `NestedClassesVisibility rule` { - - @Test - fun `reports explicit public visibility in nested objects, classes and interfaces`() { - val code = """ - internal class Outer { - public interface A - public object B - public class C - } - """ - assertThat(subject.compileAndLint(code)).hasSize(3) - } + @Test + fun `reports explicit public visibility in nested objects, classes and interfaces`() { + val code = """ + internal class Outer { + public interface A + public object B + public class C + } + """ + assertThat(subject.compileAndLint(code)).hasSize(3) + } - @Test - fun `reports explicit public visibility in nested classes inside an enum`() { - val code = """ - internal enum class Outer { - A; - public class C - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports explicit public visibility in nested classes inside an enum`() { + val code = """ + internal enum class Outer { + A; + public class C + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report nested internal classes and interfaces`() { - val code = """ - internal class Outer { - class A - internal class B - enum class E { One } - internal interface I - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report nested internal classes and interfaces`() { + val code = """ + internal class Outer { + class A + internal class B + enum class E { One } + internal interface I + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report nested private classes`() { - val code = """ - internal class Outer { - private class A - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report nested private classes`() { + val code = """ + internal class Outer { + private class A + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report nested public enums`() { - val code = """ - internal class Outer { - public enum class E { E1; } - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report nested public enums`() { + val code = """ + internal class Outer { + public enum class E { E1; } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report companion object that is explicitly public`() { - val code = """ - internal class Outer { - public companion object C - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report companion object that is explicitly public`() { + val code = """ + internal class Outer { + public companion object C + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report companion object`() { - val code = """ - internal class Outer { - companion object C - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report companion object`() { + val code = """ + internal class Outer { + companion object C + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report nested classes inside a private class`() { - val code = """ - private class Outer { - class A - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report nested classes inside a private class`() { + val code = """ + private class Outer { + class A + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report nested internal classes inside an interface`() { - val code = """ - internal interface Outer { - class A - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report nested internal classes inside an interface`() { + val code = """ + internal interface Outer { + class A + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report nested classes with a nesting depth higher than 1`() { - val code = """ - internal class Outer { - class C1 { - public class C2 - } + @Test + fun `does not report nested classes with a nesting depth higher than 1`() { + val code = """ + internal class Outer { + class C1 { + public class C2 } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/NewLineAtEndOfFileSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/NewLineAtEndOfFileSpec.kt index 67c6f53abf1..85d79712cd3 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/NewLineAtEndOfFileSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/NewLineAtEndOfFileSpec.kt @@ -2,33 +2,28 @@ package io.gitlab.arturbosch.detekt.rules.style import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class NewLineAtEndOfFileSpec { val subject = NewLineAtEndOfFile() - @Nested - inner class `NewLineAtEndOfFile rule` { - - @Test - fun `should not flag a kt file containing new line at the end`() { - val code = "class Test\n\n" // we need double '\n' because .lint() applies .trimIndent() which removes one - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `should not flag a kt file containing new line at the end`() { + val code = "class Test\n\n" // we need double '\n' because .lint() applies .trimIndent() which removes one + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `should flag a kt file not containing new line at the end`() { - val code = "class Test" - assertThat(subject.compileAndLint(code)).hasSize(1) - .hasSourceLocation(1, 11) - } + @Test + fun `should flag a kt file not containing new line at the end`() { + val code = "class Test" + assertThat(subject.compileAndLint(code)).hasSize(1) + .hasSourceLocation(1, 11) + } - @Test - fun `should not flag an empty kt file`() { - val code = "" - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `should not flag an empty kt file`() { + val code = "" + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/NoTabsSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/NoTabsSpec.kt index 73c74bed675..5765ea9c52f 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/NoTabsSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/NoTabsSpec.kt @@ -3,28 +3,23 @@ package io.gitlab.arturbosch.detekt.rules.style import io.github.detekt.test.utils.compileForTest import io.gitlab.arturbosch.detekt.rules.Case import io.gitlab.arturbosch.detekt.test.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class NoTabsSpec { - @Nested - inner class `NoTabs rule` { - - @Test - fun `should flag a line that contains a tab`() { - val subject = NoTabs() - val file = compileForTest(Case.NoTabsPositive.path()) - subject.findTabs(file) - assertThat(subject.findings).hasSize(5) - } + @Test + fun `should flag a line that contains a tab`() { + val subject = NoTabs() + val file = compileForTest(Case.NoTabsPositive.path()) + subject.findTabs(file) + assertThat(subject.findings).hasSize(5) + } - @Test - fun `should not flag a line that does not contain a tab`() { - val subject = NoTabs() - val file = compileForTest(Case.NoTabsNegative.path()) - subject.findTabs(file) - assertThat(subject.findings).isEmpty() - } + @Test + fun `should not flag a line that does not contain a tab`() { + val subject = NoTabs() + val file = compileForTest(Case.NoTabsNegative.path()) + subject.findTabs(file) + assertThat(subject.findings).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ObjectLiteralToLambdaSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ObjectLiteralToLambdaSpec.kt index 1dd4bbed6c9..728f977d82e 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ObjectLiteralToLambdaSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ObjectLiteralToLambdaSpec.kt @@ -18,586 +18,582 @@ class ObjectLiteralToLambdaSpec(val env: KotlinCoreEnvironment) { val subject = ObjectLiteralToLambda() @Nested - inner class `ObjectLiteralToLambda rule` { + inner class `report convertible expression` { + @Test + fun `is property`() { + val code = """ + fun interface Sam { + fun foo() + } + val a = object : Sam { + override fun foo() { + } + } + """ + subject.compileAndLintWithContext(env, code) + .assert() + .hasSize(1) + .hasSourceLocations(SourceLocation(4, 9)) + } - @Nested - inner class `report convertible expression` { - @Test - fun `is property`() { - val code = """ - fun interface Sam { - fun foo() - } - val a = object : Sam { + @Test + fun `is in function`() { + val code = """ + fun interface Sam { + fun foo() + } + fun bar() { + object : Sam { override fun foo() { } - } - """ - subject.compileAndLintWithContext(env, code) - .assert() - .hasSize(1) - .hasSourceLocations(SourceLocation(4, 9)) + } } + """ + subject.compileAndLintWithContext(env, code) + .assert() + .hasSize(1) + .hasSourceLocations(SourceLocation(5, 5)) + } - @Test - fun `is in function`() { - val code = """ - fun interface Sam { - fun foo() - } - fun bar() { + @Test + fun `is in init`() { + val code = """ + fun interface Sam { + fun foo() + } + object B { + init { object : Sam { override fun foo() { } } } - """ - subject.compileAndLintWithContext(env, code) - .assert() - .hasSize(1) - .hasSourceLocations(SourceLocation(5, 5)) } + """ + subject.compileAndLintWithContext(env, code) + .assert() + .hasSize(1) + .hasSourceLocations(SourceLocation(6, 9)) + } - @Test - fun `is in init`() { - val code = """ - fun interface Sam { - fun foo() - } - object B { - init { - object : Sam { - override fun foo() { - } - } - } - } - """ - subject.compileAndLintWithContext(env, code) - .assert() - .hasSize(1) - .hasSourceLocations(SourceLocation(6, 9)) + @Test + fun `is generic`() { + val code = """ + fun interface Sam { + fun foo(): T } + val a = object : Sam { + override fun foo(): Int { + return 1 + } + } + """ + subject.compileAndLintWithContext(env, code) + .assert() + .hasSize(1) + .hasSourceLocations(SourceLocation(4, 9)) + } - @Test - fun `is generic`() { - val code = """ - fun interface Sam { - fun foo(): T - } - val a = object : Sam { - override fun foo(): Int { - return 1 - } - } - """ - subject.compileAndLintWithContext(env, code) - .assert() - .hasSize(1) - .hasSourceLocations(SourceLocation(4, 9)) + @Test + fun `has other default method`() { + val code = """ + fun interface Sam { + fun foo() + fun bar() {} } + val a = object : Sam { + override fun foo() { + } + } + """ + subject.compileAndLintWithContext(env, code) + .assert() + .hasSize(1) + .hasSourceLocations(SourceLocation(5, 9)) + } - @Test - fun `has other default method`() { - val code = """ - fun interface Sam { - fun foo() - fun bar() {} - } - val a = object : Sam { - override fun foo() { - } - } - """ - subject.compileAndLintWithContext(env, code) - .assert() - .hasSize(1) - .hasSourceLocations(SourceLocation(5, 9)) + @Test + fun `nested declaration`() { + val code = """ + interface First { + fun foo() } + fun interface Second: First - @Test - fun `nested declaration`() { - val code = """ - interface First { - fun foo() - } - fun interface Second: First - - fun bar() { - object : Second { - override fun foo(){ - } + fun bar() { + object : Second { + override fun foo(){ } } - """ - subject.compileAndLintWithContext(env, code) - .assert() - .hasSize(1) - .hasSourceLocations(SourceLocation(7, 5)) } + """ + subject.compileAndLintWithContext(env, code) + .assert() + .hasSize(1) + .hasSourceLocations(SourceLocation(7, 5)) + } - @Test - fun `expression body syntax`() { - val code = """ - fun interface Sam { - fun foo(): Int - } - val a = object : Sam { - override fun foo() = 3 - } - """ - subject.compileAndLintWithContext(env, code) - .assert() - .hasSize(1) - .hasSourceLocations(SourceLocation(4, 9)) + @Test + fun `expression body syntax`() { + val code = """ + fun interface Sam { + fun foo(): Int + } + val a = object : Sam { + override fun foo() = 3 } + """ + subject.compileAndLintWithContext(env, code) + .assert() + .hasSize(1) + .hasSourceLocations(SourceLocation(4, 9)) } + } - @Nested - inner class `is not correct implement` { - @Test - fun `without type resolution`() { - val code = """ - fun interface Sam { - fun foo() - } - val a = object : Sam { - override fun foo() { - } + @Nested + inner class `is not correct implement` { + @Test + fun `without type resolution`() { + val code = """ + fun interface Sam { + fun foo() + } + val a = object : Sam { + override fun foo() { } - """ - subject.compileAndLint(code).assert().isEmpty() } + """ + subject.compileAndLint(code).assert().isEmpty() + } - @Test - fun `is empty interface`() { - val code = """ - interface Sam - val a = object : Sam {} - """ - subject.compileAndLintWithContext(env, code).assert().isEmpty() - } + @Test + fun `is empty interface`() { + val code = """ + interface Sam + val a = object : Sam {} + """ + subject.compileAndLintWithContext(env, code).assert().isEmpty() + } - @Test - fun `is empty interface and has own function`() { - val code = """ - interface Sam - val a = object : Sam { - fun foo() { - } + @Test + fun `is empty interface and has own function`() { + val code = """ + interface Sam + val a = object : Sam { + fun foo() { } - """ - subject.compileAndLintWithContext(env, code).assert().isEmpty() } + """ + subject.compileAndLintWithContext(env, code).assert().isEmpty() + } - @Test - fun `is single property interface`() { - val code = """ - interface Sam { - val foo: Int - } - val a = object : Sam { - override val foo = 1 - } - """ - subject.compileAndLintWithContext(env, code).assert().isEmpty() + @Test + fun `is single property interface`() { + val code = """ + interface Sam { + val foo: Int } + val a = object : Sam { + override val foo = 1 + } + """ + subject.compileAndLintWithContext(env, code).assert().isEmpty() + } - @Test - fun `is empty interface and has own property`() { - val code = """ - interface Sam - val a = object : Sam { - val b = 1 - } - """ - subject.compileAndLintWithContext(env, code).assert().isEmpty() + @Test + fun `is empty interface and has own property`() { + val code = """ + interface Sam + val a = object : Sam { + val b = 1 } + """ + subject.compileAndLintWithContext(env, code).assert().isEmpty() + } - @Test - fun `is not fun interface`() { - val code = """ - interface Sam { - fun foo() - } - val a = object : Sam { - override fun foo() { - } + @Test + fun `is not fun interface`() { + val code = """ + interface Sam { + fun foo() + } + val a = object : Sam { + override fun foo() { } - """ - subject.compileAndLintWithContext(env, code).assert().isEmpty() } + """ + subject.compileAndLintWithContext(env, code).assert().isEmpty() + } - @Test - fun `is not interface`() { - val code = """ - abstract class Something { - abstract fun foo() - } - val a = object : Something() { - override fun foo() { - } + @Test + fun `is not interface`() { + val code = """ + abstract class Something { + abstract fun foo() + } + val a = object : Something() { + override fun foo() { } - """ - subject.compileAndLintWithContext(env, code).assert().isEmpty() } + """ + subject.compileAndLintWithContext(env, code).assert().isEmpty() + } - @Test - fun `has multi implement`() { - val code = """ - fun interface First { - fun foo() - } - interface Second + @Test + fun `has multi implement`() { + val code = """ + fun interface First { + fun foo() + } + interface Second - val a: First = object : First, Second { - override fun foo() { - } + val a: First = object : First, Second { + override fun foo() { } - """ - subject.compileAndLintWithContext(env, code).assert().isEmpty() } + """ + subject.compileAndLintWithContext(env, code).assert().isEmpty() + } - @Test - fun `has complex implement`() { - val code = """ - abstract class First { - abstract fun foo() - } - fun interface Second { - fun foo() - } + @Test + fun `has complex implement`() { + val code = """ + abstract class First { + abstract fun foo() + } + fun interface Second { + fun foo() + } - val a: First = object : First(), Second { - override fun foo() { - } + val a: First = object : First(), Second { + override fun foo() { } - """ - subject.compileAndLintWithContext(env, code).assert().isEmpty() } + """ + subject.compileAndLintWithContext(env, code).assert().isEmpty() } + } - @Nested - inner class `has impurities` { - @Test - fun `has more than one method`() { - val code = """ - fun interface Sam { - fun foo() + @Nested + inner class `has impurities` { + @Test + fun `has more than one method`() { + val code = """ + fun interface Sam { + fun foo() + } + val a = object : Sam { + override fun foo() { } - val a = object : Sam { - override fun foo() { - } - fun bar() { - } + fun bar() { } - """ - subject.compileAndLintWithContext(env, code).assert().isEmpty() } + """ + subject.compileAndLintWithContext(env, code).assert().isEmpty() + } - @Test - fun `has property`() { - val code = """ - fun interface Sam { - fun foo() - } - val a = object : Sam { - private var bar = 0 - override fun foo() { - } + @Test + fun `has property`() { + val code = """ + fun interface Sam { + fun foo() + } + val a = object : Sam { + private var bar = 0 + override fun foo() { } - """ - subject.compileAndLintWithContext(env, code).assert().isEmpty() } + """ + subject.compileAndLintWithContext(env, code).assert().isEmpty() + } - @Test - fun `has init`() { - val code = """ - fun interface Sam { - fun foo() + @Test + fun `has init`() { + val code = """ + fun interface Sam { + fun foo() + } + val a = object : Sam { + init { } - val a = object : Sam { - init { - } - override fun foo() { - } + override fun foo() { } - """ - subject.compileAndLintWithContext(env, code).assert().isEmpty() } + """ + subject.compileAndLintWithContext(env, code).assert().isEmpty() } + } - @Nested - inner class `java interface` { - @Test - fun `is convertible`() { - val code = """ - val a = object : Runnable { - override fun run(){ - } + @Nested + inner class `java interface` { + @Test + fun `is convertible`() { + val code = """ + val a = object : Runnable { + override fun run(){ } - """ - subject.compileAndLintWithContext(env, code) - .assert() - .hasSize(1) - .hasSourceLocations(SourceLocation(1, 9)) } + """ + subject.compileAndLintWithContext(env, code) + .assert() + .hasSize(1) + .hasSourceLocations(SourceLocation(1, 9)) + } - @Test - fun `is convertible Callable generic`() { - val code = """ - import java.util.concurrent.Callable - val a = object : Callable { - override fun call(): Int { - return 1 - } + @Test + fun `is convertible Callable generic`() { + val code = """ + import java.util.concurrent.Callable + val a = object : Callable { + override fun call(): Int { + return 1 } - """ - subject.compileAndLintWithContext(env, code) - .assert() - .hasSize(1) - .hasSourceLocations(SourceLocation(2, 9)) } + """ + subject.compileAndLintWithContext(env, code) + .assert() + .hasSize(1) + .hasSourceLocations(SourceLocation(2, 9)) + } - @Test - fun `empty interface`() { - val code = """ - import java.util.EventListener - val a = object : EventListener { - fun foo() { - } + @Test + fun `empty interface`() { + val code = """ + import java.util.EventListener + val a = object : EventListener { + fun foo() { } - """ - subject.compileAndLintWithContext(env, code).assert().isEmpty() } + """ + subject.compileAndLintWithContext(env, code).assert().isEmpty() + } - @Test - fun `is convertible Enumeration generic`() { - val code = """ - import java.util.Enumeration - val a = object : Enumeration { - override fun hasMoreElements(): Boolean { - return true - } - - override fun nextElement(): Int { - return 1 - } + @Test + fun `is convertible Enumeration generic`() { + val code = """ + import java.util.Enumeration + val a = object : Enumeration { + override fun hasMoreElements(): Boolean { + return true } - """ - subject.compileAndLintWithContext(env, code).assert().isEmpty() - } - @Nested - inner class JavaSourceTests { - - private val environmentWrapper = - createEnvironment(additionalJavaSourceRootPaths = listOf(resourceAsPath("java").toFile())) - private val customEnv = environmentWrapper.env - - @AfterAll - fun disposeEnvironment() { - environmentWrapper.dispose() + override fun nextElement(): Int { + return 1 } + } + """ + subject.compileAndLintWithContext(env, code).assert().isEmpty() + } - @Test - fun `has other default methods`() { - val code = """ - import com.example.fromjava.SamWithDefaultMethods - - fun main() { - val x = object : SamWithDefaultMethods { - override fun foo() { - println() - } - } - } - """ - - subject.lintWithContext(customEnv, code).assert().hasSize(1) - } + @Nested + inner class JavaSourceTests { - @Test - fun `has only default methods`() { - val code = """ - import com.example.fromjava.OnlyDefaultMethods - - fun main() { - val x = object : OnlyDefaultMethods { - } - } - """ - subject.lintWithContext(customEnv, code).assert().isEmpty() - } + private val environmentWrapper = + createEnvironment(additionalJavaSourceRootPaths = listOf(resourceAsPath("java").toFile())) + private val customEnv = environmentWrapper.env - @Test - fun `implements a default method`() { - val code = """ - import com.example.fromjava.OnlyDefaultMethods - - fun main() { - val x = object : OnlyDefaultMethods { - override fun foo() { - println() - } - } - } - """ - subject.lintWithContext(customEnv, code).assert().isEmpty() - } + @AfterAll + fun disposeEnvironment() { + environmentWrapper.dispose() } - } - @Nested - inner class `object use itself` { @Test - fun `call 'this'`() { + fun `has other default methods`() { val code = """ - fun interface Sam { - fun foo() - } - - fun aa() { - object : Sam { + import com.example.fromjava.SamWithDefaultMethods + + fun main() { + val x = object : SamWithDefaultMethods { override fun foo() { - this + println() } } - } + } """ - subject.compileAndLintWithContext(env, code).assert().isEmpty() + + subject.lintWithContext(customEnv, code).assert().hasSize(1) } @Test - fun `use 'this'`() { + fun `has only default methods`() { val code = """ - fun interface Sam { - fun foo() - } - - fun Sam.bar() {} - - fun aa() { - object : Sam { - override fun foo() { - bar() - } + import com.example.fromjava.OnlyDefaultMethods + + fun main() { + val x = object : OnlyDefaultMethods { } - } + } """ - subject.compileAndLintWithContext(env, code).assert().isEmpty() + subject.lintWithContext(customEnv, code).assert().isEmpty() } @Test - fun `use class method`() { + fun `implements a default method`() { val code = """ - fun interface Sam { - fun foo() - } - - fun aa() { - object : Sam { + import com.example.fromjava.OnlyDefaultMethods + + fun main() { + val x = object : OnlyDefaultMethods { override fun foo() { - hashCode() + println() } } - } + } """ - subject.compileAndLintWithContext(env, code).assert().isEmpty() + subject.lintWithContext(customEnv, code).assert().isEmpty() } + } + } - @Test - fun `call 'this' inside nested object`() { - val code = """ - fun interface Sam { - fun foo() + @Nested + inner class `object use itself` { + @Test + fun `call 'this'`() { + val code = """ + fun interface Sam { + fun foo() + } + + fun aa() { + object : Sam { + override fun foo() { + this + } } - - fun aa() { - object : Sam { - override fun foo() { - object : Sam { - override fun foo() { - this - } - } - } + } + """ + subject.compileAndLintWithContext(env, code).assert().isEmpty() + } + + @Test + fun `use 'this'`() { + val code = """ + fun interface Sam { + fun foo() + } + + fun Sam.bar() {} + + fun aa() { + object : Sam { + override fun foo() { + bar() } } - """ - subject.compileAndLintWithContext(env, code) - .assert() - .hasSize(1) - .hasSourceLocations(SourceLocation(6, 5)) } + """ + subject.compileAndLintWithContext(env, code).assert().isEmpty() + } - @Test - fun `call labeled 'this'`() { - val code = """ - fun interface Sam { - fun foo() + @Test + fun `use class method`() { + val code = """ + fun interface Sam { + fun foo() + } + + fun aa() { + object : Sam { + override fun foo() { + hashCode() + } } - - class Target { - init { + } + """ + subject.compileAndLintWithContext(env, code).assert().isEmpty() + } + + @Test + fun `call 'this' inside nested object`() { + val code = """ + fun interface Sam { + fun foo() + } + + fun aa() { + object : Sam { + override fun foo() { object : Sam { override fun foo() { - this@Target + this } } } } - """ - subject.compileAndLintWithContext(env, code) - .assert() - .hasSize(1) - .hasSourceLocations(SourceLocation(7, 9)) } + """ + subject.compileAndLintWithContext(env, code) + .assert() + .hasSize(1) + .hasSourceLocations(SourceLocation(6, 5)) + } - @Test - fun `recursive call`() { - val code = """ - fun interface Sam { - fun foo() - } - - fun a() { + @Test + fun `call labeled 'this'`() { + val code = """ + fun interface Sam { + fun foo() + } + + class Target { + init { object : Sam { override fun foo() { - foo() + this@Target } } } - """ - subject.compileAndLintWithContext(env, code).assert().isEmpty() } + """ + subject.compileAndLintWithContext(env, code) + .assert() + .hasSize(1) + .hasSourceLocations(SourceLocation(7, 9)) } - @Nested - inner class `Edge case` { - // https://github.com/detekt/detekt/pull/3599#issuecomment-806389701 - @Test - fun `Anonymous objects are always newly created, but lambdas are singletons, so they have the same reference`() { - val code = """ - fun interface Sam { - fun foo() - } - - fun newObject() = object : Sam { + @Test + fun `recursive call`() { + val code = """ + fun interface Sam { + fun foo() + } + + fun a() { + object : Sam { override fun foo() { + foo() } } - - fun lambda() = Sam {} + } + """ + subject.compileAndLintWithContext(env, code).assert().isEmpty() + } + } - val a = newObject() === newObject() // false - val b = lambda() === lambda() // true - """ - subject.compileAndLintWithContext(env, code) - .assert() - .hasSize(1) - .hasSourceLocations(SourceLocation(5, 19)) + @Nested + inner class `Edge case` { + // https://github.com/detekt/detekt/pull/3599#issuecomment-806389701 + @Test + fun `Anonymous objects are always newly created, but lambdas are singletons, so they have the same reference`() { + val code = """ + fun interface Sam { + fun foo() } + + fun newObject() = object : Sam { + override fun foo() { + } + } + + fun lambda() = Sam {} + + val a = newObject() === newObject() // false + val b = lambda() === lambda() // true + """ + subject.compileAndLintWithContext(env, code) + .assert() + .hasSize(1) + .hasSourceLocations(SourceLocation(5, 19)) } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/OptionalAbstractKeywordSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/OptionalAbstractKeywordSpec.kt index 56b6b91bf7c..aa07be11e84 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/OptionalAbstractKeywordSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/OptionalAbstractKeywordSpec.kt @@ -2,64 +2,59 @@ package io.gitlab.arturbosch.detekt.rules.style import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class OptionalAbstractKeywordSpec { val subject = OptionalAbstractKeyword() - @Nested - inner class `some abstract keyword definitions are checked for optionality` { - - @Test - fun `does not report abstract keywords on an interface`() { - val code = "interface A {}" - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report abstract keywords on an interface`() { + val code = "interface A {}" + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports abstract interface with abstract property`() { - val code = "abstract interface A { abstract var x: Int }" - assertThat(subject.compileAndLint(code)).hasSize(2) - } + @Test + fun `reports abstract interface with abstract property`() { + val code = "abstract interface A { abstract var x: Int }" + assertThat(subject.compileAndLint(code)).hasSize(2) + } - @Test - fun `reports abstract interface with abstract function`() { - val code = "abstract interface A { abstract fun x() }" - val findings = subject.compileAndLint(code) + @Test + fun `reports abstract interface with abstract function`() { + val code = "abstract interface A { abstract fun x() }" + val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(2) - assertThat(findings).hasTextLocations(0 to 8, 23 to 31) - } + assertThat(findings).hasSize(2) + assertThat(findings).hasTextLocations(0 to 8, 23 to 31) + } - @Test - fun `reports nested abstract interface`() { - val code = """ - class A { - abstract interface B { - abstract fun x() - } + @Test + fun `reports nested abstract interface`() { + val code = """ + class A { + abstract interface B { + abstract fun x() } - """ - assertThat(subject.compileAndLint(code)).hasSize(2) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(2) + } - @Test - fun `does not report an abstract class`() { - val code = "abstract class A { abstract fun x() }" - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report an abstract class`() { + val code = "abstract class A { abstract fun x() }" + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report a nested abstract class function`() { - val code = """ - interface I { - abstract class A { - abstract fun dependency() - } + @Test + fun `does not report a nested abstract class function`() { + val code = """ + interface I { + abstract class A { + abstract fun dependency() } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/OptionalWhenBracesSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/OptionalWhenBracesSpec.kt index ab7d7bff909..05991eed958 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/OptionalWhenBracesSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/OptionalWhenBracesSpec.kt @@ -9,117 +9,113 @@ import org.junit.jupiter.api.Test class OptionalWhenBracesSpec { val subject = OptionalWhenBraces() - @Nested - inner class `check optional braces in when expression` { + @Test + fun `does not report necessary braces`() { + val code = """ + fun x() { + when (1) { + 1 -> print(1) + 2 -> { + print(2) + print(2) + } + else -> { + // a comment + println() + } + } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report necessary braces`() { - val code = """ - fun x() { - when (1) { - 1 -> print(1) - 2 -> { - print(2) - print(2) - } - else -> { - // a comment - println() + @Test + fun `reports unnecessary braces`() { + val code = """ + fun x() { + when (1) { + 1 -> { print(1) } + else -> println() + } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } + + @Test + fun `reports unnecessary braces for nested when`() { + val code = """ + import kotlin.random.Random + + fun main() { + when(Random.nextBoolean()) { + true -> { + when(Random.nextBoolean()) { + true -> { + println("true") + } + false -> { + println("false") + } } + println("end") } + false -> println("false") } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)) + .hasSize(2) + .hasSourceLocations(SourceLocation(7, 17), SourceLocation(10, 17)) + } - @Test - fun `reports unnecessary braces`() { - val code = """ - fun x() { - when (1) { - 1 -> { print(1) } - else -> println() + @Test + fun `reports unnecessary braces when the single statement has comments inside`() { + val code = """ + fun test(i: Int) { + when { + else -> { + when (i) { + // foo + 1 -> println(1) + // bar + else -> println(2) + } } } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)) + .hasSize(1) + .hasSourceLocations(SourceLocation(3, 9)) + } + @Nested + inner class `the statement is a lambda expression` { @Test - fun `reports unnecessary braces for nested when`() { + fun `does not report if the lambda has no arrow`() { val code = """ - import kotlin.random.Random - - fun main() { - when(Random.nextBoolean()) { - true -> { - when(Random.nextBoolean()) { - true -> { - println("true") - } - false -> { - println("false") - } - } - println("end") - } - false -> println("false") + fun test(b: Boolean): (Int) -> Int { + return when (b) { + true -> { { it + 100 } } + false -> { { it + 200 } } } } """ - assertThat(subject.compileAndLint(code)) - .hasSize(2) - .hasSourceLocations(SourceLocation(7, 17), SourceLocation(10, 17)) + assertThat(subject.compileAndLint(code)).isEmpty() } @Test - fun `reports unnecessary braces when the single statement has comments inside`() { + fun `reports if the lambda has an arrow`() { val code = """ - fun test(i: Int) { - when { - else -> { - when (i) { - // foo - 1 -> println(1) - // bar - else -> println(2) - } - } + fun test(b: Boolean): (Int) -> Int { + return when (b) { + true -> { { i -> i + 100 } } + false -> { { i -> i + 200 } } } } """ - assertThat(subject.compileAndLint(code)) - .hasSize(1) - .hasSourceLocations(SourceLocation(3, 9)) - } - - @Nested - inner class `the statement is a lambda expression` { - @Test - fun `does not report if the lambda has no arrow`() { - val code = """ - fun test(b: Boolean): (Int) -> Int { - return when (b) { - true -> { { it + 100 } } - false -> { { it + 200 } } - } - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `reports if the lambda has an arrow`() { - val code = """ - fun test(b: Boolean): (Int) -> Int { - return when (b) { - true -> { { i -> i + 100 } } - false -> { { i -> i + 200 } } - } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(2) - } + assertThat(subject.compileAndLint(code)).hasSize(2) } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/RedundantExplicitTypeSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/RedundantExplicitTypeSpec.kt index ce05311193a..5efcd83d052 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/RedundantExplicitTypeSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/RedundantExplicitTypeSpec.kt @@ -5,130 +5,125 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class RedundantExplicitTypeSpec(val env: KotlinCoreEnvironment) { val subject = RedundantExplicitType(Config.empty) - @Nested - inner class `RedundantExplicitType` { - - @Test - fun `reports explicit type for boolean`() { - val code = """ - fun function() { - val x: Boolean = true - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `reports explicit type for integer`() { - val code = """ - fun function() { - val x: Int = 3 - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `reports explicit type for long`() { - val code = """ - fun function() { - val x: Long = 3L - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `reports explicit type for float`() { - val code = """ - fun function() { - val x: Float = 3.0f - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `reports explicit type for double`() { - val code = """ - fun function() { - val x: Double = 3.0 - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `reports explicit type for char`() { - val code = """ - fun function() { - val x: Char = 'f' - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `reports explicit type for string template`() { - val substitute = "\$x" - val code = """ - fun function() { - val x = 3 - val y: String = "$substitute" - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `reports explicit type for name reference expression`() { - val code = """ - object Test - - fun foo() { - val o: Test = Test - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `reports explicit type for call expression`() { - val code = """ - interface Person { - val firstName: String - } - - class TallPerson(override val firstName: String, val height: Int): Person - - fun tallPerson() { - val t: TallPerson = TallPerson("first", 3) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `does not report explicit type for call expression when type is an interface`() { - val code = """ - interface Person { - val firstName: String - } - - class TallPerson(override val firstName: String, val height: Int): Person - - fun tallPerson() { - val t: Person = TallPerson("first", 3) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `reports explicit type for boolean`() { + val code = """ + fun function() { + val x: Boolean = true + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } + + @Test + fun `reports explicit type for integer`() { + val code = """ + fun function() { + val x: Int = 3 + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } + + @Test + fun `reports explicit type for long`() { + val code = """ + fun function() { + val x: Long = 3L + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } + + @Test + fun `reports explicit type for float`() { + val code = """ + fun function() { + val x: Float = 3.0f + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } + + @Test + fun `reports explicit type for double`() { + val code = """ + fun function() { + val x: Double = 3.0 + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } + + @Test + fun `reports explicit type for char`() { + val code = """ + fun function() { + val x: Char = 'f' + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } + + @Test + fun `reports explicit type for string template`() { + val substitute = "\$x" + val code = """ + fun function() { + val x = 3 + val y: String = "$substitute" + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } + + @Test + fun `reports explicit type for name reference expression`() { + val code = """ + object Test + + fun foo() { + val o: Test = Test + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } + + @Test + fun `reports explicit type for call expression`() { + val code = """ + interface Person { + val firstName: String + } + + class TallPerson(override val firstName: String, val height: Int): Person + + fun tallPerson() { + val t: TallPerson = TallPerson("first", 3) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } + + @Test + fun `does not report explicit type for call expression when type is an interface`() { + val code = """ + interface Person { + val firstName: String + } + + class TallPerson(override val firstName: String, val height: Int): Person + + fun tallPerson() { + val t: Person = TallPerson("first", 3) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/RedundantVisibilityModifierRuleSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/RedundantVisibilityModifierRuleSpec.kt index a766e930bfa..db47e1bcd10 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/RedundantVisibilityModifierRuleSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/RedundantVisibilityModifierRuleSpec.kt @@ -16,210 +16,207 @@ import org.junit.jupiter.api.Test class RedundantVisibilityModifierRuleSpec { val subject = RedundantVisibilityModifierRule() - @Nested - inner class `RedundantVisibilityModifier rule` { - @Test - fun `does not report overridden function of abstract class with public modifier`() { - val code = """ - abstract class A { - abstract protected fun f() - } + @Test + fun `does not report overridden function of abstract class with public modifier`() { + val code = """ + abstract class A { + abstract protected fun f() + } - class Test : A() { - override public fun f() {} - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + class Test : A() { + override public fun f() {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report overridden function of abstract class without public modifier`() { - val code = """ - abstract class A { - abstract protected fun f() - } + @Test + fun `does not report overridden function of abstract class without public modifier`() { + val code = """ + abstract class A { + abstract protected fun f() + } - class Test : A() { - override fun f() {} - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + class Test : A() { + override fun f() {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report overridden function of interface`() { - val code = """ - interface A { - fun f() - } + @Test + fun `does not report overridden function of interface`() { + val code = """ + interface A { + fun f() + } - class Test : A { - override public fun f() {} - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + class Test : A { + override public fun f() {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `should ignore the issue by alias suppression`() { - val code = """ - class Test { - @Suppress("RedundantVisibilityModifier") - public fun f() {} - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `should ignore the issue by alias suppression`() { + val code = """ + class Test { + @Suppress("RedundantVisibilityModifier") + public fun f() {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports public function in class`() { - val code = """ - class Test { - public fun f() {} - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports public function in class`() { + val code = """ + class Test { + public fun f() {} + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report function in class without modifier`() { - val code = """ - class Test { - fun f() {} - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report function in class without modifier`() { + val code = """ + class Test { + fun f() {} + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports public class`() { - val code = """ - public class Test { - fun f() {} - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports public class`() { + val code = """ + public class Test { + fun f() {} + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports interface with public modifier`() { - val code = """ - public interface Test { - public fun f() - } - """ - assertThat(subject.compileAndLint(code)).hasSize(2) - } + @Test + fun `reports interface with public modifier`() { + val code = """ + public interface Test { + public fun f() + } + """ + assertThat(subject.compileAndLint(code)).hasSize(2) + } - @Test - fun `reports field with public modifier`() { - val code = """ - class Test { - public val str : String = "test" - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports field with public modifier`() { + val code = """ + class Test { + public val str : String = "test" + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report field without public modifier`() { - val code = """ - class Test { - val str : String = "test" - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report field without public modifier`() { + val code = """ + class Test { + val str : String = "test" + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report overridden field without public modifier`() { - val code = """ - abstract class A { - abstract val test: String - } + @Test + fun `does not report overridden field without public modifier`() { + val code = """ + abstract class A { + abstract val test: String + } - class B : A() { - override val test: String = "valid" - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + class B : A() { + override val test: String = "valid" + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report overridden field with public modifier`() { - val code = """ - abstract class A { - abstract val test: String - } + @Test + fun `does not report overridden field with public modifier`() { + val code = """ + abstract class A { + abstract val test: String + } - class B : A() { - override public val test: String = "valid" - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + class B : A() { + override public val test: String = "valid" + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports internal modifier on nested class in private object`() { - val code = """ - private object A { - internal class InternalClass - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports internal modifier on nested class in private object`() { + val code = """ + private object A { + internal class InternalClass + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports internal modifier on function declaration in private object`() { - val code = """ - private object A { - internal fun internalFunction() {} - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `reports internal modifier on function declaration in private object`() { + val code = """ + private object A { + internal fun internalFunction() {} + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Nested - inner class `Explicit API mode` { + @Nested + inner class `Explicit API mode` { - val code = - compileContentForTest( - """ - public class A() { - fun f() - } - """ - ) + val code = + compileContentForTest( + """ + public class A() { + fun f() + } + """ + ) - val rule = RedundantVisibilityModifierRule() + val rule = RedundantVisibilityModifierRule() - fun mockCompilerResources(mode: ExplicitApiMode): CompilerResources { - val languageVersionSettings = mockk() - every { - hint(ExplicitApiMode::class) - languageVersionSettings.getFlag(AnalysisFlags.explicitApiMode) - } returns mode - @Suppress("DEPRECATION") - return CompilerResources(languageVersionSettings, DataFlowValueFactoryImpl(languageVersionSettings)) - } + private fun mockCompilerResources(mode: ExplicitApiMode): CompilerResources { + val languageVersionSettings = mockk() + every { + hint(ExplicitApiMode::class) + languageVersionSettings.getFlag(AnalysisFlags.explicitApiMode) + } returns mode + @Suppress("DEPRECATION") + return CompilerResources(languageVersionSettings, DataFlowValueFactoryImpl(languageVersionSettings)) + } - @Test - fun `does not report public function in class if explicit API mode is set to strict`() { - rule.visitFile(code, compilerResources = mockCompilerResources(ExplicitApiMode.STRICT)) - assertThat(rule.findings).isEmpty() - } + @Test + fun `does not report public function in class if explicit API mode is set to strict`() { + rule.visitFile(code, compilerResources = mockCompilerResources(ExplicitApiMode.STRICT)) + assertThat(rule.findings).isEmpty() + } - @Test - fun `reports public function in class if explicit API mode is disabled`() { - rule.visitFile(code, compilerResources = mockCompilerResources(ExplicitApiMode.DISABLED)) - assertThat(rule.findings).hasSize(1) - } + @Test + fun `reports public function in class if explicit API mode is disabled`() { + rule.visitFile(code, compilerResources = mockCompilerResources(ExplicitApiMode.DISABLED)) + assertThat(rule.findings).hasSize(1) + } - @Test - fun `reports public function in class if compiler resources are not available`() { - rule.visitFile(code, compilerResources = null) - assertThat(rule.findings).hasSize(1) - } + @Test + fun `reports public function in class if compiler resources are not available`() { + rule.visitFile(code, compilerResources = null) + assertThat(rule.findings).hasSize(1) } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ReturnCountSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ReturnCountSpec.kt index 5eea28c0428..9abd3b37a9b 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ReturnCountSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ReturnCountSpec.kt @@ -17,490 +17,486 @@ private const val EXCLUDE_GUARD_CLAUSES = "excludeGuardClauses" class ReturnCountSpec { @Nested - inner class `ReturnCount rule` { - - @Nested - inner class `a function without a body` { - val code = """ - fun func() = Unit - """ - - @Test - fun `does not report violation by default`() { - assertThat(ReturnCount(Config.empty).compileAndLint(code)).isEmpty() - } + inner class `a function without a body` { + val code = """ + fun func() = Unit + """ + + @Test + fun `does not report violation by default`() { + assertThat(ReturnCount(Config.empty).compileAndLint(code)).isEmpty() } + } - @Nested - inner class `a function with an empty body` { - val code = """ - fun func() {} - """ - - @Test - fun `does not report violation by default`() { - assertThat(ReturnCount(Config.empty).compileAndLint(code)).isEmpty() - } + @Nested + inner class `a function with an empty body` { + val code = """ + fun func() {} + """ + + @Test + fun `does not report violation by default`() { + assertThat(ReturnCount(Config.empty).compileAndLint(code)).isEmpty() } + } - @Nested - inner class `a file with an if condition guard clause and 2 returns` { - val code = """ - fun test(x: Int): Int { - if (x < 4) return 0 - when (x) { - 5 -> println("x=5") - 4 -> return 4 - } - return 6 - } - """ + @Nested + inner class `a file with an if condition guard clause and 2 returns` { + val code = """ + fun test(x: Int): Int { + if (x < 4) return 0 + when (x) { + 5 -> println("x=5") + 4 -> return 4 + } + return 6 + } + """ - @Test - fun `should not get flagged for if condition guard clauses`() { - val findings = ReturnCount(TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true"))) - .compileAndLint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not get flagged for if condition guard clauses`() { + val findings = ReturnCount(TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true"))) + .compileAndLint(code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `a file with an if condition guard clause with body and 2 returns` { - val code = """ - fun test(x: Int): Int { - if (x < 4) { - println("x x is less than 4") - return 0 - } - when (x) { - 5 -> println("x=5") - 4 -> return 4 - } - return 6 - } - """ + @Nested + inner class `a file with an if condition guard clause with body and 2 returns` { + val code = """ + fun test(x: Int): Int { + if (x < 4) { + println("x x is less than 4") + return 0 + } + when (x) { + 5 -> println("x=5") + 4 -> return 4 + } + return 6 + } + """ - @Test - fun `should not get flagged for if condition guard clauses`() { - val findings = ReturnCount(TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true"))) - .compileAndLint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not get flagged for if condition guard clauses`() { + val findings = ReturnCount(TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true"))) + .compileAndLint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should get flagged without guard clauses`() { - val findings = ReturnCount(TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "false"))) - .compileAndLint(code) - assertThat(findings).hasSize(1) - } + @Test + fun `should get flagged without guard clauses`() { + val findings = ReturnCount(TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "false"))) + .compileAndLint(code) + assertThat(findings).hasSize(1) } + } - @Nested - inner class `reports a too-complicated if statement for being a guard clause` { - val code = """ - fun test(x: Int): Int { - if (x < 4) { - println("x x is less than 4") - if (x < 2) { - println("x is also less than 2") - return 1 - } - return 0 - } - when (x) { - 5 -> println("x=5") - 4 -> return 4 + @Nested + inner class `reports a too-complicated if statement for being a guard clause` { + val code = """ + fun test(x: Int): Int { + if (x < 4) { + println("x x is less than 4") + if (x < 2) { + println("x is also less than 2") + return 1 } - return 6 + return 0 } - """ - - @Test - fun `should report a too-complicated if statement for being a guard clause, with EXCLUDE_GUARD_CLAUSES on`() { - val findings = ReturnCount(TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true"))) - .compileAndLint(code) - assertThat(findings).hasSize(1) + when (x) { + 5 -> println("x=5") + 4 -> return 4 } + return 6 } + """ - @Nested - inner class `a file with an ELVIS operator guard clause and 2 returns` { - val code = """ - fun test(x: Int): Int { - val y = x ?: return 0 - when (x) { - 5 -> println("x=5") - 4 -> return 4 - } - return 6 - } - """ + @Test + fun `should report a too-complicated if statement for being a guard clause, with EXCLUDE_GUARD_CLAUSES on`() { + val findings = ReturnCount(TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true"))) + .compileAndLint(code) + assertThat(findings).hasSize(1) + } + } - @Test - fun `should not get flagged for ELVIS operator guard clauses`() { - val findings = ReturnCount(TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true"))) - .compileAndLint(code) - assertThat(findings).isEmpty() - } + @Nested + inner class `a file with an ELVIS operator guard clause and 2 returns` { + val code = """ + fun test(x: Int): Int { + val y = x ?: return 0 + when (x) { + 5 -> println("x=5") + 4 -> return 4 + } + return 6 } + """ - @Nested - inner class `a file with 2 returns and an if condition guard clause which is not the first statement` { - val code = """ - fun test(x: Int): Int { - when (x) { - 5 -> println("x=5") - 4 -> return 4 - } - if (x < 4) return 0 - return 6 - } - """ + @Test + fun `should not get flagged for ELVIS operator guard clauses`() { + val findings = ReturnCount(TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true"))) + .compileAndLint(code) + assertThat(findings).isEmpty() + } + } - @Test - fun `should get flagged for an if condition guard clause which is not the first statement`() { - val findings = ReturnCount(TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true"))) - .compileAndLint(code) - assertThat(findings).hasSize(1) - } + @Nested + inner class `a file with 2 returns and an if condition guard clause which is not the first statement` { + val code = """ + fun test(x: Int): Int { + when (x) { + 5 -> println("x=5") + 4 -> return 4 + } + if (x < 4) return 0 + return 6 } + """ - @Nested - inner class `a file with 2 returns and an ELVIS guard clause which is not the first statement` { - val code = """ - fun test(x: Int): Int { - when (x) { - 5 -> println("x=5") - 4 -> return 4 - } - val y = x ?: return 0 - return 6 - } - """ + @Test + fun `should get flagged for an if condition guard clause which is not the first statement`() { + val findings = ReturnCount(TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true"))) + .compileAndLint(code) + assertThat(findings).hasSize(1) + } + } - @Test - fun `should get flagged for an ELVIS guard clause which is not the first statement`() { - val findings = ReturnCount(TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true"))) - .compileAndLint(code) - assertThat(findings).hasSize(1) - } + @Nested + inner class `a file with 2 returns and an ELVIS guard clause which is not the first statement` { + val code = """ + fun test(x: Int): Int { + when (x) { + 5 -> println("x=5") + 4 -> return 4 + } + val y = x ?: return 0 + return 6 } + """ - @Nested - inner class `a file with multiple guard clauses` { - val code = """ - fun multipleGuards(a: Int?, b: Any?, c: Int?) { - if(a == null) return - val models = b as? Int ?: return - val position = c?.takeIf { it != -1 } ?: return - if(b !is String) { - println("b is not a String") - return - } + @Test + fun `should get flagged for an ELVIS guard clause which is not the first statement`() { + val findings = ReturnCount(TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true"))) + .compileAndLint(code) + assertThat(findings).hasSize(1) + } + } + @Nested + inner class `a file with multiple guard clauses` { + val code = """ + fun multipleGuards(a: Int?, b: Any?, c: Int?) { + if(a == null) return + val models = b as? Int ?: return + val position = c?.takeIf { it != -1 } ?: return + if(b !is String) { + println("b is not a String") return } - """ - @Test - fun `should not count all four guard clauses`() { - val findings = ReturnCount( - TestConfig( - EXCLUDE_GUARD_CLAUSES to "true" - ) - ).compileAndLint(code) - assertThat(findings).isEmpty() + return } + """ - @Test - fun `should count all four guard clauses`() { - val findings = ReturnCount( - TestConfig( - EXCLUDE_GUARD_CLAUSES to "false" - ) - ).compileAndLint(code) - assertThat(findings).hasSize(1) - } + @Test + fun `should not count all four guard clauses`() { + val findings = ReturnCount( + TestConfig( + EXCLUDE_GUARD_CLAUSES to "true" + ) + ).compileAndLint(code) + assertThat(findings).isEmpty() } - @Nested - inner class `a file with 3 returns` { - val code = """ - fun test(x: Int): Int { - when (x) { - 5 -> println("x=5") - 4 -> return 4 - 3 -> return 3 - } - return 6 - } - """ + @Test + fun `should count all four guard clauses`() { + val findings = ReturnCount( + TestConfig( + EXCLUDE_GUARD_CLAUSES to "false" + ) + ).compileAndLint(code) + assertThat(findings).hasSize(1) + } + } - @Test - fun `should get flagged by default`() { - val findings = ReturnCount().compileAndLint(code) - assertThat(findings).hasSize(1) - } + @Nested + inner class `a file with 3 returns` { + val code = """ + fun test(x: Int): Int { + when (x) { + 5 -> println("x=5") + 4 -> return 4 + 3 -> return 3 + } + return 6 + } + """ - @Test - fun `should not get flagged when max value is 3`() { - val findings = ReturnCount(TestConfig(mapOf(MAX to "3"))).compileAndLint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should get flagged by default`() { + val findings = ReturnCount().compileAndLint(code) + assertThat(findings).hasSize(1) + } - @Test - fun `should get flagged when max value is 1`() { - val findings = ReturnCount(TestConfig(mapOf(MAX to "1"))).compileAndLint(code) - assertThat(findings).hasSize(1) - } + @Test + fun `should not get flagged when max value is 3`() { + val findings = ReturnCount(TestConfig(mapOf(MAX to "3"))).compileAndLint(code) + assertThat(findings).isEmpty() } - @Nested - inner class `a file with 2 returns` { - val code = """ - fun test(x: Int): Int { - when (x) { - 5 -> println("x=5") - 4 -> return 4 - } - return 6 - } - """ + @Test + fun `should get flagged when max value is 1`() { + val findings = ReturnCount(TestConfig(mapOf(MAX to "1"))).compileAndLint(code) + assertThat(findings).hasSize(1) + } + } - @Test - fun `should not get flagged by default`() { - val findings = ReturnCount().compileAndLint(code) - assertThat(findings).isEmpty() - } + @Nested + inner class `a file with 2 returns` { + val code = """ + fun test(x: Int): Int { + when (x) { + 5 -> println("x=5") + 4 -> return 4 + } + return 6 + } + """ - @Test - fun `should not get flagged when max value is 2`() { - val findings = ReturnCount(TestConfig(mapOf(MAX to "2"))).compileAndLint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not get flagged by default`() { + val findings = ReturnCount().compileAndLint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should get flagged when max value is 1`() { - val findings = ReturnCount(TestConfig(mapOf(MAX to "1"))).compileAndLint(code) - assertThat(findings).hasSize(1) - } + @Test + fun `should not get flagged when max value is 2`() { + val findings = ReturnCount(TestConfig(mapOf(MAX to "2"))).compileAndLint(code) + assertThat(findings).isEmpty() } - @Nested - inner class `a function is ignored` { - val code = """ - fun test(x: Int): Int { - when (x) { - 5 -> println("x=5") - 4 -> return 4 - 3 -> return 3 - } - return 6 - } - """ - - @Test - fun `should not get flagged`() { - val findings = ReturnCount( - TestConfig( - mapOf( - MAX to "2", - EXCLUDED_FUNCTIONS to "test" - ) + @Test + fun `should get flagged when max value is 1`() { + val findings = ReturnCount(TestConfig(mapOf(MAX to "1"))).compileAndLint(code) + assertThat(findings).hasSize(1) + } + } + + @Nested + inner class `a function is ignored` { + val code = """ + fun test(x: Int): Int { + when (x) { + 5 -> println("x=5") + 4 -> return 4 + 3 -> return 3 + } + return 6 + } + """ + + @Test + fun `should not get flagged`() { + val findings = ReturnCount( + TestConfig( + mapOf( + MAX to "2", + EXCLUDED_FUNCTIONS to "test" ) - ).compileAndLint(code) - assertThat(findings).isEmpty() - } + ) + ).compileAndLint(code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `a subset of functions are ignored` { - val code = """ - fun test1(x: Int): Int { - when (x) { - 5 -> println("x=5") - 4 -> return 4 - 3 -> return 3 - } - return 6 - } + @Nested + inner class `a subset of functions are ignored` { + val code = """ + fun test1(x: Int): Int { + when (x) { + 5 -> println("x=5") + 4 -> return 4 + 3 -> return 3 + } + return 6 + } - fun test2(x: Int): Int { - when (x) { - 5 -> println("x=5") - 4 -> return 4 - 3 -> return 3 - } - return 6 + fun test2(x: Int): Int { + when (x) { + 5 -> println("x=5") + 4 -> return 4 + 3 -> return 3 } + return 6 + } - fun test3(x: Int): Int { - when (x) { - 5 -> println("x=5") - 4 -> return 4 - 3 -> return 3 - } - return 6 + fun test3(x: Int): Int { + when (x) { + 5 -> println("x=5") + 4 -> return 4 + 3 -> return 3 } - """ - - @Test - fun `should flag none of the ignored functions`() { - val findings = ReturnCount( - TestConfig( - mapOf( - MAX to "2", - EXCLUDED_FUNCTIONS to "test1,test2" - ) + return 6 + } + """ + + @Test + fun `should flag none of the ignored functions`() { + val findings = ReturnCount( + TestConfig( + mapOf( + MAX to "2", + EXCLUDED_FUNCTIONS to "test1,test2" ) - ).compileAndLint(code) - assertThat(findings).hasSize(1) - } + ) + ).compileAndLint(code) + assertThat(findings).hasSize(1) } + } - @Nested - inner class `a function with inner object` { - val code = """ - fun test(x: Int): Int { - val a = object { - fun test2(x: Int): Int { - when (x) { - 5 -> println("x=5") - else -> return 0 - } - return 6 + @Nested + inner class `a function with inner object` { + val code = """ + fun test(x: Int): Int { + val a = object { + fun test2(x: Int): Int { + when (x) { + 5 -> println("x=5") + else -> return 0 } + return 6 } - when (x) { - 5 -> println("x=5") - else -> return 0 - } - return 6 } - """ - - @Test - fun `should not get flag when returns is in inner object`() { - val findings = ReturnCount(TestConfig(mapOf(MAX to "2"))).compileAndLint(code) - assertThat(findings).isEmpty() + when (x) { + 5 -> println("x=5") + else -> return 0 } + return 6 + } + """ + + @Test + fun `should not get flag when returns is in inner object`() { + val findings = ReturnCount(TestConfig(mapOf(MAX to "2"))).compileAndLint(code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `a function with 2 inner object` { - val code = """ - fun test(x: Int): Int { - val a = object { - fun test2(x: Int): Int { - val b = object { - fun test3(x: Int): Int { - when (x) { - 5 -> println("x=5") - else -> return 0 - } - return 6 + @Nested + inner class `a function with 2 inner object` { + val code = """ + fun test(x: Int): Int { + val a = object { + fun test2(x: Int): Int { + val b = object { + fun test3(x: Int): Int { + when (x) { + 5 -> println("x=5") + else -> return 0 } + return 6 } - when (x) { - 5 -> println("x=5") - else -> return 0 - } - return 6 } + when (x) { + 5 -> println("x=5") + else -> return 0 + } + return 6 } - when (x) { - 5 -> println("x=5") - else -> return 0 - } - return 6 } - """ - - @Test - fun `should not get flag when returns is in inner object`() { - val findings = ReturnCount(TestConfig(mapOf(MAX to "2"))).compileAndLint(code) - assertThat(findings).isEmpty() + when (x) { + 5 -> println("x=5") + else -> return 0 } + return 6 } + """ - @Nested - inner class `a function with 2 inner object and exceeded max` { - val code = """ - fun test(x: Int): Int { - val a = object { - fun test2(x: Int): Int { - val b = object { - fun test3(x: Int): Int { - when (x) { - 5 -> println("x=5") - else -> return 0 - } - return 6 + @Test + fun `should not get flag when returns is in inner object`() { + val findings = ReturnCount(TestConfig(mapOf(MAX to "2"))).compileAndLint(code) + assertThat(findings).isEmpty() + } + } + + @Nested + inner class `a function with 2 inner object and exceeded max` { + val code = """ + fun test(x: Int): Int { + val a = object { + fun test2(x: Int): Int { + val b = object { + fun test3(x: Int): Int { + when (x) { + 5 -> println("x=5") + else -> return 0 } + return 6 } - when (x) { - 5 -> println("x=5") - else -> return 0 - } - return 6 } + when (x) { + 5 -> println("x=5") + else -> return 0 + } + return 6 } - when (x) { - 5 -> println("x=5") - 4 -> return 4 - 3 -> return 3 - else -> return 0 - } - return 6 } - """ - - @Test - fun `should get flagged when returns is in inner object`() { - val findings = ReturnCount(TestConfig(mapOf(MAX to "2"))).compileAndLint(code) - assertThat(findings).hasSize(1) + when (x) { + 5 -> println("x=5") + 4 -> return 4 + 3 -> return 3 + else -> return 0 } + return 6 } + """ - @Nested - inner class `function with multiple labeled return statements` { + @Test + fun `should get flagged when returns is in inner object`() { + val findings = ReturnCount(TestConfig(mapOf(MAX to "2"))).compileAndLint(code) + assertThat(findings).hasSize(1) + } + } - val code = """ - fun readUsers(name: String): Flowable { - return userDao.read(name) - .flatMap { - if (it.isEmpty()) return@flatMap Flowable.empty() - return@flatMap Flowable.just(it[0]) - } - } - """ + @Nested + inner class `function with multiple labeled return statements` { - @Test - fun `should not count labeled returns from lambda by default`() { - val findings = ReturnCount().lint(code) - assertThat(findings).isEmpty() + val code = """ + fun readUsers(name: String): Flowable { + return userDao.read(name) + .flatMap { + if (it.isEmpty()) return@flatMap Flowable.empty() + return@flatMap Flowable.just(it[0]) } + } + """ - @Test - fun `should count labeled returns from lambda when activated`() { - val findings = ReturnCount( - TestConfig(mapOf(EXCLUDE_RETURN_FROM_LAMBDA to "false")) - ).lint(code) - assertThat(findings).hasSize(1) - } + @Test + fun `should not count labeled returns from lambda by default`() { + val findings = ReturnCount().lint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should be empty when labeled returns are de-activated`() { - val findings = ReturnCount( - TestConfig( - mapOf( - EXCLUDE_LABELED to "true", - EXCLUDE_RETURN_FROM_LAMBDA to "false" - ) + @Test + fun `should count labeled returns from lambda when activated`() { + val findings = ReturnCount( + TestConfig(mapOf(EXCLUDE_RETURN_FROM_LAMBDA to "false")) + ).lint(code) + assertThat(findings).hasSize(1) + } + + @Test + fun `should be empty when labeled returns are de-activated`() { + val findings = ReturnCount( + TestConfig( + mapOf( + EXCLUDE_LABELED to "true", + EXCLUDE_RETURN_FROM_LAMBDA to "false" ) - ).lint(code) - assertThat(findings).isEmpty() - } + ) + ).lint(code) + assertThat(findings).isEmpty() } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/SafeCastSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/SafeCastSpec.kt index 03b0baa2b9c..d0e707bd513 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/SafeCastSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/SafeCastSpec.kt @@ -2,70 +2,65 @@ package io.gitlab.arturbosch.detekt.rules.style import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class SafeCastSpec { val subject = SafeCast() - @Nested - inner class `SafeCast rule` { - - @Test - fun `reports negated expression`() { - val code = """ - fun test(element: Int) { - val cast = if (element !is Number) { - null - } else { - element - } + @Test + fun `reports negated expression`() { + val code = """ + fun test(element: Int) { + val cast = if (element !is Number) { + null + } else { + element } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports expression`() { - val code = """ - fun test(element: Int) { - val cast = if (element is Number) { - element - } else { - null - } + @Test + fun `reports expression`() { + val code = """ + fun test(element: Int) { + val cast = if (element is Number) { + element + } else { + null } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report wrong condition`() { - val code = """ - fun test(element: Int) { - val other = 3 - val cast = if (element == other) { - element - } else { - null - } + @Test + fun `does not report wrong condition`() { + val code = """ + fun test(element: Int) { + val other = 3 + val cast = if (element == other) { + element + } else { + null } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report wrong else clause`() { - val code = """ - fun test(element: Int) { - val cast = if (element is Number) { - element - } else { - String() - } + @Test + fun `does not report wrong else clause`() { + val code = """ + fun test(element: Int) { + val cast = if (element is Number) { + element + } else { + String() } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/SerialVersionUIDInSerializableClassSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/SerialVersionUIDInSerializableClassSpec.kt index 7950e5be07e..11709ca0e33 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/SerialVersionUIDInSerializableClassSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/SerialVersionUIDInSerializableClassSpec.kt @@ -3,127 +3,122 @@ package io.gitlab.arturbosch.detekt.rules.style import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class SerialVersionUIDInSerializableClassSpec { val subject = SerialVersionUIDInSerializableClass(Config.empty) - @Nested - inner class `SerialVersionUIDInSerializableClass rule` { + @Test + fun `reports class with no serialVersionUID`() { + val code = """ + import java.io.Serializable - @Test - fun `reports class with no serialVersionUID`() { - val code = """ - import java.io.Serializable + class C : Serializable + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } + + @Test + fun `reports class with wrong datatype`() { + val code = """ + import java.io.Serializable - class C : Serializable - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + class C : Serializable { + companion object { + const val serialVersionUID = 1 + } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `reports class with wrong datatype`() { - val code = """ - import java.io.Serializable + @Test + fun `reports class with wrong explicitly defined datatype`() { + val code = """ + import java.io.Serializable - class C : Serializable { - companion object { - const val serialVersionUID = 1 - } + class C : Serializable { + companion object { + const val serialVersionUID: Int = 1 } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `reports class with wrong explicitly defined datatype`() { - val code = """ - import java.io.Serializable - - class C : Serializable { - companion object { - const val serialVersionUID: Int = 1 - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } + + @Test + fun `reports class with wrong naming and without const modifier`() { + val code = """ + import java.io.Serializable + + class C : Serializable { + companion object { + const val serialVersionUUID = 1L } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } - - @Test - fun `reports class with wrong naming and without const modifier`() { - val code = """ - import java.io.Serializable - - class C : Serializable { - companion object { - const val serialVersionUUID = 1L - } - - object NestedIncorrectSerialVersionUID : Serializable { - val serialVersionUUID = 1L - } + + object NestedIncorrectSerialVersionUID : Serializable { + val serialVersionUUID = 1L } - """ - assertThat(subject.compileAndLint(code)).hasSize(2) - } - - @Test - fun `does not report a unserializable class`() { - val code = "class NoSerializableClass" - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report an interface that implements Serializable`() { - val code = """ - import java.io.Serializable - - interface I : Serializable - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report UID constant with positive value`() { - val code = """ - import java.io.Serializable - - class C : Serializable { - companion object { - const val serialVersionUID = 1L - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(2) + } + + @Test + fun `does not report a unserializable class`() { + val code = "class NoSerializableClass" + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report an interface that implements Serializable`() { + val code = """ + import java.io.Serializable + + interface I : Serializable + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report UID constant with positive value`() { + val code = """ + import java.io.Serializable + + class C : Serializable { + companion object { + const val serialVersionUID = 1L } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report UID constant with negative value`() { - val code = """ - import java.io.Serializable - - class C : Serializable { - companion object { - const val serialVersionUID = -1L - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report UID constant with negative value`() { + val code = """ + import java.io.Serializable + + class C : Serializable { + companion object { + const val serialVersionUID = -1L } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report UID constant with explicit Long type`() { - val code = """ - import java.io.Serializable - - class C : Serializable { - companion object { - const val serialVersionUID: Long = 1 - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report UID constant with explicit Long type`() { + val code = """ + import java.io.Serializable + + class C : Serializable { + companion object { + const val serialVersionUID: Long = 1 } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/SpacingBetweenPackageAndImportsSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/SpacingBetweenPackageAndImportsSpec.kt index 8bdac35d149..21221a2d03c 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/SpacingBetweenPackageAndImportsSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/SpacingBetweenPackageAndImportsSpec.kt @@ -11,121 +11,117 @@ import org.junit.jupiter.api.Test class SpacingBetweenPackageAndImportsSpec { val subject = SpacingBetweenPackageAndImports(Config.empty) - @Nested - inner class `SpacingBetweenPackageAndImports rule` { + @Test + fun `has no blank lines violation`() { + val code = "package test\n\nimport a.b\n\nclass A {}" + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `has no blank lines violation`() { - val code = "package test\n\nimport a.b\n\nclass A {}" - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `has a package and import declaration`() { + val code = "package test\n\nimport a.b" + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `has a package and import declaration`() { - val code = "package test\n\nimport a.b" - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `has no import declaration`() { + val code = "package test\n\nclass A {}" + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `has no import declaration`() { - val code = "package test\n\nclass A {}" - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `has no package declaration`() { + val code = "import a.b\n\nclass A {}" + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `has no package declaration`() { - val code = "import a.b\n\nclass A {}" - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `has no package and import declaration`() { + val code = "class A {}" + assertThat(subject.lint(code)).isEmpty() + } + + @Test + fun `has a comment declaration`() { + val code = "import a.b\n\n// a comment" + assertThat(subject.lint(code)).isEmpty() + } + + @Test + fun `is an empty kt file`() { + assertThat(subject.lint("")).isEmpty() + } + + @Nested + inner class `Kotlin scripts` { @Test - fun `has no package and import declaration`() { - val code = "class A {}" - assertThat(subject.lint(code)).isEmpty() + fun `has no package declaration in script`() { + val code = "import a.b\n\nprint(1)" + val ktsFile = compileContentForTest(code, "Test.kts") + assertThat(subject.lint(ktsFile)).isEmpty() } @Test - fun `has a comment declaration`() { - val code = "import a.b\n\n// a comment" - assertThat(subject.lint(code)).isEmpty() + fun `has no package and import declaration in script`() { + val code = "print(1)" + val ktsFile = compileContentForTest(code, "Test.kts") + assertThat(subject.lint(ktsFile)).isEmpty() } @Test - fun `is an empty kt file`() { - assertThat(subject.lint("")).isEmpty() + fun `has import declarations separated by new line in script`() { + val code = "import a.b\n\nimport a.c\n\nprint(1)" + val ktsFile = compileContentForTest(code, "Test.kts") + assertThat(subject.lint(ktsFile)).isEmpty() } + } - @Nested - inner class `Kotlin scripts` { - - @Test - fun `has no package declaration in script`() { - val code = "import a.b\n\nprint(1)" - val ktsFile = compileContentForTest(code, "Test.kts") - assertThat(subject.lint(ktsFile)).isEmpty() - } - - @Test - fun `has no package and import declaration in script`() { - val code = "print(1)" - val ktsFile = compileContentForTest(code, "Test.kts") - assertThat(subject.lint(ktsFile)).isEmpty() - } - - @Test - fun `has import declarations separated by new line in script`() { - val code = "import a.b\n\nimport a.c\n\nprint(1)" - val ktsFile = compileContentForTest(code, "Test.kts") - assertThat(subject.lint(ktsFile)).isEmpty() - } - } + @Test + fun `has code on new line`() { + val code = "package test\nimport a.b\nclass A {}" + assertThat(subject.lint(code)).hasSize(2) + } - @Test - fun `has code on new line`() { - val code = "package test\nimport a.b\nclass A {}" - assertThat(subject.lint(code)).hasSize(2) - } + @Test + fun `has code with spaces`() { + val code = "package test; import a.b; class A {}" + assertThat(subject.lint(code)).hasSize(2) + } - @Test - fun `has code with spaces`() { - val code = "package test; import a.b; class A {}" - assertThat(subject.lint(code)).hasSize(2) - } + @Test + fun `has too many blank lines`() { + val code = "package test\n\n\nimport a.b\n\n\nclass A {}" + assertThat(subject.lint(code)).hasSize(2) + } - @Test - fun `has too many blank lines`() { - val code = "package test\n\n\nimport a.b\n\n\nclass A {}" - assertThat(subject.lint(code)).hasSize(2) - } + @Test + fun `has package declarations in same line`() { + val code = "package test;import a.b;class A {}" + assertThat(subject.lint(code)).hasSize(2) + } - @Test - fun `has package declarations in same line`() { - val code = "package test;import a.b;class A {}" - assertThat(subject.lint(code)).hasSize(2) - } + @Test + fun `has multiple imports in file`() { + val code = """ + package com.my - @Test - fun `has multiple imports in file`() { - val code = """ - package com.my + import kotlin.collections.List + import kotlin.collections.Set - import kotlin.collections.List - import kotlin.collections.Set + class A { } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - class A { } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `has no class`() { + val code = """ + package com.my.has.no.clazz - @Test - fun `has no class`() { - val code = """ - package com.my.has.no.clazz - - import kotlin.collections.List - import kotlin.collections.Set - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + import kotlin.collections.List + import kotlin.collections.Set + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ThrowsCountSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ThrowsCountSpec.kt index 08cc3681dbe..26e4a7314a0 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ThrowsCountSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/ThrowsCountSpec.kt @@ -13,294 +13,290 @@ private const val EXCLUDE_GUARD_CLAUSES = "excludeGuardClauses" class ThrowsCountSpec { @Nested - inner class `ThrowsCount rule` { - - @Nested - inner class `a function with an empty body` { - val code = """ - fun func() {} - """ - - @Test - fun `does not report violation by default`() { - assertThat(ThrowsCount(Config.empty).lint(code)).isEmpty() - } + inner class `a function with an empty body` { + val code = """ + fun func() {} + """ + + @Test + fun `does not report violation by default`() { + assertThat(ThrowsCount(Config.empty).lint(code)).isEmpty() } + } - @Nested - inner class `a function without a body` { - val code = """ - fun func() = Unit - """ + @Nested + inner class `a function without a body` { + val code = """ + fun func() = Unit + """ + + @Test + fun `does not report violation by default`() { + assertThat(ThrowsCount(Config.empty).lint(code)).isEmpty() + } + } - @Test - fun `does not report violation by default`() { - assertThat(ThrowsCount(Config.empty).lint(code)).isEmpty() + @Nested + inner class `code with 2 throw expressions` { + val code = """ + fun f2(x: Int) { + when (x) { + 1 -> throw IOException() + 2 -> throw IOException() + } } + """ + val subject = ThrowsCount(Config.empty) + + @Test + fun `does not report violation`() { + assertThat(subject.lint(code)).isEmpty() } + } - @Nested - inner class `code with 2 throw expressions` { - val code = """ - fun f2(x: Int) { - when (x) { - 1 -> throw IOException() - 2 -> throw IOException() - } + @Nested + inner class `code with 3 throw expressions` { + val code = """ + fun f1(x: Int) { + when (x) { + 1 -> throw IOException() + 2 -> throw IOException() + 3 -> throw IOException() } - """ - val subject = ThrowsCount(Config.empty) - - @Test - fun `does not report violation`() { - assertThat(subject.lint(code)).isEmpty() } + """ + val subject = ThrowsCount(Config.empty) + + @Test + fun `reports violation by default`() { + assertThat(subject.lint(code)).hasSize(1) } + } - @Nested - inner class `code with 3 throw expressions` { - val code = """ - fun f1(x: Int) { - when (x) { - 1 -> throw IOException() - 2 -> throw IOException() - 3 -> throw IOException() - } + @Nested + inner class `code with an override function with 3 throw expressions` { + val code = """ + override fun f3(x: Int) { // does not report overridden function + when (x) { + 1 -> throw IOException() + 2 -> throw IOException() + 3 -> throw IOException() } - """ - val subject = ThrowsCount(Config.empty) - - @Test - fun `reports violation by default`() { - assertThat(subject.lint(code)).hasSize(1) } + """ + val subject = ThrowsCount(Config.empty) + + @Test + fun `reports violation by default`() { + assertThat(subject.lint(code)).isEmpty() } + } - @Nested - inner class `code with an override function with 3 throw expressions` { - val code = """ - override fun f3(x: Int) { // does not report overridden function + @Nested + inner class `code with a nested function with 3 throw expressions` { + val code = """ + import java.io.IOException + + fun foo(x: Int) { + fun bar(x: Int) { when (x) { 1 -> throw IOException() 2 -> throw IOException() 3 -> throw IOException() } } - """ - val subject = ThrowsCount(Config.empty) - - @Test - fun `reports violation by default`() { - assertThat(subject.lint(code)).isEmpty() + return bar(x) } + """ + val subject = ThrowsCount(Config.empty) + + @Test + fun `reports violation by default`() { + val findings = subject.lint(code) + assertThat(findings).hasSize(1) + assertThat(findings[0].entity.location.source.line).isEqualTo(4) } + } - @Nested - inner class `code with a nested function with 3 throw expressions` { - val code = """ - import java.io.IOException - - fun foo(x: Int) { - fun bar(x: Int) { - when (x) { - 1 -> throw IOException() - 2 -> throw IOException() - 3 -> throw IOException() - } - } - return bar(x) - } - """ - val subject = ThrowsCount(Config.empty) - - @Test - fun `reports violation by default`() { - val findings = subject.lint(code) - assertThat(findings).hasSize(1) - assertThat(findings[0].entity.location.source.line).isEqualTo(4) + @Nested + inner class `max count == 3` { + val code = """ + fun f4(x: String?) { + val denulled = x ?: throw IOException() + val int = x?.toInt() ?: throw IOException() + val double = x?.toDouble() ?: throw IOException() } - } + """ - @Nested - inner class `max count == 3` { - val code = """ - fun f4(x: String?) { - val denulled = x ?: throw IOException() - val int = x?.toInt() ?: throw IOException() - val double = x?.toDouble() ?: throw IOException() - } - """ - - @Test - fun `does not report when max parameter is 3`() { - val config = TestConfig(mapOf(MAX to "3")) - val subject = ThrowsCount(config) - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `does not report when max parameter is 3`() { + val config = TestConfig(mapOf(MAX to "3")) + val subject = ThrowsCount(config) + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `reports violation when max parameter is 2`() { - val config = TestConfig(mapOf(MAX to "2")) - val subject = ThrowsCount(config) - assertThat(subject.lint(code)).hasSize(1) - } + @Test + fun `reports violation when max parameter is 2`() { + val config = TestConfig(mapOf(MAX to "2")) + val subject = ThrowsCount(config) + assertThat(subject.lint(code)).hasSize(1) } + } - @Nested - inner class `code with ELVIS operator guard clause` { - val codeWithGuardClause = """ - fun test(x: Int): Int { - val y = x ?: throw Exception() - when (x) { - 5 -> println("x=5") - 4 -> throw Exception() - } - throw Exception() + @Nested + inner class `code with ELVIS operator guard clause` { + val codeWithGuardClause = """ + fun test(x: Int): Int { + val y = x ?: throw Exception() + when (x) { + 5 -> println("x=5") + 4 -> throw Exception() } - """ - - @Test - fun `should not report violation with EXCLUDE_GUARD_CLAUSES as true`() { - val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true")) - val subject = ThrowsCount(config) - assertThat(subject.lint(codeWithGuardClause)).isEmpty() + throw Exception() } + """ - @Test - fun `should report violation with EXCLUDE_GUARD_CLAUSES as false`() { - val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "false")) - val subject = ThrowsCount(config) - assertThat(subject.lint(codeWithGuardClause)).hasSize(1) - } + @Test + fun `should not report violation with EXCLUDE_GUARD_CLAUSES as true`() { + val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true")) + val subject = ThrowsCount(config) + assertThat(subject.lint(codeWithGuardClause)).isEmpty() } - @Nested - inner class `code with if condition guard clause` { - val codeWithGuardClause = """ - fun test(x: Int): Int { - if(x == null) throw Exception() - when (x) { - 5 -> println("x=5") - 4 -> throw Exception() - } - throw Exception() - } - """ + @Test + fun `should report violation with EXCLUDE_GUARD_CLAUSES as false`() { + val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "false")) + val subject = ThrowsCount(config) + assertThat(subject.lint(codeWithGuardClause)).hasSize(1) + } + } - @Test - fun `should not report violation with EXCLUDE_GUARD_CLAUSES as true`() { - val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true")) - val subject = ThrowsCount(config) - assertThat(subject.lint(codeWithGuardClause)).isEmpty() + @Nested + inner class `code with if condition guard clause` { + val codeWithGuardClause = """ + fun test(x: Int): Int { + if(x == null) throw Exception() + when (x) { + 5 -> println("x=5") + 4 -> throw Exception() + } + throw Exception() } + """ - @Test - fun `should report violation with EXCLUDE_GUARD_CLAUSES as false`() { - val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "false")) - val subject = ThrowsCount(config) - assertThat(subject.lint(codeWithGuardClause)).hasSize(1) - } + @Test + fun `should not report violation with EXCLUDE_GUARD_CLAUSES as true`() { + val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true")) + val subject = ThrowsCount(config) + assertThat(subject.lint(codeWithGuardClause)).isEmpty() } - @Nested - inner class `reports a too-complicated if statement for being a guard clause` { - val codeWithIfCondition = """ - fun test(x: Int): Int { - if (x < 4) { - println("x x is less than 4") - if (x < 2) { - println("x is also less than 2") - throw Exception() - } - throw Exception() - } - when (x) { - 5 -> println("x=5") - 4 -> throw Exception() + @Test + fun `should report violation with EXCLUDE_GUARD_CLAUSES as false`() { + val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "false")) + val subject = ThrowsCount(config) + assertThat(subject.lint(codeWithGuardClause)).hasSize(1) + } + } + + @Nested + inner class `reports a too-complicated if statement for being a guard clause` { + val codeWithIfCondition = """ + fun test(x: Int): Int { + if (x < 4) { + println("x x is less than 4") + if (x < 2) { + println("x is also less than 2") + throw Exception() } throw Exception() } - """ - - @Test - fun `should report violation even with EXCLUDE_GUARD_CLAUSES as true`() { - val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true")) - val subject = ThrowsCount(config) - assertThat(subject.lint(codeWithIfCondition)).hasSize(1) + when (x) { + 5 -> println("x=5") + 4 -> throw Exception() + } + throw Exception() } + """ + + @Test + fun `should report violation even with EXCLUDE_GUARD_CLAUSES as true`() { + val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true")) + val subject = ThrowsCount(config) + assertThat(subject.lint(codeWithIfCondition)).hasSize(1) } + } - @Nested - inner class `a file with 2 returns and an if condition guard clause which is not the first statement` { - val codeWithIfCondition = """ - fun test(x: Int): Int { - when (x) { - 5 -> println("x=5") - 4 -> throw Exception() - } - if (x < 4) throw Exception() - throw Exception() + @Nested + inner class `a file with 2 returns and an if condition guard clause which is not the first statement` { + val codeWithIfCondition = """ + fun test(x: Int): Int { + when (x) { + 5 -> println("x=5") + 4 -> throw Exception() } - """ - - @Test - fun `should report the violation even with EXCLUDE_GUARD_CLAUSES as true`() { - val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true")) - val subject = ThrowsCount(config) - assertThat(subject.lint(codeWithIfCondition)).hasSize(1) + if (x < 4) throw Exception() + throw Exception() } + """ + + @Test + fun `should report the violation even with EXCLUDE_GUARD_CLAUSES as true`() { + val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true")) + val subject = ThrowsCount(config) + assertThat(subject.lint(codeWithIfCondition)).hasSize(1) } + } - @Nested - inner class `a file with 2 returns and an ELVIS guard clause which is not the first statement` { - val codeWithIfCondition = """ - fun test(x: Int): Int { - when (x) { - 5 -> println("x=5") - 4 -> throw Exception() - } - val y = x ?: throw Exception() - throw Exception() + @Nested + inner class `a file with 2 returns and an ELVIS guard clause which is not the first statement` { + val codeWithIfCondition = """ + fun test(x: Int): Int { + when (x) { + 5 -> println("x=5") + 4 -> throw Exception() } - """ - - @Test - fun `should report the violation even with EXCLUDE_GUARD_CLAUSES as true`() { - val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true")) - val subject = ThrowsCount(config) - assertThat(subject.lint(codeWithIfCondition)).hasSize(1) + val y = x ?: throw Exception() + throw Exception() } - } + """ - @Nested - inner class `a file with multiple guard clauses` { - val codeWithMultipleGuardClauses = """ - fun multipleGuards(a: Int?, b: Any?, c: Int?) { - if(a == null) throw Exception() - val models = b as? Int ?: throw Exception() - val position = c?.takeIf { it != -1 } ?: throw Exception() - if(b !is String) { - println("b is not a String") - throw Exception() - } + @Test + fun `should report the violation even with EXCLUDE_GUARD_CLAUSES as true`() { + val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true")) + val subject = ThrowsCount(config) + assertThat(subject.lint(codeWithIfCondition)).hasSize(1) + } + } + @Nested + inner class `a file with multiple guard clauses` { + val codeWithMultipleGuardClauses = """ + fun multipleGuards(a: Int?, b: Any?, c: Int?) { + if(a == null) throw Exception() + val models = b as? Int ?: throw Exception() + val position = c?.takeIf { it != -1 } ?: throw Exception() + if(b !is String) { + println("b is not a String") throw Exception() } - """ - @Test - fun `should not report violation with EXCLUDE_GUARD_CLAUSES as true`() { - val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true")) - val subject = ThrowsCount(config) - assertThat(subject.lint(codeWithMultipleGuardClauses)).isEmpty() + throw Exception() } + """ - @Test - fun `should report violation with EXCLUDE_GUARD_CLAUSES as false`() { - val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "false")) - val subject = ThrowsCount(config) - assertThat(subject.lint(codeWithMultipleGuardClauses)).hasSize(1) - } + @Test + fun `should not report violation with EXCLUDE_GUARD_CLAUSES as true`() { + val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "true")) + val subject = ThrowsCount(config) + assertThat(subject.lint(codeWithMultipleGuardClauses)).isEmpty() + } + + @Test + fun `should report violation with EXCLUDE_GUARD_CLAUSES as false`() { + val config = TestConfig(mapOf(EXCLUDE_GUARD_CLAUSES to "false")) + val subject = ThrowsCount(config) + assertThat(subject.lint(codeWithMultipleGuardClauses)).hasSize(1) } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/TrailingWhitespaceSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/TrailingWhitespaceSpec.kt index b711567a598..32c8ae6b986 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/TrailingWhitespaceSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/TrailingWhitespaceSpec.kt @@ -8,72 +8,68 @@ import org.junit.jupiter.api.Test class TrailingWhitespaceSpec { @Nested - inner class `TrailingWhitespace rule` { + inner class `positive cases` { - @Nested - inner class `positive cases` { - - @Test - fun `reports a line just with a whitespace`() { - val rule = TrailingWhitespace() - rule.visit(" ".toKtFileContent()) - assertThat(rule.findings).hasTextLocations(0 to 1) - } + @Test + fun `reports a line just with a whitespace`() { + val rule = TrailingWhitespace() + rule.visit(" ".toKtFileContent()) + assertThat(rule.findings).hasTextLocations(0 to 1) + } - @Test - fun `reports a commented line with a whitespace at the end`() { - val rule = TrailingWhitespace() - rule.visit("// A comment ".toKtFileContent()) - assertThat(rule.findings).hasTextLocations(12 to 13) - } + @Test + fun `reports a commented line with a whitespace at the end`() { + val rule = TrailingWhitespace() + rule.visit("// A comment ".toKtFileContent()) + assertThat(rule.findings).hasTextLocations(12 to 13) + } - @Test - fun `reports a class declaration with a whitespace at the end`() { - val rule = TrailingWhitespace() - rule.visit(" class TrailingWhitespacePositive { \n }".toKtFileContent()) - assertThat(rule.findings).hasTextLocations(36 to 37) - } + @Test + fun `reports a class declaration with a whitespace at the end`() { + val rule = TrailingWhitespace() + rule.visit(" class TrailingWhitespacePositive { \n }".toKtFileContent()) + assertThat(rule.findings).hasTextLocations(36 to 37) + } - @Test - fun `reports a print statement with a tab at the end`() { - val rule = TrailingWhitespace() - rule.visit("\t\tprintln(\"A message\")\t".toKtFileContent()) - assertThat(rule.findings).hasTextLocations(22 to 23) - } + @Test + fun `reports a print statement with a tab at the end`() { + val rule = TrailingWhitespace() + rule.visit("\t\tprintln(\"A message\")\t".toKtFileContent()) + assertThat(rule.findings).hasTextLocations(22 to 23) } + } - @Nested - inner class `negative cases` { + @Nested + inner class `negative cases` { - @Test - fun `does not report a class and function declaration with no whitespaces at the end`() { - val code = """ - class C { + @Test + fun `does not report a class and function declaration with no whitespaces at the end`() { + val code = """ + class C { - fun f() { - println("A message") - println("Another message") ; - } + fun f() { + println("A message") + println("Another message") ; } - """.trimIndent() - val rule = TrailingWhitespace() - rule.visit(code.toKtFileContent()) - assertThat(rule.findings).isEmpty() - } + } + """.trimIndent() + val rule = TrailingWhitespace() + rule.visit(code.toKtFileContent()) + assertThat(rule.findings).isEmpty() + } - @Test - fun `does not report an indentation inside multi-line strings`() { - val code = """ - val multiLineStringWithIndents = ""${'"'} - Should ignore indent on the next line - - Should ignore indent on the previous line - ""${'"'} - """.trim() - val rule = TrailingWhitespace() - rule.visit(code.toKtFileContent()) - assertThat(rule.findings).isEmpty() - } + @Test + fun `does not report an indentation inside multi-line strings`() { + val code = """ + val multiLineStringWithIndents = ""${'"'} + Should ignore indent on the next line + + Should ignore indent on the previous line + ""${'"'} + """.trim() + val rule = TrailingWhitespace() + rule.visit(code.toKtFileContent()) + assertThat(rule.findings).isEmpty() } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryAbstractClassSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryAbstractClassSpec.kt index 8cb567ee33b..360405bb274 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryAbstractClassSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryAbstractClassSpec.kt @@ -17,269 +17,265 @@ class UnnecessaryAbstractClassSpec(val env: KotlinCoreEnvironment) { UnnecessaryAbstractClass(TestConfig(mapOf(EXCLUDE_ANNOTATED_CLASSES to listOf("Deprecated")))) @Nested - inner class `UnnecessaryAbstractClass rule` { + inner class `abstract classes with no concrete members` { + val message = "An abstract class without a concrete member can be refactored to an interface." - @Nested - inner class `abstract classes with no concrete members` { - val message = "An abstract class without a concrete member can be refactored to an interface." - - @Test - fun `reports an abstract class with no concrete member`() { - val code = """ - abstract class A { - abstract val i: Int - abstract fun f() - public abstract fun f2() - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertFindingMessage(findings, message) - } - - @Nested - inner class `reports completely-empty abstract classes` { - @Test - fun `case 1`() { - val code = "abstract class A" - val findings = subject.compileAndLintWithContext(env, code) - assertFindingMessage(findings, message) - } - - @Test - fun `case 2`() { - val code = "abstract class A()" - val findings = subject.compileAndLintWithContext(env, code) - assertFindingMessage(findings, message) - } - - @Test - fun `case 3`() { - val code = "abstract class A {}" - val findings = subject.compileAndLintWithContext(env, code) - assertFindingMessage(findings, message) - } - - @Test - fun `case 4`() { - val code = "abstract class A() {}" - val findings = subject.compileAndLintWithContext(env, code) - assertFindingMessage(findings, message) + @Test + fun `reports an abstract class with no concrete member`() { + val code = """ + abstract class A { + abstract val i: Int + abstract fun f() + public abstract fun f2() } - - @Test - fun `that inherits from an interface`() { - val code = """ - interface A { - val i: Int - } - abstract class B : A - """ - val findings = subject.compileAndLintWithContext(env, code) - assertFindingMessage(findings, message) - } - - @Test - fun `that inherits from another abstract class`() { - val code = """ - @Deprecated("We don't care about this first class") - abstract class A { - abstract val i: Int - } - abstract class B : A() - """ - val findings = subject.compileAndLintWithContext(env, code) - assertFindingMessage(findings, message) - } - } - - @Test - fun `does not report an abstract class with concrete members derived from a base class`() { - val code = """ - abstract class A { - abstract fun f() - val i: Int = 0 - } - - abstract class B : A() { - abstract fun g() - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `does not report an abstract class with a internal abstract member`() { - val code = """ - abstract class A { - internal abstract fun f() - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `does not report an abstract class with a protected abstract member`() { - val code = """ - abstract class A { - protected abstract fun f() - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertFindingMessage(findings, message) } @Nested - inner class `abstract classes with no abstract members` { - - val message = "An abstract class without an abstract member can be refactored to a concrete class." - + inner class `reports completely-empty abstract classes` { @Test - fun `reports no abstract members in abstract class`() { - val code = """ - abstract class A { - val i: Int = 0 - fun f() {} - } - """ + fun `case 1`() { + val code = "abstract class A" val findings = subject.compileAndLintWithContext(env, code) assertFindingMessage(findings, message) } @Test - fun `reports no abstract members in nested abstract class inside a concrete class`() { - val code = """ - class Outer { - abstract class Inner { - fun f() {} - } - } - """ + fun `case 2`() { + val code = "abstract class A()" val findings = subject.compileAndLintWithContext(env, code) assertFindingMessage(findings, message) } @Test - fun `reports no abstract members in nested abstract class inside an interface`() { - val code = """ - interface Inner { - abstract class A { - fun f() {} - } - } - """ + fun `case 3`() { + val code = "abstract class A {}" val findings = subject.compileAndLintWithContext(env, code) assertFindingMessage(findings, message) } @Test - fun `reports no abstract members in an abstract class with just a constructor`() { - val code = "abstract class A(val i: Int)" + fun `case 4`() { + val code = "abstract class A() {}" val findings = subject.compileAndLintWithContext(env, code) assertFindingMessage(findings, message) } @Test - fun `reports no abstract members in an abstract class with a body and a constructor`() { - val code = "abstract class A(val i: Int) {}" + fun `that inherits from an interface`() { + val code = """ + interface A { + val i: Int + } + abstract class B : A + """ val findings = subject.compileAndLintWithContext(env, code) assertFindingMessage(findings, message) } @Test - fun `reports an abstract class with no abstract member derived from a class with abstract members`() { + fun `that inherits from another abstract class`() { val code = """ - abstract class Base { + @Deprecated("We don't care about this first class") + abstract class A { abstract val i: Int - abstract fun f() - fun f1() {} - } - - abstract class Sub : Base() { - override val i: Int - get() = 1 - - override fun f() {} - - fun g() {} } + abstract class B : A() """ val findings = subject.compileAndLintWithContext(env, code) assertFindingMessage(findings, message) } } - @Nested - inner class `abstract classes with members` { + @Test + fun `does not report an abstract class with concrete members derived from a base class`() { + val code = """ + abstract class A { + abstract fun f() + val i: Int = 0 + } - @Test - fun `does not report an abstract class with members and an abstract class derived from it`() { - val code = """ - abstract class A { - abstract val i: Int - fun f() {} - } - - abstract class B : A() { - fun g() {} - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + abstract class B : A() { + abstract fun g() + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report an abstract class with a constructor and an abstract class derived from it`() { - val code = """ - abstract class A(val i: Int) { - abstract fun f() - } - - abstract class B : A(0) { - fun g() {} - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does not report an abstract class with a internal abstract member`() { + val code = """ + abstract class A { + internal abstract fun f() + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report an abstract class with a function derived from an interface`() { - val code = """ - abstract class A : Interface { - fun g() {} - } - - interface Interface { - fun f() + @Test + fun `does not report an abstract class with a protected abstract member`() { + val code = """ + abstract class A { + protected abstract fun f() + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + } + + @Nested + inner class `abstract classes with no abstract members` { + + val message = "An abstract class without an abstract member can be refactored to a concrete class." + + @Test + fun `reports no abstract members in abstract class`() { + val code = """ + abstract class A { + val i: Int = 0 + fun f() {} + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertFindingMessage(findings, message) + } + + @Test + fun `reports no abstract members in nested abstract class inside a concrete class`() { + val code = """ + class Outer { + abstract class Inner { + fun f() {} } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertFindingMessage(findings, message) + } - @Test - fun `does not report abstract classes with module annotation`() { - val code = """ - @Deprecated("test") + @Test + fun `reports no abstract members in nested abstract class inside an interface`() { + val code = """ + interface Inner { abstract class A { - abstract fun f() + fun f() {} } - - @kotlin.Deprecated("test") - abstract class B { - abstract fun f() - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertFindingMessage(findings, message) + } - @Test - fun `does not report abstract classes with properties in the primary constructor`() { - val code = """ - interface I { - fun test(): Int - } - abstract class Test(val x: Int) : I - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `reports no abstract members in an abstract class with just a constructor`() { + val code = "abstract class A(val i: Int)" + val findings = subject.compileAndLintWithContext(env, code) + assertFindingMessage(findings, message) + } + + @Test + fun `reports no abstract members in an abstract class with a body and a constructor`() { + val code = "abstract class A(val i: Int) {}" + val findings = subject.compileAndLintWithContext(env, code) + assertFindingMessage(findings, message) + } + + @Test + fun `reports an abstract class with no abstract member derived from a class with abstract members`() { + val code = """ + abstract class Base { + abstract val i: Int + abstract fun f() + fun f1() {} + } + + abstract class Sub : Base() { + override val i: Int + get() = 1 + + override fun f() {} + + fun g() {} + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertFindingMessage(findings, message) + } + } + + @Nested + inner class `abstract classes with members` { + + @Test + fun `does not report an abstract class with members and an abstract class derived from it`() { + val code = """ + abstract class A { + abstract val i: Int + fun f() {} + } + + abstract class B : A() { + fun g() {} + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `does not report an abstract class with a constructor and an abstract class derived from it`() { + val code = """ + abstract class A(val i: Int) { + abstract fun f() + } + + abstract class B : A(0) { + fun g() {} + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `does not report an abstract class with a function derived from an interface`() { + val code = """ + abstract class A : Interface { + fun g() {} + } + + interface Interface { + fun f() + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `does not report abstract classes with module annotation`() { + val code = """ + @Deprecated("test") + abstract class A { + abstract fun f() + } + + @kotlin.Deprecated("test") + abstract class B { + abstract fun f() + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `does not report abstract classes with properties in the primary constructor`() { + val code = """ + interface I { + fun test(): Int + } + abstract class Test(val x: Int) : I + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryAnnotationUseSiteTargetSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryAnnotationUseSiteTargetSpec.kt index 7edf5277801..e489a159d8a 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryAnnotationUseSiteTargetSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryAnnotationUseSiteTargetSpec.kt @@ -3,80 +3,75 @@ package io.gitlab.arturbosch.detekt.rules.style import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class UnnecessaryAnnotationUseSiteTargetSpec { - @Nested - inner class `UnnecessaryAnnotationUseSiteTarget rule` { + @Test + @DisplayName("Unnecessary @param: in a property constructor") + fun unnecessaryParamInPropertyConstructor() { + val code = """ + class C(@param:Asdf private val foo: String) - @Test - @DisplayName("Unnecessary @param: in a property constructor") - fun unnecessaryParamInPropertyConstructor() { - val code = """ - class C(@param:Asdf private val foo: String) - - annotation class Asdf - """ - assertThat(UnnecessaryAnnotationUseSiteTarget().compileAndLint(code)).hasTextLocations("param:") - } + annotation class Asdf + """ + assertThat(UnnecessaryAnnotationUseSiteTarget().compileAndLint(code)).hasTextLocations("param:") + } - @Test - @DisplayName("Unnecessary @param: in a constructor") - fun unnecessaryParamInConstructor() { - val code = """ - class C(@param:Asdf foo: String) + @Test + @DisplayName("Unnecessary @param: in a constructor") + fun unnecessaryParamInConstructor() { + val code = """ + class C(@param:Asdf foo: String) - annotation class Asdf - """ - assertThat(UnnecessaryAnnotationUseSiteTarget().compileAndLint(code)).hasTextLocations("param:") - } + annotation class Asdf + """ + assertThat(UnnecessaryAnnotationUseSiteTarget().compileAndLint(code)).hasTextLocations("param:") + } - @Test - @DisplayName("Necessary @get:") - fun unnecessaryGet() { - val code = """ - class C(@get:Asdf private val foo: String) + @Test + @DisplayName("Necessary @get:") + fun unnecessaryGet() { + val code = """ + class C(@get:Asdf private val foo: String) - annotation class Asdf - """ - assertThat(UnnecessaryAnnotationUseSiteTarget().compileAndLint(code)).isEmpty() - } + annotation class Asdf + """ + assertThat(UnnecessaryAnnotationUseSiteTarget().compileAndLint(code)).isEmpty() + } - @Test - @DisplayName("Necessary @property:") - fun necessaryProperty() { - val code = """ - class C(@property:Asdf private val foo: String) + @Test + @DisplayName("Necessary @property:") + fun necessaryProperty() { + val code = """ + class C(@property:Asdf private val foo: String) - annotation class Asdf - """ - assertThat(UnnecessaryAnnotationUseSiteTarget().compileAndLint(code)).isEmpty() - } + annotation class Asdf + """ + assertThat(UnnecessaryAnnotationUseSiteTarget().compileAndLint(code)).isEmpty() + } - @Test - @DisplayName("Unnecessary @property:") - fun unnecessaryProperty() { - val code = """ - class C { - @property:Asdf private val foo: String = "bar" - } + @Test + @DisplayName("Unnecessary @property:") + fun unnecessaryProperty() { + val code = """ + class C { + @property:Asdf private val foo: String = "bar" + } - annotation class Asdf - """ - assertThat(UnnecessaryAnnotationUseSiteTarget().compileAndLint(code)).hasTextLocations("property:") - } + annotation class Asdf + """ + assertThat(UnnecessaryAnnotationUseSiteTarget().compileAndLint(code)).hasTextLocations("property:") + } - @Test - @DisplayName("Unnecessary @property: at a top level property") - fun unnecessaryPropertyAtTopLevel() { - val code = """ - @property:Asdf private val foo: String = "bar" + @Test + @DisplayName("Unnecessary @property: at a top level property") + fun unnecessaryPropertyAtTopLevel() { + val code = """ + @property:Asdf private val foo: String = "bar" - annotation class Asdf - """ - assertThat(UnnecessaryAnnotationUseSiteTarget().compileAndLint(code)).hasTextLocations("property:") - } + annotation class Asdf + """ + assertThat(UnnecessaryAnnotationUseSiteTarget().compileAndLint(code)).hasTextLocations("property:") } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryApplySpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryApplySpec.kt index 55998041eff..cd051c8214c 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryApplySpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryApplySpec.kt @@ -15,438 +15,434 @@ class UnnecessaryApplySpec(val env: KotlinCoreEnvironment) { val subject = UnnecessaryApply(Config.empty) @Nested - inner class `UnnecessaryApply rule` { + inner class `unnecessary apply expressions that can be changed to ordinary method call` { + + @Test + fun `reports an apply on non-nullable type`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val a: Int = 0 + a.apply { + plus(1) + } + } + """ + ) + assertThat(findings).hasSize(1) + assertThat(findings.first().message).isEqualTo("apply expression can be omitted") + } - @Nested - inner class `unnecessary apply expressions that can be changed to ordinary method call` { + @Test + fun `reports an apply on nullable type`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val a: Int? = null + // Resolution: we can't say here if plus is on 'this' or just a side effect when a is not null + // However such cases should be better handled with an if-null check instead of misusing apply + a?.apply { + plus(1) + } + } + """ + ) + assertThat(findings).hasSize(1) + assertThat(findings.first().message).isEqualTo("apply can be replaced with let or an if") + } - @Test - fun `reports an apply on non-nullable type`() { - val findings = subject.compileAndLintWithContext( + @Test + fun `reports a false negative apply on nullable type - #1485`() { + assertThat( + subject.compileAndLintWithContext( env, """ - fun f() { - val a: Int = 0 - a.apply { - plus(1) - } + val a: Any? = Any() + fun Any.b() = Unit + + fun main() { + a?.apply { + b() } + } """ ) - assertThat(findings).hasSize(1) - assertThat(findings.first().message).isEqualTo("apply expression can be omitted") - } + ).hasSize(1) + } - @Test - fun `reports an apply on nullable type`() { - val findings = subject.compileAndLintWithContext( + @Test + fun `does not report an apply with lambda block`() { + assertThat( + subject.compileAndLintWithContext( env, """ - fun f() { - val a: Int? = null - // Resolution: we can't say here if plus is on 'this' or just a side effect when a is not null - // However such cases should be better handled with an if-null check instead of misusing apply - a?.apply { - plus(1) - } - } + fun f() { + val a: Int? = null + a?.apply({ + plus(1) + }) + } """ ) - assertThat(findings).hasSize(1) - assertThat(findings.first().message).isEqualTo("apply can be replaced with let or an if") - } - - @Test - fun `reports a false negative apply on nullable type - #1485`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - val a: Any? = Any() - fun Any.b() = Unit + ).isEmpty() + } + + @Test + fun `does not report single statement in apply used as function argument`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + fun b(i: Int?) {} + + fun main() { + val a: Int? = null + b(a.apply { + toString() + }) + } + """ + ) + ).isEmpty() + } + + @Test + fun `does not report single assignment statement in apply used as function argument - #1517`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + class C { + var prop = 0 + } - fun main() { - a?.apply { - b() + fun main() { + val list = ArrayList() + list.add( + if (true) { + C().apply { + prop = 1 + } + } else { + C() } - } - """ - ) - ).hasSize(1) - } - - @Test - fun `does not report an apply with lambda block`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - fun f() { - val a: Int? = null - a?.apply({ - plus(1) - }) - } - """ ) - ).isEmpty() - } - - @Test - fun `does not report single statement in apply used as function argument`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - fun b(i: Int?) {} - - fun main() { - val a: Int? = null - b(a.apply { - toString() - }) + } + """ + ) + ).isEmpty() + } + + @Test + fun `does not report if result of apply is used - #2938`() { + assertThat( + subject.compileAndLint( + """ + fun main() { + val a = listOf(mutableListOf("")) + .map { it.apply { add("") } } + } + """ + ) + ).isEmpty() + } + + @Test + fun `does not report applies with lambda body containing more than one statement`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + fun b(i: Int?) {} + + fun main() { + val a: Int? = null + a?.apply { + plus(1) + plus(2) } - """ - ) - ).isEmpty() - } - - @Test - fun `does not report single assignment statement in apply used as function argument - #1517`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - class C { - var prop = 0 + a?.apply { + plus(1) + plus(2) } - - fun main() { - val list = ArrayList() - list.add( - if (true) { - C().apply { - prop = 1 - } - } else { - C() - } - ) + b(1.apply { + plus(1) + plus(2) + }) + } + """ + ) + ).isEmpty() + } + + @Test + fun `reports when lambda has a dot qualified expression`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun test(foo: Foo) { + foo.apply { + bar.bar() } - """ - ) - ).isEmpty() - } - - @Test - fun `does not report if result of apply is used - #2938`() { - assertThat( - subject.compileAndLint( - """ - fun main() { - val a = listOf(mutableListOf("")) - .map { it.apply { add("") } } + } + + class Foo(val bar: Bar) + + class Bar { + fun bar() {} + } + """ + ) + assertThat(findings).hasSize(1) + } + + @Test + fun `reports when lambda has a dot qualified expression which has 'this' receiver`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun test(foo: Foo) { + foo.apply { + this.bar.bar() } - """ - ) - ).isEmpty() - } - - @Test - fun `does not report applies with lambda body containing more than one statement`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - fun b(i: Int?) {} - - fun main() { - val a: Int? = null - a?.apply { - plus(1) - plus(2) - } - a?.apply { - plus(1) - plus(2) - } - b(1.apply { - plus(1) - plus(2) - }) + } + + class Foo(val bar: Bar) + + class Bar { + fun bar() {} + } + """ + ) + assertThat(findings).hasSize(1) + } + + @Test + fun `reports when lambda has a 'this' expression`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun test() { + "foo".apply { + this } - """ - ) - ).isEmpty() - } + } + """ + ) + assertThat(findings).hasSize(1) + } + } - @Test - fun `reports when lambda has a dot qualified expression`() { - val findings = subject.compileAndLintWithContext( + @Nested + inner class `reported false positives - #1305` { + + @Test + fun `is used within an assignment expr itself`() { + assertThat( + subject.compileAndLintWithContext( env, """ - fun test(foo: Foo) { - foo.apply { - bar.bar() - } - } - - class Foo(val bar: Bar) - - class Bar { - fun bar() {} - } + class C { + fun f() = true + } + + val a = C().apply { f() } """ ) - assertThat(findings).hasSize(1) - } + ).isEmpty() + } - @Test - fun `reports when lambda has a dot qualified expression which has 'this' receiver`() { - val findings = subject.compileAndLintWithContext( + @Test + fun `is used as return type of extension function`() { + assertThat( + subject.compileAndLintWithContext( env, """ - fun test(foo: Foo) { - foo.apply { - this.bar.bar() - } - } - - class Foo(val bar: Bar) - - class Bar { - fun bar() {} - } + class C(var prop: Int) + + fun Int.f() = C(5).apply { prop = 10 } """ ) - assertThat(findings).hasSize(1) - } + ).isEmpty() + } - @Test - fun `reports when lambda has a 'this' expression`() { - val findings = subject.compileAndLintWithContext( + @Test + fun `should not flag apply when assigning property on this`() { + assertThat( + subject.compileAndLintWithContext( env, """ - fun test() { - "foo".apply { - this - } + class C(var prop: Int) { + private val c by lazy { + C(1).apply { prop = 3 } } + } """ ) - assertThat(findings).hasSize(1) - } + ).isEmpty() } - @Nested - inner class `reported false positives - #1305` { - - @Test - fun `is used within an assignment expr itself`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - class C { - fun f() = true - } - - val a = C().apply { f() } - """ - ) - ).isEmpty() - } - - @Test - fun `is used as return type of extension function`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - class C(var prop: Int) - - fun Int.f() = C(5).apply { prop = 10 } - """ - ) - ).isEmpty() - } - - @Test - fun `should not flag apply when assigning property on this`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - class C(var prop: Int) { - private val c by lazy { - C(1).apply { prop = 3 } + @Test + fun `should not report apply when using it after returning something`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + class C(var prop: Int) + + fun f() = (C(5)).apply { prop = 10 } + """ + ) + ).isEmpty() + } + + @Test + fun `should not report apply usage inside safe chained expressions`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + fun f() { + val arguments = listOf(1,2,3) + ?.map { it * 2 } + ?.apply { if (true) 4 } + ?: listOf(0) + } + """ + ) + ).isEmpty() + } + } + + @Nested + inner class `false positive in single nesting expressions - #1473` { + + @Test + fun `should not report the if expression`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + class C { + fun has() = true + } + + fun f() { + C().apply { + if (has()) { + // actions } } - """ - ) - ).isEmpty() - } - - @Test - fun `should not report apply when using it after returning something`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - class C(var prop: Int) - - fun f() = (C(5)).apply { prop = 10 } - """ - ) - ).isEmpty() - } - - @Test - fun `should not report apply usage inside safe chained expressions`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - fun f() { - val arguments = listOf(1,2,3) - ?.map { it * 2 } - ?.apply { if (true) 4 } - ?: listOf(0) - } - """ - ) - ).isEmpty() - } + } + """ + ) + ).isEmpty() } - @Nested - inner class `false positive in single nesting expressions - #1473` { - - @Test - fun `should not report the if expression`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - class C { - fun has() = true - } + @Test + fun `should report reference expressions`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + class C { + val prop = 5 + } - fun f() { - C().apply { - if (has()) { - // actions - } - } + fun f() { + C().apply { + prop } - """ - ) - ).isEmpty() - } - - @Test - fun `should report reference expressions`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - class C { - val prop = 5 + + C().apply { + this.prop } + } + """ + ) + ).hasSize(2) + } + } - fun f() { - C().apply { - prop - } + @Nested + inner class `false positive when it's used as an expression - #2435` { - C().apply { - this.prop - } + @Test + fun `do not report when it's used as an assignment`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + class C { + fun f() {} + } + + fun main() { + val c = if (5 >= 3) { + C().apply { f() } + } else { + C() } - """ - ) - ).hasSize(2) - } + } + """ + ) + ).isEmpty() } - @Nested - inner class `false positive when it's used as an expression - #2435` { - - @Test - fun `do not report when it's used as an assignment`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - class C { - fun f() {} - } - - fun main() { - val c = if (5 >= 3) { - C().apply { f() } - } else { - C() - } - } - """ - ) - ).isEmpty() - } - - @Test - fun `do not report when it's used as the last statement of a block inside lambda`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - class C { - fun f() {} + @Test + fun `do not report when it's used as the last statement of a block inside lambda`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + class C { + fun f() {} + } + + fun print(block: () -> C) { + println(block()) + } + + fun main() { + print { + println("Does nothing") + C().apply { f() } } + } + """ + ) + ).isEmpty() + } + } + + @Nested + inner class `false positive when lambda has multiple member references - #3561` { - fun print(block: () -> C) { - println(block()) + @Test + fun `do not report when lambda has multiple member references`() { + assertThat( + subject.compileAndLintWithContext( + env, + """ + fun test(foo: Foo) { + foo.apply { + bar { + baz = 2 + } + } } - fun main() { - print { - println("Does nothing") - C().apply { f() } + class Foo { + fun bar(f: () -> Unit) { } + var baz = 1 } - """ - ) - ).isEmpty() - } - } - @Nested - inner class `false positive when lambda has multiple member references - #3561` { - - @Test - fun `do not report when lambda has multiple member references`() { - assertThat( - subject.compileAndLintWithContext( - env, - """ - fun test(foo: Foo) { - foo.apply { - bar { - baz = 2 - } - } - } - - class Foo { - fun bar(f: () -> Unit) { - } - var baz = 1 - } - - """ - ) - ).isEmpty() - } + """ + ) + ).isEmpty() } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryInheritanceSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryInheritanceSpec.kt index 9eb5d6200cc..1c90c41279f 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryInheritanceSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryInheritanceSpec.kt @@ -3,30 +3,25 @@ package io.gitlab.arturbosch.detekt.rules.style import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.test.lint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class UnnecessaryInheritanceSpec { val subject = UnnecessaryInheritance(Config.empty) - @Nested - inner class `check inherit classes` { - - @Test - fun `has unnecessary super type declarations`() { - val findings = subject.lint( - """ - class A : Any() - class B : Object() - """ - ) - assertThat(findings).hasSize(2) - } + @Test + fun `has unnecessary super type declarations`() { + val findings = subject.lint( + """ + class A : Any() + class B : Object() + """ + ) + assertThat(findings).hasSize(2) + } - @Test - fun `has no unnecessary super type declarations`() { - val findings = subject.lint("class C : An()") - assertThat(findings).isEmpty() - } + @Test + fun `has no unnecessary super type declarations`() { + val findings = subject.lint("class C : An()") + assertThat(findings).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryInnerClassSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryInnerClassSpec.kt index 3c341f65515..a20068ddcf4 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryInnerClassSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryInnerClassSpec.kt @@ -12,43 +12,76 @@ import org.junit.jupiter.api.Test class UnnecessaryInnerClassSpec(val env: KotlinCoreEnvironment) { val subject = UnnecessaryInnerClass(Config.empty) + @Test + fun `reports when an inner class does not access members of its outer class`() { + val code = """ + val fileFoo = "FILE_FOO" + + class A { + val foo = "BAR" + + fun printFoo() { + println(foo) + } + + inner class B { + val fizz = "BUZZ" + + fun printFizz() { + println(fileFoo) + println(fizz) + } + } + } + """.trimIndent() + + assertThat(subject.lintWithContext(env, code)).hasSize(1) + } + @Nested - inner class `UnnecessaryInnerClass Rule` { + inner class `does not report an inner class accessing outer-class members` { @Test - fun `reports when an inner class does not access members of its outer class`() { + fun `as a default argument for a constructor`() { val code = """ - val fileFoo = "FILE_FOO" - class A { val foo = "BAR" - - fun printFoo() { - println(foo) - } - + + inner class B(val fizz: String = foo) + } + """.trimIndent() + + assertThat(subject.lintWithContext(env, code)).isEmpty() + } + + @Test + fun `as a property initializer`() { + val code = """ + class A { + val foo = "BAR" + inner class B { - val fizz = "BUZZ" - - fun printFizz() { - println(fileFoo) - println(fizz) - } + val fizz = foo } } """.trimIndent() - assertThat(subject.lintWithContext(env, code)).hasSize(1) + assertThat(subject.lintWithContext(env, code)).isEmpty() } @Nested - inner class `does not report an inner class accessing outer-class members` { + inner class `in a variable assignment` { @Test - fun `as a default argument for a constructor`() { + fun `where the outer-class variable is on the left`() { val code = """ class A { - val foo = "BAR" + var foo = "BAR" - inner class B(val fizz: String = foo) + inner class B { + val fizz = "BUZZ" + init { + foo = fizz + } + } } """.trimIndent() @@ -56,13 +89,16 @@ class UnnecessaryInnerClassSpec(val env: KotlinCoreEnvironment) { } @Test - fun `as a property initializer`() { + fun `where the outer-class variable is on the right`() { val code = """ class A { val foo = "BAR" inner class B { - val fizz = foo + val fizz: String + init { + fizz = foo + } } } """.trimIndent() @@ -70,170 +106,37 @@ class UnnecessaryInnerClassSpec(val env: KotlinCoreEnvironment) { assertThat(subject.lintWithContext(env, code)).isEmpty() } - @Nested - inner class `in a variable assignment` { - @Test - fun `where the outer-class variable is on the left`() { - val code = """ - class A { - var foo = "BAR" - - inner class B { - val fizz = "BUZZ" - init { - foo = fizz - } - } - } - """.trimIndent() - - assertThat(subject.lintWithContext(env, code)).isEmpty() - } - - @Test - fun `where the outer-class variable is on the right`() { - val code = """ - class A { - val foo = "BAR" - - inner class B { - val fizz: String - init { - fizz = foo - } - } - } - """.trimIndent() - - assertThat(subject.lintWithContext(env, code)).isEmpty() - } - - @Test - fun `where the outer-class variable is in a compound statement`() { - val code = """ - class A { - val foo = "BAR" - - inner class B { - val fizz: String - init { - fizz = "FOO" + foo - } - } - } - """.trimIndent() - - assertThat(subject.lintWithContext(env, code)).isEmpty() - } - } - - @Nested - inner class `in an if-statement` { - @Test - fun `where the outer-class variable is the only expression`() { - val code = """ - class A(val foo: Boolean) { - - inner class B { - fun printFoo() { - if (foo) { - println("FOO") - } - } - } - } - """.trimIndent() - - assertThat(subject.lintWithContext(env, code)).isEmpty() - } - - @Test - fun `where the outer-class variable is on the left`() { - val code = """ - class A { - val foo = "BAR" - - inner class B { - fun printFoo() { - if (foo == "BAR") { - println("FOO") - } - } - } - } - """.trimIndent() - - assertThat(subject.lintWithContext(env, code)).isEmpty() - } - - @Test - fun `where the outer-class variable is on the right`() { - val code = """ - class A { - val foo = "BAR" - - inner class B { - fun printFoo() { - if ("BAR" == foo) { - println("FOO") - } - } - } - } - """.trimIndent() - - assertThat(subject.lintWithContext(env, code)).isEmpty() - } - - @Test - fun `where the outer-class variable is in a compound statement`() { - val code = """ - class A { - val foo = "BAR" - - inner class B { - val fizz = "BUZZ" - fun printFoo() { - if (fizz == "BUZZ" && foo) { - println("FOO") - } - } - } - } - """.trimIndent() - - assertThat(subject.lintWithContext(env, code)).isEmpty() - } - } - @Test - fun `as a function initializer`() { + fun `where the outer-class variable is in a compound statement`() { val code = """ class A { - fun printFoo() { - println("FOO") - } - + val foo = "BAR" + inner class B { - fun printFizz() = printFoo() + val fizz: String + init { + fizz = "FOO" + foo + } } } """.trimIndent() assertThat(subject.lintWithContext(env, code)).isEmpty() } + } + @Nested + inner class `in an if-statement` { @Test - fun `as a function call`() { + fun `where the outer-class variable is the only expression`() { val code = """ - class A { - fun printFoo() { - println("FOO") - } + class A(val foo: Boolean) { inner class B { - fun printFizz() { - printFoo() + fun printFoo() { + if (foo) { + println("FOO") + } } } } @@ -243,14 +146,16 @@ class UnnecessaryInnerClassSpec(val env: KotlinCoreEnvironment) { } @Test - fun `as a function argument`() { + fun `where the outer-class variable is on the left`() { val code = """ class A { val foo = "BAR" inner class B { - fun printFizz() { - println(foo) + fun printFoo() { + if (foo == "BAR") { + println("FOO") + } } } } @@ -260,14 +165,16 @@ class UnnecessaryInnerClassSpec(val env: KotlinCoreEnvironment) { } @Test - fun `as a default value in a function signature`() { + fun `where the outer-class variable is on the right`() { val code = """ class A { val foo = "BAR" inner class B { - fun printFizz(fizzVal: String = foo) { - println(fizzVal) + fun printFoo() { + if ("BAR" == foo) { + println("FOO") + } } } } @@ -277,20 +184,17 @@ class UnnecessaryInnerClassSpec(val env: KotlinCoreEnvironment) { } @Test - fun `to call a function of the member`() { + fun `where the outer-class variable is in a compound statement`() { val code = """ - class FooClass { - fun printFoo() { - println("FOO") - } - } - class A { - val foo = FooClass() + val foo = "BAR" inner class B { - fun printFizz() { - foo.printFoo() + val fizz = "BUZZ" + fun printFoo() { + if (fizz == "BUZZ" && foo) { + println("FOO") + } } } } @@ -298,86 +202,154 @@ class UnnecessaryInnerClassSpec(val env: KotlinCoreEnvironment) { assertThat(subject.lintWithContext(env, code)).isEmpty() } + } - @Test - fun `to call a function type variable of the member`() { - val code = """ - class A { - val foo: () -> Unit = {} - - inner class B { - fun bar() { - foo() - } + @Test + fun `as a function initializer`() { + val code = """ + class A { + fun printFoo() { + println("FOO") + } + + inner class B { + fun printFizz() = printFoo() + } + } + """.trimIndent() + + assertThat(subject.lintWithContext(env, code)).isEmpty() + } + + @Test + fun `as a function call`() { + val code = """ + class A { + fun printFoo() { + println("FOO") + } + + inner class B { + fun printFizz() { + printFoo() } } - """.trimIndent() + } + """.trimIndent() - assertThat(subject.lintWithContext(env, code)).isEmpty() - } + assertThat(subject.lintWithContext(env, code)).isEmpty() } - @Nested - inner class `does not report a double-nested inner class accessing from an outer-class member` { + @Test + fun `as a function argument`() { + val code = """ + class A { + val foo = "BAR" + + inner class B { + fun printFizz() { + println(foo) + } + } + } + """.trimIndent() - @Test - fun `when the innermost class refers a inner class and the inner class refers the outermost class`() { - val code = """ - class A { - val foo = "BAR" - - inner class B { - val fizz = foo - inner class C { - fun printFoo() { - println(fizz) - } - } + assertThat(subject.lintWithContext(env, code)).isEmpty() + } + + @Test + fun `as a default value in a function signature`() { + val code = """ + class A { + val foo = "BAR" + + inner class B { + fun printFizz(fizzVal: String = foo) { + println(fizzVal) } } - """.trimIndent() + } + """.trimIndent() - assertThat(subject.lintWithContext(env, code)).isEmpty() - } + assertThat(subject.lintWithContext(env, code)).isEmpty() + } - @Test - fun `when the innermost class refers the outermost class`() { - val code = """ - class A { - val foo = "BAR" - - inner class B { - inner class C { - fun printFoo() { - println(foo) - } - } + @Test + fun `to call a function of the member`() { + val code = """ + class FooClass { + fun printFoo() { + println("FOO") + } + } + + class A { + val foo = FooClass() + + inner class B { + fun printFizz() { + foo.printFoo() } } - """.trimIndent() + } + """.trimIndent() - assertThat(subject.lintWithContext(env, code)).isEmpty() - } + assertThat(subject.lintWithContext(env, code)).isEmpty() } @Test - fun `does not report anonymous inner classes`() { + fun `to call a function type variable of the member`() { val code = """ - interface FooInterface { - fun doFoo() + class A { + val foo: () -> Unit = {} + + inner class B { + fun bar() { + foo() + } + } } + """.trimIndent() - class Foo { - fun runFoo(fi: FooInterface) { - fi.doFoo() + assertThat(subject.lintWithContext(env, code)).isEmpty() + } + } + + @Nested + inner class `does not report a double-nested inner class accessing from an outer-class member` { + + @Test + fun `when the innermost class refers a inner class and the inner class refers the outermost class`() { + val code = """ + class A { + val foo = "BAR" + + inner class B { + val fizz = foo + inner class C { + fun printFoo() { + println(fizz) + } + } } + } + """.trimIndent() + + assertThat(subject.lintWithContext(env, code)).isEmpty() + } + + @Test + fun `when the innermost class refers the outermost class`() { + val code = """ + class A { + val foo = "BAR" - fun run() { - runFoo(object : FooInterface { - override fun doFoo() { - println("FOO") + inner class B { + inner class C { + fun printFoo() { + println(foo) } - }) + } } } """.trimIndent() @@ -385,4 +357,29 @@ class UnnecessaryInnerClassSpec(val env: KotlinCoreEnvironment) { assertThat(subject.lintWithContext(env, code)).isEmpty() } } + + @Test + fun `does not report anonymous inner classes`() { + val code = """ + interface FooInterface { + fun doFoo() + } + + class Foo { + fun runFoo(fi: FooInterface) { + fi.doFoo() + } + + fun run() { + runFoo(object : FooInterface { + override fun doFoo() { + println("FOO") + } + }) + } + } + """.trimIndent() + + assertThat(subject.lintWithContext(env, code)).isEmpty() + } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryLetSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryLetSpec.kt index 6415fd9c409..918177ef0a2 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryLetSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryLetSpec.kt @@ -12,410 +12,407 @@ import org.junit.jupiter.api.Test class UnnecessaryLetSpec(val env: KotlinCoreEnvironment) { val subject = UnnecessaryLet(Config.empty) - @Nested - inner class `UnnecessaryLet rule` { - @Test - fun `reports unnecessary lets that can be changed to ordinary method call 1`() { - val findings = subject.compileAndLintWithContext( - env, - """ - fun f() { - val a: Int = 1 - a.let { it.plus(1) } - a.let { that -> that.plus(1) } - } - """ - ) - assertThat(findings).hasSize(2) - assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } - } + @Test + fun `reports unnecessary lets that can be changed to ordinary method call 1`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val a: Int = 1 + a.let { it.plus(1) } + a.let { that -> that.plus(1) } + } + """ + ) + assertThat(findings).hasSize(2) + assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } + } - @Test - fun `reports unnecessary lets that can be changed to ordinary method call 2`() { - val findings = subject.compileAndLintWithContext( - env, - """ - fun f() { - val a: Int? = null - a?.let { it.plus(1) } - a?.let { that -> that.plus(1) } - } - """ - ) - assertThat(findings).hasSize(2) - assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } - } + @Test + fun `reports unnecessary lets that can be changed to ordinary method call 2`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val a: Int? = null + a?.let { it.plus(1) } + a?.let { that -> that.plus(1) } + } + """ + ) + assertThat(findings).hasSize(2) + assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } + } - @Test - fun `reports unnecessary lets that can be changed to ordinary method call 3`() { - val findings = subject.compileAndLintWithContext( - env, - """ - fun f() { - val a: Int? = null - a?.let { it?.plus(1) } - a?.let { that -> that?.plus(1) } - } - """ - ) - assertThat(findings).hasSize(2) - assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } - } + @Test + fun `reports unnecessary lets that can be changed to ordinary method call 3`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val a: Int? = null + a?.let { it?.plus(1) } + a?.let { that -> that?.plus(1) } + } + """ + ) + assertThat(findings).hasSize(2) + assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } + } - @Test - fun `reports unnecessary lets that can be changed to ordinary method call 4`() { - val findings = subject.compileAndLintWithContext( - env, - """ - fun f() { - val a: Int? = null - a?.let { that -> that.plus(1) }?.let { it.plus(1) } - } - """ - ) - assertThat(findings).hasSize(2) - assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } - } + @Test + fun `reports unnecessary lets that can be changed to ordinary method call 4`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val a: Int? = null + a?.let { that -> that.plus(1) }?.let { it.plus(1) } + } + """ + ) + assertThat(findings).hasSize(2) + assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } + } - @Test - fun `reports unnecessary lets that can be changed to ordinary method call 5`() { - val findings = subject.compileAndLintWithContext( - env, - """ - fun f() { - val a: Int = 1 - a.let { 1.plus(1) } - a.let { that -> 1.plus(1) } - } - """ - ) - assertThat(findings).hasSize(2) - assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } - } + @Test + fun `reports unnecessary lets that can be changed to ordinary method call 5`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val a: Int = 1 + a.let { 1.plus(1) } + a.let { that -> 1.plus(1) } + } + """ + ) + assertThat(findings).hasSize(2) + assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } + } - @Test - fun `reports unnecessary lets that can be changed to ordinary method call 6`() { - val findings = subject.compileAndLintWithContext( - env, - """ - fun f() { - val a: Int = 1 - val x = a.let { 1.plus(1) } - val y = a.let { that -> 1.plus(1) } - } - """ - ) - assertThat(findings).hasSize(2) - assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } - } + @Test + fun `reports unnecessary lets that can be changed to ordinary method call 6`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val a: Int = 1 + val x = a.let { 1.plus(1) } + val y = a.let { that -> 1.plus(1) } + } + """ + ) + assertThat(findings).hasSize(2) + assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } + } - @Test - fun `reports unnecessary lets that can be replaced with an if`() { - val findings = subject.compileAndLintWithContext( - env, - """ - fun f() { - val a: Int? = null - a?.let { 1.plus(1) } - a?.let { that -> 1.plus(1) } - } - """ - ) - assertThat(findings).hasSize(2) - assertThat(findings).allMatch { it.message == MESSAGE_USE_IF } - } + @Test + fun `reports unnecessary lets that can be replaced with an if`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val a: Int? = null + a?.let { 1.plus(1) } + a?.let { that -> 1.plus(1) } + } + """ + ) + assertThat(findings).hasSize(2) + assertThat(findings).allMatch { it.message == MESSAGE_USE_IF } + } - @Test - fun `reports unnecessary lets that can be changed to ordinary method call 7`() { - val findings = subject.compileAndLintWithContext( - env, - """ - fun f() { - val a: Int? = null - a.let { print(it) } - a.let { that -> print(that) } - } - """ - ) - assertThat(findings).hasSize(2) - assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } - } + @Test + fun `reports unnecessary lets that can be changed to ordinary method call 7`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val a: Int? = null + a.let { print(it) } + a.let { that -> print(that) } + } + """ + ) + assertThat(findings).hasSize(2) + assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } + } - @Test - fun `reports use of let without the safe call operator when we use an argument`() { - val findings = subject.compileAndLintWithContext( - env, - """ - fun f() { - val f: (Int?) -> Boolean = { true } - val a: Int? = null - a.let(f) - } - """ - ) - assertThat(findings).hasSize(1) - assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } - } + @Test + fun `reports use of let without the safe call operator when we use an argument`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val f: (Int?) -> Boolean = { true } + val a: Int? = null + a.let(f) + } + """ + ) + assertThat(findings).hasSize(1) + assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } + } - @Test - fun `does not report lets used for function calls 1`() { - val findings = subject.compileAndLintWithContext( - env, - """ - fun f() { - val a: Int? = null - a?.let { print(it) } - a?.let { that -> 1.plus(that) } - } - """ - ) - assertThat(findings).isEmpty() - } + @Test + fun `does not report lets used for function calls 1`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val a: Int? = null + a?.let { print(it) } + a?.let { that -> 1.plus(that) } + } + """ + ) + assertThat(findings).isEmpty() + } - @Test - fun `does not report lets used for function calls 2`() { - val findings = subject.compileAndLintWithContext( - env, - """ - fun f() { - val a: Int? = null - a?.let { that -> 1.plus(that) }?.let { print(it) } - } - """ - ) - assertThat(findings).isEmpty() - } + @Test + fun `does not report lets used for function calls 2`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val a: Int? = null + a?.let { that -> 1.plus(that) }?.let { print(it) } + } + """ + ) + assertThat(findings).isEmpty() + } - @Test - fun `does not report 'can be replaced by if' because you will need an else too`() { - val findings = subject.compileAndLintWithContext( - env, - """ - fun f() { - val a: Int? = null - val x = a?.let { 1.plus(1) } - val y = a?.let { that -> 1.plus(1) } - } - """ - ) - assertThat(findings).isEmpty() - } + @Test + fun `does not report 'can be replaced by if' because you will need an else too`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val a: Int? = null + val x = a?.let { 1.plus(1) } + val y = a?.let { that -> 1.plus(1) } + } + """ + ) + assertThat(findings).isEmpty() + } - @Test - fun `does not report a let where returned value is used - #2987`() { - val findings = subject.compileAndLintWithContext( - env, - """ - fun f() { - val a = listOf?>(listOf("")) - .map { list -> list?.let { it + it } } - } - """ - ) - assertThat(findings).isEmpty() - } + @Test + fun `does not report a let where returned value is used - #2987`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val a = listOf?>(listOf("")) + .map { list -> list?.let { it + it } } + } + """ + ) + assertThat(findings).isEmpty() + } - @Test - fun `does not report use of let with the safe call operator when we use an argument`() { - val findings = subject.compileAndLintWithContext( - env, - """ - fun f() { - val f: (Int?) -> Boolean = { true } - val a: Int? = null - a?.let(f) - } - """ - ) - assertThat(findings).hasSize(0) - } + @Test + fun `does not report use of let with the safe call operator when we use an argument`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val f: (Int?) -> Boolean = { true } + val a: Int? = null + a?.let(f) + } + """ + ) + assertThat(findings).hasSize(0) + } - @Test - fun `does not report lets with lambda body containing more than one statement`() { - val findings = subject.compileAndLintWithContext( - env, - """ - fun f() { - val a: Int? = null - val b: Int = 1 - b.let { - it.plus(1) - it.plus(2) - } - a?.let { - it.plus(1) - it.plus(2) - } - b.let { that -> - that.plus(1) - that.plus(2) - } - a?.let { that -> - that.plus(1) - that.plus(2) - } - a?.let { that -> - 1.plus(that) - } - ?.let { - it.plus(1) - it.plus(2) - } + @Test + fun `does not report lets with lambda body containing more than one statement`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val a: Int? = null + val b: Int = 1 + b.let { + it.plus(1) + it.plus(2) } - """ - ) - assertThat(findings).isEmpty() - } - - @Test - fun `does not report lets where it is used multiple times`() { - val findings = subject.compileAndLintWithContext( - env, - """ - fun f() { - val a: Int? = null - val b: Int = 1 - a?.let { it.plus(it) } - b.let { it.plus(it) } - a?.let { foo -> foo.plus(foo) } - b.let { foo -> foo.plus(foo) } + a?.let { + it.plus(1) + it.plus(2) } - """ - ) - assertThat(findings).isEmpty() - } - - @Nested - inner class `destructuring declarations` { - @Test - fun `does not report 'let' when parameters are used more than once`() { - val content = """ - data class Foo(val a: Int, val b: Int) - - fun test(foo: Foo) { - foo.let { (a, b) -> a + b } + b.let { that -> + that.plus(1) + that.plus(2) + } + a?.let { that -> + that.plus(1) + that.plus(2) + } + a?.let { that -> + 1.plus(that) + } + ?.let { + it.plus(1) + it.plus(2) } - """ - val findings = subject.compileAndLintWithContext(env, content) - assertThat(findings).isEmpty() } + """ + ) + assertThat(findings).isEmpty() + } - @Test - fun `does not report 'let' with a safe call when a parameter is used more than once`() { - val content = """ - data class Foo(val a: Int, val b: Int) - - fun test(foo: Foo) { - foo.let { (a, _) -> a + a } - } - """ - val findings = subject.compileAndLintWithContext(env, content) - assertThat(findings).isEmpty() + @Test + fun `does not report lets where it is used multiple times`() { + val findings = subject.compileAndLintWithContext( + env, + """ + fun f() { + val a: Int? = null + val b: Int = 1 + a?.let { it.plus(it) } + b.let { it.plus(it) } + a?.let { foo -> foo.plus(foo) } + b.let { foo -> foo.plus(foo) } } + """ + ) + assertThat(findings).isEmpty() + } - @Test - fun `does not report 'let' when parameters with types are used more than once`() { - val content = """ - data class Foo(val a: Int, val b: Int) - - fun test(foo: Foo) { - foo.let { (a: Int, b: Int) -> a + b } - } - """ - val findings = subject.compileAndLintWithContext(env, content) - assertThat(findings).isEmpty() + @Nested + inner class `destructuring declarations` { + @Test + fun `does not report 'let' when parameters are used more than once`() { + val content = """ + data class Foo(val a: Int, val b: Int) + + fun test(foo: Foo) { + foo.let { (a, b) -> a + b } } + """ + val findings = subject.compileAndLintWithContext(env, content) + assertThat(findings).isEmpty() + } - @Test - fun `reports 'let' when parameters are used only once`() { - val content = """ - data class Foo(val a: Int, val b: Int) - - fun test(foo: Foo) { - foo.let { (a, _) -> a } - } - """ - val findings = subject.compileAndLintWithContext(env, content) - assertThat(findings).hasSize(1) - assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } + @Test + fun `does not report 'let' with a safe call when a parameter is used more than once`() { + val content = """ + data class Foo(val a: Int, val b: Int) + + fun test(foo: Foo) { + foo.let { (a, _) -> a + a } } + """ + val findings = subject.compileAndLintWithContext(env, content) + assertThat(findings).isEmpty() + } - @Test - fun `reports 'let' with a safe call when parameters are used only once`() { - val content = """ - data class Foo(val a: Int, val b: Int) - - fun test(foo: Foo?) { - foo?.let { (_, b) -> b.plus(1) } - } - """ - val findings = subject.compileAndLintWithContext(env, content) - assertThat(findings).hasSize(1) - assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } + @Test + fun `does not report 'let' when parameters with types are used more than once`() { + val content = """ + data class Foo(val a: Int, val b: Int) + + fun test(foo: Foo) { + foo.let { (a: Int, b: Int) -> a + b } } + """ + val findings = subject.compileAndLintWithContext(env, content) + assertThat(findings).isEmpty() + } - @Test - fun `reports 'let' when parameters are not used`() { - val content = """ - data class Foo(val a: Int, val b: Int) - - fun test(foo: Foo) { - foo.let { (_, _) -> 0 } - } - """ - val findings = subject.compileAndLintWithContext(env, content) - assertThat(findings).hasSize(1) - assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } + @Test + fun `reports 'let' when parameters are used only once`() { + val content = """ + data class Foo(val a: Int, val b: Int) + + fun test(foo: Foo) { + foo.let { (a, _) -> a } } + """ + val findings = subject.compileAndLintWithContext(env, content) + assertThat(findings).hasSize(1) + assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } + } - @Test - fun `reports 'let' with a safe call when parameters are not used`() { - val content = """ - data class Foo(val a: Int, val b: Int) - - fun test(foo: Foo?) { - foo?.let { (_, _) -> 0 } - } - """ - val findings = subject.compileAndLintWithContext(env, content) - assertThat(findings).hasSize(1) - assertThat(findings).allMatch { it.message == MESSAGE_USE_IF } + @Test + fun `reports 'let' with a safe call when parameters are used only once`() { + val content = """ + data class Foo(val a: Int, val b: Int) + + fun test(foo: Foo?) { + foo?.let { (_, b) -> b.plus(1) } } + """ + val findings = subject.compileAndLintWithContext(env, content) + assertThat(findings).hasSize(1) + assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } } @Test - fun `reports when implicit parameter isn't used`() { + fun `reports 'let' when parameters are not used`() { val content = """ - fun test(value: Int?) { - value?.let { - listOf(1).map { it } - } - } + data class Foo(val a: Int, val b: Int) + + fun test(foo: Foo) { + foo.let { (_, _) -> 0 } + } """ val findings = subject.compileAndLintWithContext(env, content) assertThat(findings).hasSize(1) - assertThat(findings).allMatch { it.message == MESSAGE_USE_IF } + assertThat(findings).allMatch { it.message == MESSAGE_OMIT_LET } } @Test - fun `does not report when an implicit parameter is used in an inner lambda`() { + fun `reports 'let' with a safe call when parameters are not used`() { val content = """ - fun callMe(callback: () -> Unit) { - callback() - } - - fun test(value: Int?) { - value?.let { - callMe { - println(it) - } - } - } + data class Foo(val a: Int, val b: Int) + + fun test(foo: Foo?) { + foo?.let { (_, _) -> 0 } + } """ val findings = subject.compileAndLintWithContext(env, content) - assertThat(findings).isEmpty() + assertThat(findings).hasSize(1) + assertThat(findings).allMatch { it.message == MESSAGE_USE_IF } } } + + @Test + fun `reports when implicit parameter isn't used`() { + val content = """ + fun test(value: Int?) { + value?.let { + listOf(1).map { it } + } + } + """ + val findings = subject.compileAndLintWithContext(env, content) + assertThat(findings).hasSize(1) + assertThat(findings).allMatch { it.message == MESSAGE_USE_IF } + } + + @Test + fun `does not report when an implicit parameter is used in an inner lambda`() { + val content = """ + fun callMe(callback: () -> Unit) { + callback() + } + + fun test(value: Int?) { + value?.let { + callMe { + println(it) + } + } + } + """ + val findings = subject.compileAndLintWithContext(env, content) + assertThat(findings).isEmpty() + } } private const val MESSAGE_OMIT_LET = "let expression can be omitted" diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryParenthesesSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryParenthesesSpec.kt index d8abb8656a1..e896d9c2462 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryParenthesesSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryParenthesesSpec.kt @@ -3,190 +3,185 @@ package io.gitlab.arturbosch.detekt.rules.style import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.test.lint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class UnnecessaryParenthesesSpec { val subject = UnnecessaryParentheses(Config.empty) - @Nested - inner class `UnnecessaryParentheses rule` { - - @Test - fun `with unnecessary parentheses on val assignment`() { - val code = "val local = (5)" - assertThat(subject.lint(code)).hasSize(1) - } - - @Test - fun `with unnecessary parentheses on val assignment operation`() { - val code = "val local = (5 + 3)" - assertThat(subject.lint(code)).hasSize(1) - } - - @Test - fun `with unnecessary parentheses on function call`() { - val code = "val local = 3.plus((5))" - assertThat(subject.lint(code)).hasSize(1) - } - - @Test - fun `unnecessary parentheses in other parentheses`() { - val code = """ - fun x(a: String, b: String) { - if ((a equals b)) { - println("Test") - } - } - """ - assertThat(subject.lint(code)).hasSize(1) - } - - @Test - fun `does not report unnecessary parentheses around lambdas`() { - val code = """ - fun function (a: (input: String) -> Unit) { - a.invoke("TEST") + @Test + fun `with unnecessary parentheses on val assignment`() { + val code = "val local = (5)" + assertThat(subject.lint(code)).hasSize(1) + } + + @Test + fun `with unnecessary parentheses on val assignment operation`() { + val code = "val local = (5 + 3)" + assertThat(subject.lint(code)).hasSize(1) + } + + @Test + fun `with unnecessary parentheses on function call`() { + val code = "val local = 3.plus((5))" + assertThat(subject.lint(code)).hasSize(1) + } + + @Test + fun `unnecessary parentheses in other parentheses`() { + val code = """ + fun x(a: String, b: String) { + if ((a equals b)) { + println("Test") } + } + """ + assertThat(subject.lint(code)).hasSize(1) + } + + @Test + fun `does not report unnecessary parentheses around lambdas`() { + val code = """ + fun function (a: (input: String) -> Unit) { + a.invoke("TEST") + } + + fun test() { + function({ input -> println(input) }) + } + """ + assertThat(subject.lint(code)).isEmpty() + } + + @Test + fun `doesn't report function calls containing lambdas and other parameters`() { + val code = """ + fun function (integer: Int, a: (input: String) -> Unit) { + a.invoke("TEST") + } + + fun test() { + function(1, { input -> println(input) }) + } + """ + assertThat(subject.lint(code)).isEmpty() + } + + @Test + fun `does not report unnecessary parentheses when assigning a lambda to a val`() { + val code = """ + fun f() { + instance.copy(value = { false }) + } + """ + assertThat(subject.lint(code)).isEmpty() + } - fun test() { - function({ input -> println(input) }) + @Test + fun `does not report well behaved parentheses`() { + val code = """ + fun x(a: String, b: String) { + if (a equals b) { + println("Test") } - """ - assertThat(subject.lint(code)).isEmpty() - } - - @Test - fun `doesn't report function calls containing lambdas and other parameters`() { - val code = """ - fun function (integer: Int, a: (input: String) -> Unit) { - a.invoke("TEST") + } + """ + assertThat(subject.lint(code)).isEmpty() + } + + @Test + fun `does not report well behaved parentheses in super constructors`() { + val code = """ + class TestSpek : SubjectSpek({ + describe("a simple test") { + it("should do something") { + } } + }) + """ + assertThat(subject.lint(code)).isEmpty() + } - fun test() { - function(1, { input -> println(input) }) + @Test + fun `does not report well behaved parentheses in constructors`() { + val code = """ + class TestSpek({ + describe("a simple test") { + it("should do something") { + } } - """ - assertThat(subject.lint(code)).isEmpty() - } - - @Test - fun `does not report unnecessary parentheses when assigning a lambda to a val`() { - val code = """ - fun f() { - instance.copy(value = { false }) + }) + """ + assertThat(subject.lint(code)).isEmpty() + } + + @Test + fun `should not report lambdas within super constructor calls`() { + val code = """ + class Clazz( + private val func: (X, Y) -> Z + ) { + constructor() : this({ first, second -> true }) + } + """ + assertThat(subject.lint(code)).isEmpty() + } + + @Test + fun `should not report call to function with two lambda parameters with one as block body`() { + val code = """ + class Clazz { + fun test(first: (Int) -> Unit, second: (Int) -> Unit) { + first(1) + second(2) } - """ - assertThat(subject.lint(code)).isEmpty() - } - - @Test - fun `does not report well behaved parentheses`() { - val code = """ - fun x(a: String, b: String) { - if (a equals b) { - println("Test") - } + + fun call() { + test({ println(it) }) { println(it) } } - """ - assertThat(subject.lint(code)).isEmpty() - } - - @Test - fun `does not report well behaved parentheses in super constructors`() { - val code = """ - class TestSpek : SubjectSpek({ - describe("a simple test") { - it("should do something") { - } - } - }) - """ - assertThat(subject.lint(code)).isEmpty() - } - - @Test - fun `does not report well behaved parentheses in constructors`() { - val code = """ - class TestSpek({ - describe("a simple test") { - it("should do something") { - } - } - }) - """ - assertThat(subject.lint(code)).isEmpty() - } - - @Test - fun `should not report lambdas within super constructor calls`() { - val code = """ - class Clazz( - private val func: (X, Y) -> Z - ) { - constructor() : this({ first, second -> true }) + } + """ + assertThat(subject.lint(code)).isEmpty() + } + + @Test + fun `should not report call to function with two lambda parameters`() { + val code = """ + class Clazz { + fun test(first: (Int) -> Unit, second: (Int) -> Unit) { + first(1) + second(2) } - """ - assertThat(subject.lint(code)).isEmpty() - } - - @Test - fun `should not report call to function with two lambda parameters with one as block body`() { - val code = """ - class Clazz { - fun test(first: (Int) -> Unit, second: (Int) -> Unit) { - first(1) - second(2) - } - fun call() { - test({ println(it) }) { println(it) } - } + fun call() { + test({ println(it) }, { println(it) }) } - """ - assertThat(subject.lint(code)).isEmpty() - } - - @Test - fun `should not report call to function with two lambda parameters`() { - val code = """ - class Clazz { - fun test(first: (Int) -> Unit, second: (Int) -> Unit) { - first(1) - second(2) - } + } + """ + assertThat(subject.lint(code)).isEmpty() + } - fun call() { - test({ println(it) }, { println(it) }) - } + @Test + fun `should not report call to function with multiple lambdas as parameters but also other parameters`() { + val code = """ + class Clazz { + fun test(text: String, first: () -> Unit, second: () -> Unit) { + first() + second() } - """ - assertThat(subject.lint(code)).isEmpty() - } - - @Test - fun `should not report call to function with multiple lambdas as parameters but also other parameters`() { - val code = """ - class Clazz { - fun test(text: String, first: () -> Unit, second: () -> Unit) { - first() - second() - } - fun call() { - test("hello", { println(it) }) { println(it) } - } + fun call() { + test("hello", { println(it) }) { println(it) } } - """ - assertThat(subject.lint(code)).isEmpty() - } - - @Test - fun `should not report interface delegation with parenthesis - #3851`() { - val code = """ - class Clazz: Comparable by ("hello".filter { it != 'l' }) - """ - assertThat(subject.lint(code)).isEmpty() - } + } + """ + assertThat(subject.lint(code)).isEmpty() + } + + @Test + fun `should not report interface delegation with parenthesis - #3851`() { + val code = """ + class Clazz: Comparable by ("hello".filter { it != 'l' }) + """ + assertThat(subject.lint(code)).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UntilInsteadOfRangeToSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UntilInsteadOfRangeToSpec.kt index dfa4ba796a7..9dd2adfbd02 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UntilInsteadOfRangeToSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UntilInsteadOfRangeToSpec.kt @@ -4,79 +4,74 @@ import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.lint import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class UntilInsteadOfRangeToSpec { val subject = UntilInsteadOfRangeTo(Config.empty) - @Nested - inner class `UntilInsteadOfRangeTo rule` { - - @Test - @DisplayName("reports for '..'") - fun reportsForDoubleDotsInForIterator() { - val code = """ - fun f() { - for (i in 0 .. 10 - 1) {} - } - """ - val findings = subject.lint(code) - assertThat(findings).hasSize(1) - assertThat(findings[0]).hasMessage("'..' call can be replaced with 'until'") - } + @Test + @DisplayName("reports for '..'") + fun reportsForDoubleDotsInForIterator() { + val code = """ + fun f() { + for (i in 0 .. 10 - 1) {} + } + """ + val findings = subject.lint(code) + assertThat(findings).hasSize(1) + assertThat(findings[0]).hasMessage("'..' call can be replaced with 'until'") + } - @Test - fun `does not report if rangeTo not used`() { - val code = """ - fun f() { - for (i in 0 until 10 - 1) {} - for (i in 10 downTo 2 - 1) {} - } - """ - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `does not report if rangeTo not used`() { + val code = """ + fun f() { + for (i in 0 until 10 - 1) {} + for (i in 10 downTo 2 - 1) {} + } + """ + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `does not report if upper value isn't a binary expression`() { - val code = """ - fun f() { - for (i in 0 .. 10) {} - } - """ - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `does not report if upper value isn't a binary expression`() { + val code = """ + fun f() { + for (i in 0 .. 10) {} + } + """ + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `does not report if not minus one`() { - val code = """ - fun f() { - for (i in 0 .. 10 + 1) {} - for (i in 0 .. 10 - 2) {} - } - """ - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `does not report if not minus one`() { + val code = """ + fun f() { + for (i in 0 .. 10 + 1) {} + for (i in 0 .. 10 - 2) {} + } + """ + assertThat(subject.lint(code)).isEmpty() + } - @Test - @DisplayName("reports for '..'") - fun reportsForDoubleDots() { - val code = "val r = 0 .. 10 - 1" - assertThat(subject.lint(code)).hasSize(1) - } + @Test + @DisplayName("reports for '..'") + fun reportsForDoubleDots() { + val code = "val r = 0 .. 10 - 1" + assertThat(subject.lint(code)).hasSize(1) + } - @Test - fun `does not report binary expressions without a range operator`() { - val code = "val sum = 1 + 2" - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `does not report binary expressions without a range operator`() { + val code = "val sum = 1 + 2" + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `reports for 'rangeTo'`() { - val code = "val r = 0.rangeTo(10 - 1)" - val findings = subject.lint(code) - assertThat(findings).hasSize(1) - assertThat(findings[0]).hasMessage("'rangeTo' call can be replaced with 'until'") - } + @Test + fun `reports for 'rangeTo'`() { + val code = "val r = 0.rangeTo(10 - 1)" + val findings = subject.lint(code) + assertThat(findings).hasSize(1) + assertThat(findings[0]).hasMessage("'rangeTo' call can be replaced with 'until'") } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnusedImportsSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnusedImportsSpec.kt index 7fa29ee9585..81197fb3ecd 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnusedImportsSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnusedImportsSpec.kt @@ -5,613 +5,608 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.lintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class UnusedImportsSpec(val env: KotlinCoreEnvironment) { val subject = UnusedImports(Config.empty) - @Nested - inner class `UnusedImports rule` { + @Test + fun `does not report infix operators`() { + val main = """ + import tasks.success - @Test - fun `does not report infix operators`() { - val main = """ - import tasks.success + fun task(f: () -> Unit) = 1 - fun task(f: () -> Unit) = 1 - - fun main() { - task { - } success { - } + fun main() { + task { + } success { } - """ - val additional = """ - package tasks - - infix fun Int.success(f: () -> Unit) {} - """ - assertThat(subject.lintWithContext(env, main, additional)).isEmpty() - } - - @Test - fun `does not report imports in documentation`() { - val main = """ - import tasks.success - import tasks.failure - import tasks.undefined - - fun task(f: () -> Unit) = 1 + } + """ + val additional = """ + package tasks - /** - * Reference to [failure] - */ - class Test { - /** Reference to [undefined]*/ - fun main() { - task { - } success { - } - } - } - """ - val additional = """ - package tasks - - infix fun Int.success(f: () -> Unit) {} - infix fun Int.failure(f: () -> Unit) {} - infix fun Int.undefined(f: () -> Unit) {} - """ - assertThat(subject.lintWithContext(env, main, additional)).isEmpty() - } + infix fun Int.success(f: () -> Unit) {} + """ + assertThat(subject.lintWithContext(env, main, additional)).isEmpty() + } - @Test - fun `should ignore import for link`() { - val main = """ - import tasks.success - import tasks.failure - import tasks.undefined + @Test + fun `does not report imports in documentation`() { + val main = """ + import tasks.success + import tasks.failure + import tasks.undefined - fun task(f: () -> Unit) = 1 + fun task(f: () -> Unit) = 1 - /** - * Reference [undefined][failure] - */ + /** + * Reference to [failure] + */ + class Test { + /** Reference to [undefined]*/ fun main() { task { } success { } - } - """ - val additional = """ - package tasks - - infix fun Int.success(f: () -> Unit) {} - infix fun Int.failure(f: () -> Unit) {} - infix fun Int.undefined(f: () -> Unit) {} - """ - val lint = subject.lintWithContext(env, main, additional) - with(lint) { - assertThat(this).hasSize(1) - assertThat(this[0].entity.signature).endsWith("import tasks.undefined") - } - } - - @Test - fun `reports imports from the current package`() { - val main = """ - package test - import test.SomeClass - - val a: SomeClass? = null - """ - val additional = """ - package test - - class SomeClass - """ - val lint = subject.lintWithContext(env, main, additional) - with(lint) { - assertThat(this).hasSize(1) - assertThat(this[0].entity.signature).endsWith("import test.SomeClass") + } } - } - - @Test - fun `does not report KDoc references with method calls`() { - val main = """ - package com.example - - import android.text.TextWatcher + """ + val additional = """ + package tasks + + infix fun Int.success(f: () -> Unit) {} + infix fun Int.failure(f: () -> Unit) {} + infix fun Int.undefined(f: () -> Unit) {} + """ + assertThat(subject.lintWithContext(env, main, additional)).isEmpty() + } - class Test { - /** - * [TextWatcher.beforeTextChanged] - */ - fun test() { - TODO() - } + @Test + fun `should ignore import for link`() { + val main = """ + import tasks.success + import tasks.failure + import tasks.undefined + + fun task(f: () -> Unit) = 1 + + /** + * Reference [undefined][failure] + */ + fun main() { + task { + } success { } - """ - val additional = """ - package android.text - - class TextWatcher { - fun beforeTextChanged() {} - } - """ - assertThat(subject.lintWithContext(env, main, additional)).isEmpty() + } + """ + val additional = """ + package tasks + + infix fun Int.success(f: () -> Unit) {} + infix fun Int.failure(f: () -> Unit) {} + infix fun Int.undefined(f: () -> Unit) {} + """ + val lint = subject.lintWithContext(env, main, additional) + with(lint) { + assertThat(this).hasSize(1) + assertThat(this[0].entity.signature).endsWith("import tasks.undefined") } + } - @Test - fun `reports imports with different cases`() { - val main = """ - import p.a - import p.B6 // positive - import p.B as B12 // positive - import p2.B as B2 - import p.C - import escaped.`when` - import escaped.`foo` // positive - import p.D - - /** reference to [D] */ - fun main() { - println(a()) - C.call() - fn(B2.NAME) - `when`() - } + @Test + fun `reports imports from the current package`() { + val main = """ + package test + import test.SomeClass + + val a: SomeClass? = null + """ + val additional = """ + package test + + class SomeClass + """ + val lint = subject.lintWithContext(env, main, additional) + with(lint) { + assertThat(this).hasSize(1) + assertThat(this[0].entity.signature).endsWith("import test.SomeClass") + } + } - fun fn(s: String) {} - """ - val p = """ - package p + @Test + fun `does not report KDoc references with method calls`() { + val main = """ + package com.example - fun a() {} - class B6 - class B - object C { - fun call() {} - } - class D - """ - val p2 = """ - package p2 + import android.text.TextWatcher - object B { - const val NAME = "" + class Test { + /** + * [TextWatcher.beforeTextChanged] + */ + fun test() { + TODO() } - """ - val escaped = """ - package escaped - - fun `when`() {} - fun `foo`() {} - """ - val lint = subject.lintWithContext(env, main, p, p2, escaped) - with(lint) { - assertThat(this).hasSize(3) - assertThat(this[0].entity.signature).contains("import p.B6") - assertThat(this[1].entity.signature).contains("import p.B as B12") - assertThat(this[2].entity.signature).contains("import escaped.`foo`") } - } + """ + val additional = """ + package android.text + + class TextWatcher { + fun beforeTextChanged() {} + } + """ + assertThat(subject.lintWithContext(env, main, additional)).isEmpty() + } - @Test - fun `does not report imports in same package when inner`() { - val main = """ - package test - - import test.Outer.Inner - - open class Something - - class Foo : Something() - """ - val additional = """ - package test - - class Outer { - class Inner - } - """ - val lint = subject.lintWithContext(env, main, additional) - with(lint) { - assertThat(this).isEmpty() + @Test + fun `reports imports with different cases`() { + val main = """ + import p.a + import p.B6 // positive + import p.B as B12 // positive + import p2.B as B2 + import p.C + import escaped.`when` + import escaped.`foo` // positive + import p.D + + /** reference to [D] */ + fun main() { + println(a()) + C.call() + fn(B2.NAME) + `when`() } - } - @Test - fun `does not report KDoc @see annotation linking to class`() { - val main = """ - import tasks.success - - /** - * Do something. - * @see success - */ - fun doSomething() - """ - val additional = """ - package tasks - - fun success() {} - """ - assertThat(subject.lintWithContext(env, main, additional)).isEmpty() - } + fun fn(s: String) {} + """ + val p = """ + package p - @Test - fun `does not report KDoc @see annotation linking to class with description`() { - val main = """ - import tasks.success + fun a() {} + class B6 + class B + object C { + fun call() {} + } + class D + """ + val p2 = """ + package p2 - /** - * Do something. - * @see success something - */ - fun doSomething() {} - """ - val additional = """ - package tasks - - fun success() {} - """ - assertThat(subject.lintWithContext(env, main, additional)).isEmpty() + object B { + const val NAME = "" + } + """ + val escaped = """ + package escaped + + fun `when`() {} + fun `foo`() {} + """ + val lint = subject.lintWithContext(env, main, p, p2, escaped) + with(lint) { + assertThat(this).hasSize(3) + assertThat(this[0].entity.signature).contains("import p.B6") + assertThat(this[1].entity.signature).contains("import p.B as B12") + assertThat(this[2].entity.signature).contains("import escaped.`foo`") } + } - @Test - fun `reports KDoc @see annotation that does not link to class`() { - val main = """ - import tasks.success - - /** - * Do something. - * @see something - */ - fun doSomething() {} - """ - val additional = """ - package tasks - - fun success() {} - """ - assertThat(subject.lintWithContext(env, main, additional)).hasSize(1) + @Test + fun `does not report imports in same package when inner`() { + val main = """ + package test + + import test.Outer.Inner + + open class Something + + class Foo : Something() + """ + val additional = """ + package test + + class Outer { + class Inner + } + """ + val lint = subject.lintWithContext(env, main, additional) + with(lint) { + assertThat(this).isEmpty() } + } - @Test - fun `reports KDoc @see annotation that links after description`() { - val main = """ - import tasks.success + @Test + fun `does not report KDoc @see annotation linking to class`() { + val main = """ + import tasks.success + + /** + * Do something. + * @see success + */ + fun doSomething() + """ + val additional = """ + package tasks + + fun success() {} + """ + assertThat(subject.lintWithContext(env, main, additional)).isEmpty() + } - /** - * Do something. - * @see something success - */ - fun doSomething() {} - """ - val additional = """ - package tasks - - fun success() {} - """ - assertThat(subject.lintWithContext(env, main, additional)).hasSize(1) - } + @Test + fun `does not report KDoc @see annotation linking to class with description`() { + val main = """ + import tasks.success + + /** + * Do something. + * @see success something + */ + fun doSomething() {} + """ + val additional = """ + package tasks + + fun success() {} + """ + assertThat(subject.lintWithContext(env, main, additional)).isEmpty() + } - @Test - fun `does not report imports in KDoc`() { - val main = """ - import tasks.success // here - import tasks.undefined // and here + @Test + fun `reports KDoc @see annotation that does not link to class`() { + val main = """ + import tasks.success + + /** + * Do something. + * @see something + */ + fun doSomething() {} + """ + val additional = """ + package tasks + + fun success() {} + """ + assertThat(subject.lintWithContext(env, main, additional)).hasSize(1) + } - /** - * Do something. - * @throws success when ... - * @exception success when ... - * @see undefined - * @sample success when ... - */ - fun doSomething() {} - """ - val additional = """ - package tasks - - fun success() {} - fun undefined() {} - """ - assertThat(subject.lintWithContext(env, main, additional)).isEmpty() - } + @Test + fun `reports KDoc @see annotation that links after description`() { + val main = """ + import tasks.success + + /** + * Do something. + * @see something success + */ + fun doSomething() {} + """ + val additional = """ + package tasks + + fun success() {} + """ + assertThat(subject.lintWithContext(env, main, additional)).hasSize(1) + } - @Test - fun `should not report import alias as unused when the alias is used`() { - val main = """ - import test.forEach as foreach - fun foo() = listOf().iterator().foreach {} - """ - val additional = """ - package test - fun Iterator.forEach(f: () -> Unit) {} - """ - assertThat(subject.lintWithContext(env, main, additional)).isEmpty() - } + @Test + fun `does not report imports in KDoc`() { + val main = """ + import tasks.success // here + import tasks.undefined // and here + + /** + * Do something. + * @throws success when ... + * @exception success when ... + * @see undefined + * @sample success when ... + */ + fun doSomething() {} + """ + val additional = """ + package tasks + + fun success() {} + fun undefined() {} + """ + assertThat(subject.lintWithContext(env, main, additional)).isEmpty() + } - @Test - fun `should not report used alias even when import is from same package`() { - val main = """ - package com.example + @Test + fun `should not report import alias as unused when the alias is used`() { + val main = """ + import test.forEach as foreach + fun foo() = listOf().iterator().foreach {} + """ + val additional = """ + package test + fun Iterator.forEach(f: () -> Unit) {} + """ + assertThat(subject.lintWithContext(env, main, additional)).isEmpty() + } - import com.example.foo as myFoo // from same package but with alias, check alias usage - import com.example.other.foo as otherFoo // not from package with used alias + @Test + fun `should not report used alias even when import is from same package`() { + val main = """ + package com.example - fun f(): Boolean { - return myFoo() == otherFoo() - } - """ - val additional1 = """ - package com.example - fun foo() = 1 - """ - val additional2 = """ - package com.example.other - fun foo() = 1 - """ - assertThat(subject.lintWithContext(env, main, additional1, additional2)).isEmpty() - } + import com.example.foo as myFoo // from same package but with alias, check alias usage + import com.example.other.foo as otherFoo // not from package with used alias - @Test - fun `should not report import of provideDelegate operator overload - #1608`() { - val main = """ - import org.gradle.kotlin.dsl.Foo - import org.gradle.kotlin.dsl.provideDelegate // this line specifically should not be reported - - class DumpVersionProperties { - private val dumpVersionProperties by Foo() - } - """ - val additional = """ - package org.gradle.kotlin.dsl - - import kotlin.reflect.KProperty - - class Foo - - operator fun Foo.provideDelegate( - thisRef: T, - prop: KProperty<*> - ) = lazy { "" } - """ - assertThat(subject.lintWithContext(env, main, additional)).isEmpty() - } + fun f(): Boolean { + return myFoo() == otherFoo() + } + """ + val additional1 = """ + package com.example + fun foo() = 1 + """ + val additional2 = """ + package com.example.other + fun foo() = 1 + """ + assertThat(subject.lintWithContext(env, main, additional1, additional2)).isEmpty() + } - @Test - fun `should not report import of componentN operator`() { - val main = """ - import com.example.MyClass.component1 - import com.example.MyClass.component2 - import com.example.MyClass.component543 + @Test + fun `should not report import of provideDelegate operator overload - #1608`() { + val main = """ + import org.gradle.kotlin.dsl.Foo + import org.gradle.kotlin.dsl.provideDelegate // this line specifically should not be reported + + class DumpVersionProperties { + private val dumpVersionProperties by Foo() + } + """ + val additional = """ + package org.gradle.kotlin.dsl + + import kotlin.reflect.KProperty + + class Foo + + operator fun Foo.provideDelegate( + thisRef: T, + prop: KProperty<*> + ) = lazy { "" } + """ + assertThat(subject.lintWithContext(env, main, additional)).isEmpty() + } - fun test() { - val (a, b) = MyClass(1, 2) - } - """ - val additional = """ - package com.example - data class MyClass(val a: Int, val b: Int) - """ + @Test + fun `should not report import of componentN operator`() { + val main = """ + import com.example.MyClass.component1 + import com.example.MyClass.component2 + import com.example.MyClass.component543 - assertThat(subject.lintWithContext(env, main, additional)).isEmpty() - } + fun test() { + val (a, b) = MyClass(1, 2) + } + """ + val additional = """ + package com.example + data class MyClass(val a: Int, val b: Int) + """ - @Test - fun `should report import of identifiers with component in the name`() { - val main = """ - import com.example.TestComponent - import com.example.component1.Unused - import com.example.components - import com.example.component1AndSomethingElse + assertThat(subject.lintWithContext(env, main, additional)).isEmpty() + } - fun test() { - println("Testing") - } - """ - val additional1 = """ - package com.example - class TestComponent - fun components() {} - fun component1AndSomethingElse() {} - """ - val additional2 = """ - package com.example.component1 - class Unused - """ - val lint = subject.lintWithContext(env, main, additional1, additional2) - - with(lint) { - assertThat(this).hasSize(4) - assertThat(this[0].entity.signature).endsWith("import com.example.TestComponent") - assertThat(this[1].entity.signature).endsWith("import com.example.component1.Unused") - assertThat(this[2].entity.signature).endsWith("import com.example.components") - assertThat(this[3].entity.signature).endsWith("import com.example.component1AndSomethingElse") + @Test + fun `should report import of identifiers with component in the name`() { + val main = """ + import com.example.TestComponent + import com.example.component1.Unused + import com.example.components + import com.example.component1AndSomethingElse + + fun test() { + println("Testing") } + """ + val additional1 = """ + package com.example + class TestComponent + fun components() {} + fun component1AndSomethingElse() {} + """ + val additional2 = """ + package com.example.component1 + class Unused + """ + val lint = subject.lintWithContext(env, main, additional1, additional2) + + with(lint) { + assertThat(this).hasSize(4) + assertThat(this[0].entity.signature).endsWith("import com.example.TestComponent") + assertThat(this[1].entity.signature).endsWith("import com.example.component1.Unused") + assertThat(this[2].entity.signature).endsWith("import com.example.components") + assertThat(this[3].entity.signature).endsWith("import com.example.component1AndSomethingElse") } + } - @Test - fun `reports when same name identifiers are imported and used`() { - val mainFile = """ - import foo.test - import bar.test - fun main() { - test(1) - } - """ - val additionalFile1 = """ - package foo - fun test(i: Int) {} - """ - val additionalFile2 = """ - package bar - fun test(s: String) {} - """ - val findings = subject.lintWithContext(env, mainFile, additionalFile1, additionalFile2) - assertThat(findings).hasSize(1) - assertThat(findings[0].entity.signature).endsWith("import bar.test") - } + @Test + fun `reports when same name identifiers are imported and used`() { + val mainFile = """ + import foo.test + import bar.test + fun main() { + test(1) + } + """ + val additionalFile1 = """ + package foo + fun test(i: Int) {} + """ + val additionalFile2 = """ + package bar + fun test(s: String) {} + """ + val findings = subject.lintWithContext(env, mainFile, additionalFile1, additionalFile2) + assertThat(findings).hasSize(1) + assertThat(findings[0].entity.signature).endsWith("import bar.test") + } - @Test - fun `does not report when used as a type`() { - val code = """ - import java.util.HashMap - - fun doesNothing(thing: HashMap) { - } - """ - val findings = subject.lintWithContext(env, code) - assertThat(findings).isEmpty() - } + @Test + fun `does not report when used as a type`() { + val code = """ + import java.util.HashMap + + fun doesNothing(thing: HashMap) { + } + """ + val findings = subject.lintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `does not report when used in a class literal expression`() { - val code = """ - import java.util.HashMap - import kotlin.reflect.KClass - - annotation class Ann(val value: KClass<*>) - - @Ann(HashMap::class) - fun foo() {} - """ - val findings = subject.lintWithContext(env, code) - assertThat(findings).isEmpty() - } + @Test + fun `does not report when used in a class literal expression`() { + val code = """ + import java.util.HashMap + import kotlin.reflect.KClass + + annotation class Ann(val value: KClass<*>) + + @Ann(HashMap::class) + fun foo() {} + """ + val findings = subject.lintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `does not report when used as a constructor call`() { - val mainFile = """ - import x.y.z.Foo - - val foo = Foo() - """ - val additionalFile = """ - package x.y.z - - class Foo - """ - val findings = subject.lintWithContext(env, mainFile, additionalFile) - assertThat(findings).isEmpty() - } + @Test + fun `does not report when used as a constructor call`() { + val mainFile = """ + import x.y.z.Foo + + val foo = Foo() + """ + val additionalFile = """ + package x.y.z + + class Foo + """ + val findings = subject.lintWithContext(env, mainFile, additionalFile) + assertThat(findings).isEmpty() + } - @Test - fun `does not report when used as a annotation`() { - val mainFile = """ - import x.y.z.Ann - - @Ann - fun foo() {} - """ - val additionalFile = """ - package x.y.z - - annotation class Ann - """ - val findings = subject.lintWithContext(env, mainFile, additionalFile) - assertThat(findings).isEmpty() - } + @Test + fun `does not report when used as a annotation`() { + val mainFile = """ + import x.y.z.Ann + + @Ann + fun foo() {} + """ + val additionalFile = """ + package x.y.z + + annotation class Ann + """ + val findings = subject.lintWithContext(env, mainFile, additionalFile) + assertThat(findings).isEmpty() + } - @Test - fun `does not report companion object`() { - val mainFile = """ - import x.y.z.Foo - - val x = Foo - """ - val additionalFile = """ - package x.y.z - - class Foo { - companion object - } - """ - val findings = subject.lintWithContext(env, mainFile, additionalFile) - assertThat(findings).isEmpty() - } + @Test + fun `does not report companion object`() { + val mainFile = """ + import x.y.z.Foo + + val x = Foo + """ + val additionalFile = """ + package x.y.z + + class Foo { + companion object + } + """ + val findings = subject.lintWithContext(env, mainFile, additionalFile) + assertThat(findings).isEmpty() + } - @Test - fun `does not report companion object that calls function`() { - val mainFile = """ - import x.y.z.Foo - - val x = Foo.create() - """ - val additionalFile = """ - package x.y.z - - class Foo { - companion object { - fun create(): Foo = Foo() - } + @Test + fun `does not report companion object that calls function`() { + val mainFile = """ + import x.y.z.Foo + + val x = Foo.create() + """ + val additionalFile = """ + package x.y.z + + class Foo { + companion object { + fun create(): Foo = Foo() } - """ - val findings = subject.lintWithContext(env, mainFile, additionalFile) - assertThat(findings).isEmpty() - } + } + """ + val findings = subject.lintWithContext(env, mainFile, additionalFile) + assertThat(findings).isEmpty() + } - @Test - fun `does not report companion object that references variable`() { - val mainFile = """ - import x.y.z.Foo - - val x = Foo.BAR - """ - val additionalFile = """ - package x.y.z - - class Foo { - companion object { - const val BAR = 1 - } + @Test + fun `does not report companion object that references variable`() { + val mainFile = """ + import x.y.z.Foo + + val x = Foo.BAR + """ + val additionalFile = """ + package x.y.z + + class Foo { + companion object { + const val BAR = 1 } - """ - val findings = subject.lintWithContext(env, mainFile, additionalFile) - assertThat(findings).isEmpty() - } + } + """ + val findings = subject.lintWithContext(env, mainFile, additionalFile) + assertThat(findings).isEmpty() + } - @Test - fun `does not report static import`() { - val mainFile = """ - import x.y.z.FetchType - - val x = FetchType.LAZY - """ - val additionalFile = """ - package x.y.z - - enum class FetchType { - LAZY - } - """ - assertThat(subject.lintWithContext(env, mainFile, additionalFile)).isEmpty() - } + @Test + fun `does not report static import`() { + val mainFile = """ + import x.y.z.FetchType + + val x = FetchType.LAZY + """ + val additionalFile = """ + package x.y.z + + enum class FetchType { + LAZY + } + """ + assertThat(subject.lintWithContext(env, mainFile, additionalFile)).isEmpty() + } - @Test - fun `does not report annotations used as attributes - #3246`() { - val mainFile = """ - import x.y.z.AnnotationA - import x.y.z.AnnotationB - - class SomeClass { - @AnnotationB(attribute = AnnotationA()) - val someProp: Int = 42 - } - """ - val additionalFile = """ - package x.y.z - - annotation class AnnotationA - annotation class AnnotationB(val attribute: AnnotationA) - """ - assertThat(subject.lintWithContext(env, mainFile, additionalFile)).isEmpty() - } + @Test + fun `does not report annotations used as attributes - #3246`() { + val mainFile = """ + import x.y.z.AnnotationA + import x.y.z.AnnotationB + + class SomeClass { + @AnnotationB(attribute = AnnotationA()) + val someProp: Int = 42 + } + """ + val additionalFile = """ + package x.y.z + + annotation class AnnotationA + annotation class AnnotationB(val attribute: AnnotationA) + """ + assertThat(subject.lintWithContext(env, mainFile, additionalFile)).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseAnyOrNoneInsteadOfFindSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseAnyOrNoneInsteadOfFindSpec.kt index 1aa932300ea..0280f2a52a3 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseAnyOrNoneInsteadOfFindSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseAnyOrNoneInsteadOfFindSpec.kt @@ -5,106 +5,102 @@ import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class UseAnyOrNoneInsteadOfFindSpec(val env: KotlinCoreEnvironment) { val subject = UseAnyOrNoneInsteadOfFind() - @Nested - inner class `UseAnyOrNoneInsteadOfFind rule` { - @Test - @DisplayName("Reports collections.find != null") - fun reportCollectionsFindNotEqualToNull() { - val code = "val x = listOf(1, 2, 3).find { it == 4 } != null" - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - assertThat(actual[0].message).isEqualTo("Use 'any' instead of 'find'") - } + @Test + @DisplayName("Reports collections.find != null") + fun reportCollectionsFindNotEqualToNull() { + val code = "val x = listOf(1, 2, 3).find { it == 4 } != null" + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + assertThat(actual[0].message).isEqualTo("Use 'any' instead of 'find'") + } - @Test - @DisplayName("Reports sequences.find != null") - fun reportSequencesFindNotEqualToNull() { - val code = "val x = sequenceOf(1, 2, 3).find { it == 4 } != null" - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - } + @Test + @DisplayName("Reports sequences.find != null") + fun reportSequencesFindNotEqualToNull() { + val code = "val x = sequenceOf(1, 2, 3).find { it == 4 } != null" + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + } - @Test - @DisplayName("Reports text.find != null") - fun reportTextFindNotEqualToNull() { - val code = "val x = \"123\".find { it == '4' } != null" - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - } + @Test + @DisplayName("Reports text.find != null") + fun reportTextFindNotEqualToNull() { + val code = "val x = \"123\".find { it == '4' } != null" + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + } - @Test - @DisplayName("Reports collections.firstOrNull != null") - fun reportCollectionsFirstOrNullNotEqualToNull() { - val code = "val x = arrayOf(1, 2, 3).firstOrNull { it == 4 } != null" - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - assertThat(actual[0].message).isEqualTo("Use 'any' instead of 'firstOrNull'") - } + @Test + @DisplayName("Reports collections.firstOrNull != null") + fun reportCollectionsFirstOrNullNotEqualToNull() { + val code = "val x = arrayOf(1, 2, 3).firstOrNull { it == 4 } != null" + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + assertThat(actual[0].message).isEqualTo("Use 'any' instead of 'firstOrNull'") + } - @Test - @DisplayName("Reports sequences.firstOrNull != null") - fun reportSequencesFirstOrNullNotEqualToNull() { - val code = "val x = sequenceOf(1, 2, 3).firstOrNull { it == 4 } != null" - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - } + @Test + @DisplayName("Reports sequences.firstOrNull != null") + fun reportSequencesFirstOrNullNotEqualToNull() { + val code = "val x = sequenceOf(1, 2, 3).firstOrNull { it == 4 } != null" + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + } - @Test - @DisplayName("Reports text.firstOrNull != null") - fun reportTextFirstOrNullNotEqualToNull() { - val code = "val x = \"123\".firstOrNull { it == '4' } != null" - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - } + @Test + @DisplayName("Reports text.firstOrNull != null") + fun reportTextFirstOrNullNotEqualToNull() { + val code = "val x = \"123\".firstOrNull { it == '4' } != null" + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + } - @Test - @DisplayName("Reports collections.find == null") - fun reportCollectionsFindEqualToNull() { - val code = "val x = setOf(1, 2, 3).find { it == 4 } == null" - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - assertThat(actual[0].message).isEqualTo("Use 'none' instead of 'find'") - } + @Test + @DisplayName("Reports collections.find == null") + fun reportCollectionsFindEqualToNull() { + val code = "val x = setOf(1, 2, 3).find { it == 4 } == null" + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + assertThat(actual[0].message).isEqualTo("Use 'none' instead of 'find'") + } - @Test - @DisplayName("Reports null != collections.find") - fun reportNullNotEqualToCollectionsFind() { - val code = "val x = null != listOf(1, 2, 3).find { it == 4 }" - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - assertThat(actual[0].message).isEqualTo("Use 'any' instead of 'find'") - } + @Test + @DisplayName("Reports null != collections.find") + fun reportNullNotEqualToCollectionsFind() { + val code = "val x = null != listOf(1, 2, 3).find { it == 4 }" + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + assertThat(actual[0].message).isEqualTo("Use 'any' instead of 'find'") + } - @Test - @DisplayName("Reports collections.find != null in extension") - fun reportCollectionsFindNotEqualToNullInExtension() { - val code = "fun List.test(): Boolean = find { it == 4 } != null" - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - } + @Test + @DisplayName("Reports collections.find != null in extension") + fun reportCollectionsFindNotEqualToNullInExtension() { + val code = "fun List.test(): Boolean = find { it == 4 } != null" + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + } - @Test - @DisplayName("Reports collections.lastOrNull != null") - fun reportCollectionsLastOrNullNotEqualToNull() { - val code = "val x = listOf(1, 2, 3).lastOrNull { it == 4 } != null" - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - assertThat(actual[0].message).isEqualTo("Use 'any' instead of 'lastOrNull'") - } + @Test + @DisplayName("Reports collections.lastOrNull != null") + fun reportCollectionsLastOrNullNotEqualToNull() { + val code = "val x = listOf(1, 2, 3).lastOrNull { it == 4 } != null" + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + assertThat(actual[0].message).isEqualTo("Use 'any' instead of 'lastOrNull'") + } - @Test - @DisplayName("Does not report collections.find") - fun noReportCollectionsFind() { - val code = "val x = listOf(1, 2, 3).find { it == 4 }" - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).isEmpty() - } + @Test + @DisplayName("Does not report collections.find") + fun noReportCollectionsFind() { + val code = "val x = listOf(1, 2, 3).find { it == 4 }" + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseArrayLiteralsInAnnotationsSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseArrayLiteralsInAnnotationsSpec.kt index a8613ac75a6..a06a1469df7 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseArrayLiteralsInAnnotationsSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseArrayLiteralsInAnnotationsSpec.kt @@ -3,42 +3,36 @@ package io.gitlab.arturbosch.detekt.rules.style import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class UseArrayLiteralsInAnnotationsSpec { val subject = UseArrayLiteralsInAnnotations() - @Nested - @DisplayName("suggests replacing arrayOf with [] syntax`") - inner class ReplaceArrayOfWithSquareBrackets { - - @Test - fun `finds an arrayOf usage`() { - val findings = subject.compileAndLint( - """ - annotation class Test(val values: Array) - @Test(arrayOf("value")) - fun test() = Unit - """ - ) - - assertThat(findings).hasSize(1) - } - - @Test - @DisplayName("expects [] syntax") - fun expectsBracketSyntax() { - val findings = subject.compileAndLint( - """ - annotation class Test(val values: Array) - @Test(["value"]) - fun test() = Unit - """ - ) + @Test + fun `finds an arrayOf usage`() { + val findings = subject.compileAndLint( + """ + annotation class Test(val values: Array) + @Test(arrayOf("value")) + fun test() = Unit + """ + ) + + assertThat(findings).hasSize(1) + } - assertThat(findings).isEmpty() - } + @Test + @DisplayName("expects [] syntax") + fun expectsBracketSyntax() { + val findings = subject.compileAndLint( + """ + annotation class Test(val values: Array) + @Test(["value"]) + fun test() = Unit + """ + ) + + assertThat(findings).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseCheckNotNullSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseCheckNotNullSpec.kt index 749002413a2..460aee82f9e 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseCheckNotNullSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseCheckNotNullSpec.kt @@ -4,46 +4,42 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class UseCheckNotNullSpec(val env: KotlinCoreEnvironment) { val subject = UseCheckNotNull() - @Nested - inner class `UseCheckNotNull rule` { - @Test - fun `reports 'check' calls with a non-null check`() { - val code = """ - fun test(i: Int?) { - check(i != null) - } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - } + @Test + fun `reports 'check' calls with a non-null check`() { + val code = """ + fun test(i: Int?) { + check(i != null) + } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + } - @Test - fun `reports 'check' calls with a non-null check that has 'null' on the left side`() { - val code = """ - fun test(i: Int?) { - check(null != i) - } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - } + @Test + fun `reports 'check' calls with a non-null check that has 'null' on the left side`() { + val code = """ + fun test(i: Int?) { + check(null != i) + } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + } - @Test - fun `does not report a 'check' call without a non-null check`() { - val code = """ - fun test(i: Int) { - check(i > 0) - } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).isEmpty() - } + @Test + fun `does not report a 'check' call without a non-null check`() { + val code = """ + fun test(i: Int) { + check(i > 0) + } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseCheckOrErrorSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseCheckOrErrorSpec.kt index 7dfedc755ab..28d7ff8e727 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseCheckOrErrorSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseCheckOrErrorSpec.kt @@ -14,109 +14,148 @@ import org.junit.jupiter.api.Test class UseCheckOrErrorSpec(val env: KotlinCoreEnvironment) { val subject = UseCheckOrError(Config.empty) - @Nested - inner class `UseCheckOrError rule` { + @Test + fun `reports if a an IllegalStateException is thrown`() { + val code = """ + fun x() { + doSomething() + if (a < 0) throw IllegalStateException() + } + """ + assertThat(subject.lint(code)).hasSourceLocation(3, 16) + } - @Test - fun `reports if a an IllegalStateException is thrown`() { - val code = """ - fun x() { - doSomething() - if (a < 0) throw IllegalStateException() - } - """ - assertThat(subject.lint(code)).hasSourceLocation(3, 16) - } + @Test + fun `reports if a an IllegalStateException is thrown with an error message`() { + val code = """ + fun x() { + doSomething() + if (a < 0) throw IllegalStateException("More details") + } + """ + assertThat(subject.lint(code)).hasSourceLocation(3, 16) + } - @Test - fun `reports if a an IllegalStateException is thrown with an error message`() { - val code = """ - fun x() { - doSomething() - if (a < 0) throw IllegalStateException("More details") + @Test + fun `reports if a an IllegalStateException is thrown as default case of a when expression`() { + val code = """ + fun x(a: Int) = + when (a) { + 1 -> doSomething() + else -> throw IllegalStateException() } - """ - assertThat(subject.lint(code)).hasSourceLocation(3, 16) - } + """ + assertThat(subject.lint(code)).hasSourceLocation(4, 17) + } - @Test - fun `reports if a an IllegalStateException is thrown as default case of a when expression`() { - val code = """ - fun x(a: Int) = - when (a) { - 1 -> doSomething() - else -> throw IllegalStateException() - } - """ - assertThat(subject.lint(code)).hasSourceLocation(4, 17) - } + @Test + fun `reports if an IllegalStateException is thrown by its fully qualified name`() { + val code = """ + fun x() { + doSomething() + if (a < 0) throw java.lang.IllegalStateException() + } + """ + assertThat(subject.lint(code)).hasSourceLocation(3, 16) + } - @Test - fun `reports if an IllegalStateException is thrown by its fully qualified name`() { - val code = """ - fun x() { - doSomething() - if (a < 0) throw java.lang.IllegalStateException() - } - """ - assertThat(subject.lint(code)).hasSourceLocation(3, 16) - } + @Test + fun `reports if an IllegalStateException is thrown by its fully qualified name using the kotlin type alias`() { + val code = """ + fun x() { + doSomething() + if (a < 0) throw kotlin.IllegalStateException() + } + """ + assertThat(subject.lint(code)).hasSourceLocation(3, 16) + } - @Test - fun `reports if an IllegalStateException is thrown by its fully qualified name using the kotlin type alias`() { - val code = """ - fun x() { - doSomething() - if (a < 0) throw kotlin.IllegalStateException() - } - """ - assertThat(subject.lint(code)).hasSourceLocation(3, 16) - } + @Test + fun `does not report if any other kind of exception is thrown`() { + val code = """ + fun x() { + doSomething() + if (a < 0) throw SomeBusinessException() + } + """ + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `does not report if any other kind of exception is thrown`() { - val code = """ - fun x() { - doSomething() - if (a < 0) throw SomeBusinessException() + @Test + fun `does not report an issue if the exception thrown has a message and a cause`() { + val code = """ + private fun missing(): Nothing { + if (cause != null) { + throw IllegalStateException("message", cause) } - """ - assertThat(subject.lint(code)).isEmpty() - } + } + """ + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `does not report an issue if the exception thrown has a message and a cause`() { - val code = """ - private fun missing(): Nothing { - if (cause != null) { - throw IllegalStateException("message", cause) - } + @Test + fun `does not report an issue if the exception thrown as the only action in a block`() { + val code = """ + fun unsafeRunSync(): A = + unsafeRunTimed(Duration.INFINITE) + .fold({ throw IllegalStateException("message") }, ::identity) + """ + assertThat(subject.lint(code)).isEmpty() + } + + @Test + fun `reports an issue if the exception thrown as the only action in a function`() { + val code = """fun doThrow() = throw IllegalStateException("message")""" + assertThat(subject.lint(code)).hasSourceLocation(1, 17) + } + + @Test + fun `reports an issue if the exception thrown as the only action in a function block`() { + val code = """fun doThrow() { throw IllegalStateException("message") }""" + assertThat(subject.lint(code)).hasSourceLocation(1, 17) + } + + @Test + fun `does not report if the exception thrown has a non-String argument`() { + val code = """ + fun test(throwable: Throwable) { + when(throwable) { + is NumberFormatException -> println("a") + else -> throw IllegalStateException(throwable) } - """ - assertThat(subject.lint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report an issue if the exception thrown as the only action in a block`() { - val code = """ - fun unsafeRunSync(): A = - unsafeRunTimed(Duration.INFINITE) - .fold({ throw IllegalStateException("message") }, ::identity) - """ - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `does not report if the exception thrown has a String literal argument and a non-String argument`() { + val code = """ + fun test(throwable: Throwable) { + when(throwable) { + is NumberFormatException -> println("a") + else -> throw IllegalStateException("b", throwable) + } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports an issue if the exception thrown as the only action in a function`() { - val code = """fun doThrow() = throw IllegalStateException("message")""" - assertThat(subject.lint(code)).hasSourceLocation(1, 17) - } + @Test + fun `does not report if the exception thrown has a non-String literal argument`() { + val code = """ + fun test(throwable: Throwable) { + when(throwable) { + is NumberFormatException -> println("a") + else -> throw IllegalStateException(throwable.toString()) + } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `reports an issue if the exception thrown as the only action in a function block`() { - val code = """fun doThrow() { throw IllegalStateException("message") }""" - assertThat(subject.lint(code)).hasSourceLocation(1, 17) - } + @Nested + inner class `with binding context` { @Test fun `does not report if the exception thrown has a non-String argument`() { @@ -128,7 +167,7 @@ class UseCheckOrErrorSpec(val env: KotlinCoreEnvironment) { } } """ - assertThat(subject.compileAndLint(code)).isEmpty() + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } @Test @@ -141,11 +180,11 @@ class UseCheckOrErrorSpec(val env: KotlinCoreEnvironment) { } } """ - assertThat(subject.compileAndLint(code)).isEmpty() + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } @Test - fun `does not report if the exception thrown has a non-String literal argument`() { + fun `reports if the exception thrown has a non-String literal argument`() { val code = """ fun test(throwable: Throwable) { when(throwable) { @@ -154,63 +193,20 @@ class UseCheckOrErrorSpec(val env: KotlinCoreEnvironment) { } } """ - assertThat(subject.compileAndLint(code)).isEmpty() + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) } - @Nested - inner class `with binding context` { - - @Test - fun `does not report if the exception thrown has a non-String argument`() { - val code = """ - fun test(throwable: Throwable) { - when(throwable) { - is NumberFormatException -> println("a") - else -> throw IllegalStateException(throwable) - } - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `does not report if the exception thrown has a String literal argument and a non-String argument`() { - val code = """ - fun test(throwable: Throwable) { - when(throwable) { - is NumberFormatException -> println("a") - else -> throw IllegalStateException("b", throwable) - } - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `reports if the exception thrown has a non-String literal argument`() { - val code = """ - fun test(throwable: Throwable) { - when(throwable) { - is NumberFormatException -> println("a") - else -> throw IllegalStateException(throwable.toString()) - } - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `reports if the exception thrown has a string literal argument`() { - val code = """ - fun test(throwable: Throwable) { - when(throwable) { - is NumberFormatException -> println("a") - else -> throw IllegalStateException("b") - } + @Test + fun `reports if the exception thrown has a string literal argument`() { + val code = """ + fun test(throwable: Throwable) { + when(throwable) { + is NumberFormatException -> println("a") + else -> throw IllegalStateException("b") } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseDataClassSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseDataClassSpec.kt index d9439703ef6..5996b55864a 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseDataClassSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseDataClassSpec.kt @@ -19,403 +19,399 @@ class UseDataClassSpec(val env: KotlinCoreEnvironment) { val subject = UseDataClass(Config.empty) @Nested - inner class `UseDataClass rule` { - - @Nested - inner class `does not report invalid data class candidates` { - - @Test - fun `does not report a valid class`() { - val code = """ - class NoDataClassCandidate(val i: Int) { - val i2: Int = 0 - fun f() { - println() - } - object Obj - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report a candidate class with additional method`() { - val code = """ - class NoDataClassCandidateWithAdditionalMethod(val i: Int) { - fun f1() { - println() - } - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report a candidate class with a private constructor`() { - val code = """ - class NoDataClassCandidateWithOnlyPrivateCtor1 private constructor(val i: Int) - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + inner class `does not report invalid data class candidates` { - @Test - fun `does not report a candidate class with a private explicit constructor`() { - val code = """ - class NoDataClassCandidateWithOnlyPrivateCtor2 { - private constructor(i: Int) - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report a candidate sealed class`() { - val code = """ - sealed class NoDataClassBecauseItsSealed { - data class Success(val any: Any) : NoDataClassBecauseItsSealed() - data class Error(val error: Throwable) : NoDataClassBecauseItsSealed() - } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report a candidate enum class`() { - val code = """ - enum class EnumNoDataClass(val i: Int) { - FIRST(1), SECOND(2); + @Test + fun `does not report a valid class`() { + val code = """ + class NoDataClassCandidate(val i: Int) { + val i2: Int = 0 + fun f() { + println() } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } - - @Test - fun `does not report a candidate annotation class`() { - val code = """ - annotation class AnnotationNoDataClass(val i: Int) - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + object Obj + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report a candidate with an interface that has methods`() { - val code = """ - interface SomeInterface { - fun foo(): Int - } - - class NotDataClassBecauseItsImplementingInterfaceWithMethods(val i : Int): SomeInterface { - override fun foo() = i + @Test + fun `does not report a candidate class with additional method`() { + val code = """ + class NoDataClassCandidateWithAdditionalMethod(val i: Int) { + fun f1() { + println() } - """ + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report a candidate class with a private constructor`() { + val code = """ + class NoDataClassCandidateWithOnlyPrivateCtor1 private constructor(val i: Int) + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report an existing data class candidate with an interface`() { - val code = """ - interface SimpleInterface { - val i: Int - } - - data class DataClass(override val i: Int): SimpleInterface - """ + @Test + fun `does not report a candidate class with a private explicit constructor`() { + val code = """ + class NoDataClassCandidateWithOnlyPrivateCtor2 { + private constructor(i: Int) + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report a candidate sealed class`() { + val code = """ + sealed class NoDataClassBecauseItsSealed { + data class Success(val any: Any) : NoDataClassBecauseItsSealed() + data class Error(val error: Throwable) : NoDataClassBecauseItsSealed() + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report a class extending a class and implementing an interface`() { - val code = """ - interface SimpleInterface { - val i: Int - } - - open class BaseClass(open val j: Int) - - class DataClass(override val i: Int, override val j: Int): SimpleInterface, BaseClass(j) - """ + @Test + fun `does not report a candidate enum class`() { + val code = """ + enum class EnumNoDataClass(val i: Int) { + FIRST(1), SECOND(2); + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - assertThat(subject.compileAndLint(code)).isEmpty() - } + @Test + fun `does not report a candidate annotation class`() { + val code = """ + annotation class AnnotationNoDataClass(val i: Int) + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report a class with delegating interface`() { - val code = """ - interface I - class B() : I - class A(val b: B) : I by b - """ + @Test + fun `does not report a candidate with an interface that has methods`() { + val code = """ + interface SomeInterface { + fun foo(): Int + } + + class NotDataClassBecauseItsImplementingInterfaceWithMethods(val i : Int): SomeInterface { + override fun foo() = i + } + """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + assertThat(subject.compileAndLint(code)).isEmpty() } - @Nested - inner class `does report data class candidates` { + @Test + fun `does not report an existing data class candidate with an interface`() { + val code = """ + interface SimpleInterface { + val i: Int + } + + data class DataClass(override val i: Int): SimpleInterface + """ - @Test - fun `does report a data class candidate`() { - val code = """ - class DataClassCandidate1(val i: Int) - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does report a candidate class with extra property`() { - val code = """ - class DataClassCandidateWithProperties(val i: Int) { - val i2: Int = 0 - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `does not report a class extending a class and implementing an interface`() { + val code = """ + interface SimpleInterface { + val i: Int + } + + open class BaseClass(open val j: Int) + + class DataClass(override val i: Int, override val j: Int): SimpleInterface, BaseClass(j) + """ - @Test - fun `does report a candidate class with extra public constructor`() { - val code = """ - class DataClassCandidate2(val s: String) { - private constructor(i: Int) : this(i.toString()) - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does report a candidate class with both a private and public constructor`() { - val code = """ - class DataClassCandidate3 private constructor(val s: String) { - constructor(i: Int) : this(i.toString()) - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `does not report a class with delegating interface`() { + val code = """ + interface I + class B() : I + class A(val b: B) : I by b + """ - @Test - fun `does report a candidate class with overridden data class methods`() { - val code = """ - class DataClassCandidateWithOverriddenMethods(val i: Int) { - override fun equals(other: Any?): Boolean { - return super.equals(other) - } - override fun hashCode(): Int { - return super.hashCode() - } - override fun toString(): String { - return super.toString() - } - } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + assertThat(subject.compileAndLint(code)).isEmpty() + } + } - @Test - fun `does report a candidate class with a simple interface extension`() { - val code = """ - interface SimpleInterface - class DataClass(val i: Int): SimpleInterface - """ + @Nested + inner class `does report data class candidates` { - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `does report a data class candidate`() { + val code = """ + class DataClassCandidate1(val i: Int) + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does report a candidate class with an interface extension that overrides vals`() { - val code = """ - interface SimpleInterface { - val i: Int - } - - class DataClass(override val i: Int): SimpleInterface - """ + @Test + fun `does report a candidate class with extra property`() { + val code = """ + class DataClassCandidateWithProperties(val i: Int) { + val i2: Int = 0 + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - assertThat(subject.compileAndLint(code)).hasSize(1) - } + @Test + fun `does report a candidate class with extra public constructor`() { + val code = """ + class DataClassCandidate2(val s: String) { + private constructor(i: Int) : this(i.toString()) + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) } - @Nested - inner class `copy method` { + @Test + fun `does report a candidate class with both a private and public constructor`() { + val code = """ + class DataClassCandidate3 private constructor(val s: String) { + constructor(i: Int) : this(i.toString()) + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does report with copy method`() { - val code = """ - class D(val a: Int, val b: String) { - fun copy(a: Int, b: String): D = D(a, b) + @Test + fun `does report a candidate class with overridden data class methods`() { + val code = """ + class DataClassCandidateWithOverriddenMethods(val i: Int) { + override fun equals(other: Any?): Boolean { + return super.equals(other) } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `does report with copy method which has an implicit return type`() { - val code = """ - class D(val a: Int, val b: String) { - fun copy(a: Int, b: String) = D(a, b) + override fun hashCode(): Int { + return super.hashCode() } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `does not report with copy method which has no parameters`() { - val code = """ - class D(val a: Int, val b: String) { - fun copy(): D = D(0, "") + override fun toString(): String { + return super.toString() } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report with copy method which has more parameters than the primary constructor`() { - val code = """ - class D(val a: Int, val b: String) { - fun copy(a: Int, b: String, c: String): D = D(a, b + c) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does report a candidate class with a simple interface extension`() { + val code = """ + interface SimpleInterface + class DataClass(val i: Int): SimpleInterface + """ - @Test - fun `does not report with copy method which has different parameter types`() { - val code = """ - class D(val a: Int, val b: String) { - fun copy(a: Int, b: Int): D = D(a, b.toString()) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report with copy method which has different parameter types 2`() { - val code = """ - class D(val a: Int, val b: String) { - fun copy(a: Int, b: String?): D = D(a, b.toString()) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does report a candidate class with an interface extension that overrides vals`() { + val code = """ + interface SimpleInterface { + val i: Int + } + + class DataClass(override val i: Int): SimpleInterface + """ - @Test - fun `does not report with copy method which has a different return type`() { - val code = """ - class D(val a: Int, val b: String) { - fun copy(a: Int, b: String) { - } - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + assertThat(subject.compileAndLint(code)).hasSize(1) } + } - @Nested - inner class `does report class with vars and allowVars` { - - @Test - fun `does not report class with mutable constructor parameter`() { - val code = """class DataClassCandidateWithVar(var i: Int)""" - val config = TestConfig(mapOf(ALLOW_VARS to "true")) - assertThat(UseDataClass(config).compileAndLint(code)).isEmpty() - } + @Nested + inner class `copy method` { - @Test - fun `does not report class with mutable properties`() { - val code = """ - class DataClassCandidateWithProperties(var i: Int) { - var i2: Int = 0 - } - """ - val config = TestConfig(mapOf(ALLOW_VARS to "true")) - assertThat(UseDataClass(config).compileAndLint(code)).isEmpty() - } + @Test + fun `does report with copy method`() { + val code = """ + class D(val a: Int, val b: String) { + fun copy(a: Int, b: String): D = D(a, b) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `does not report class with both mutable property and immutable parameters`() { - val code = """ - class DataClassCandidateWithMixedProperties(val i: Int) { - var i2: Int = 0 - } - """ - val config = TestConfig(mapOf(ALLOW_VARS to "true")) - assertThat(UseDataClass(config).compileAndLint(code)).isEmpty() - } + @Test + fun `does report with copy method which has an implicit return type`() { + val code = """ + class D(val a: Int, val b: String) { + fun copy(a: Int, b: String) = D(a, b) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } - @Test - fun `does not report class with both mutable parameter and immutable property`() { - val code = """ - class DataClassCandidateWithMixedProperties(var i: Int) { - val i2: Int = 0 - } - """ - val config = TestConfig(mapOf(ALLOW_VARS to "true")) - assertThat(UseDataClass(config).compileAndLint(code)).isEmpty() - } + @Test + fun `does not report with copy method which has no parameters`() { + val code = """ + class D(val a: Int, val b: String) { + fun copy(): D = D(0, "") + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } @Test - fun `does not report inline classes`() { - assertThat(subject.lint("inline class A(val x: Int)")).isEmpty() + fun `does not report with copy method which has more parameters than the primary constructor`() { + val code = """ + class D(val a: Int, val b: String) { + fun copy(a: Int, b: String, c: String): D = D(a, b + c) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } @Test - fun `does not report value classes`() { + fun `does not report with copy method which has different parameter types`() { val code = """ - @JvmInline - value class A(val x: Int) - """.trimIndent() - assertThat(subject.lint(code)).isEmpty() + class D(val a: Int, val b: String) { + fun copy(a: Int, b: Int): D = D(a, b.toString()) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } @Test - fun `does not report a class which has an ignored annotation`() { + fun `does not report with copy method which has different parameter types 2`() { val code = """ - import kotlin.SinceKotlin + class D(val a: Int, val b: String) { + fun copy(a: Int, b: String?): D = D(a, b.toString()) + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @SinceKotlin("1.0.0") - class AnnotatedClass(val i: Int) {} + @Test + fun `does not report with copy method which has a different return type`() { + val code = """ + class D(val a: Int, val b: String) { + fun copy(a: Int, b: String) { + } + } """ - val config = TestConfig(mapOf(EXCLUDE_ANNOTATED_CLASSES to "kotlin.*")) + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + } + + @Nested + inner class `does report class with vars and allowVars` { + + @Test + fun `does not report class with mutable constructor parameter`() { + val code = """class DataClassCandidateWithVar(var i: Int)""" + val config = TestConfig(mapOf(ALLOW_VARS to "true")) assertThat(UseDataClass(config).compileAndLint(code)).isEmpty() } @Test - fun `does not report a class with a delegated property`() { + fun `does not report class with mutable properties`() { val code = """ - import kotlin.properties.Delegates - class C(val i: Int) { - var prop: String by Delegates.observable("") { - prop, old, new -> println("") - } + class DataClassCandidateWithProperties(var i: Int) { + var i2: Int = 0 } """ - assertThat(subject.compileAndLint(code)).isEmpty() + val config = TestConfig(mapOf(ALLOW_VARS to "true")) + assertThat(UseDataClass(config).compileAndLint(code)).isEmpty() } @Test - fun `reports class with nested delegation`() { + fun `does not report class with both mutable property and immutable parameters`() { val code = """ - import kotlin.properties.Delegates - class C(val i: Int) { - var prop: C = C(1).apply { - var str: String by Delegates.observable("") { - prop, old, new -> println("") - } - } + class DataClassCandidateWithMixedProperties(val i: Int) { + var i2: Int = 0 } """ - assertThat(subject.compileAndLint(code)).hasSize(1) + val config = TestConfig(mapOf(ALLOW_VARS to "true")) + assertThat(UseDataClass(config).compileAndLint(code)).isEmpty() } @Test - fun `does not report inner classes`() { + fun `does not report class with both mutable parameter and immutable property`() { val code = """ - class Outer { - inner class Inner(val x: Int) + class DataClassCandidateWithMixedProperties(var i: Int) { + val i2: Int = 0 } - """.trimIndent() - assertThat(subject.compileAndLint(code)).isEmpty() + """ + val config = TestConfig(mapOf(ALLOW_VARS to "true")) + assertThat(UseDataClass(config).compileAndLint(code)).isEmpty() } } + + @Test + fun `does not report inline classes`() { + assertThat(subject.lint("inline class A(val x: Int)")).isEmpty() + } + + @Test + fun `does not report value classes`() { + val code = """ + @JvmInline + value class A(val x: Int) + """.trimIndent() + assertThat(subject.lint(code)).isEmpty() + } + + @Test + fun `does not report a class which has an ignored annotation`() { + val code = """ + import kotlin.SinceKotlin + + @SinceKotlin("1.0.0") + class AnnotatedClass(val i: Int) {} + """ + val config = TestConfig(mapOf(EXCLUDE_ANNOTATED_CLASSES to "kotlin.*")) + assertThat(UseDataClass(config).compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report a class with a delegated property`() { + val code = """ + import kotlin.properties.Delegates + class C(val i: Int) { + var prop: String by Delegates.observable("") { + prop, old, new -> println("") + } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `reports class with nested delegation`() { + val code = """ + import kotlin.properties.Delegates + class C(val i: Int) { + var prop: C = C(1).apply { + var str: String by Delegates.observable("") { + prop, old, new -> println("") + } + } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } + + @Test + fun `does not report inner classes`() { + val code = """ + class Outer { + inner class Inner(val x: Int) + } + """.trimIndent() + assertThat(subject.compileAndLint(code)).isEmpty() + } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseEmptyCounterpartSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseEmptyCounterpartSpec.kt index ad438326078..bcdfc2d4780 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseEmptyCounterpartSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseEmptyCounterpartSpec.kt @@ -5,85 +5,80 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class UseEmptyCounterpartSpec(val env: KotlinCoreEnvironment) { val rule = UseEmptyCounterpart(Config.empty) - @Nested - inner class `UseEmptyCounterpart rule` { - - @Test - fun `reports no-arg instantiation`() { - val code = """ - val array = arrayOf() - val list = listOf() - val nonNullList = listOfNotNull() - val map = mapOf() - val sequence = sequenceOf() - val set = setOf() - """ - assertThat(rule.compileAndLintWithContext(env, code)).hasSize(6) - } + @Test + fun `reports no-arg instantiation`() { + val code = """ + val array = arrayOf() + val list = listOf() + val nonNullList = listOfNotNull() + val map = mapOf() + val sequence = sequenceOf() + val set = setOf() + """ + assertThat(rule.compileAndLintWithContext(env, code)).hasSize(6) + } - @Test - fun `reports no-arg instantiation with inferred type parameters`() { - val code = """ - val array: Array = arrayOf() - val list: List = listOf() - val list: List = listOfNotNull() - val map: Map = mapOf() - val sequence: Sequence = sequenceOf() - val set: Set = setOf() - """ - assertThat(rule.compileAndLintWithContext(env, code)).hasSize(6) - } + @Test + fun `reports no-arg instantiation with inferred type parameters`() { + val code = """ + val array: Array = arrayOf() + val list: List = listOf() + val list: List = listOfNotNull() + val map: Map = mapOf() + val sequence: Sequence = sequenceOf() + val set: Set = setOf() + """ + assertThat(rule.compileAndLintWithContext(env, code)).hasSize(6) + } - @Test - fun `does not report empty instantiation`() { - val code = """ - val array = emptyArray() - val list = emptyList() - val map = emptyMap() - val sequence = emptySequence() - val set = emptySet() - """ - assertThat(rule.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does not report empty instantiation`() { + val code = """ + val array = emptyArray() + val list = emptyList() + val map = emptyMap() + val sequence = emptySequence() + val set = emptySet() + """ + assertThat(rule.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report instantiation with arguments`() { - val code = """ - val array = arrayOf(0) - val list = listOf(0) - val nonNullList = listOfNotNull(0) - val map = mapOf(0 to 0) - val sequence = sequenceOf(0) - val set = setOf(0) - """ - assertThat(rule.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does not report instantiation with arguments`() { + val code = """ + val array = arrayOf(0) + val list = listOf(0) + val nonNullList = listOfNotNull(0) + val map = mapOf(0 to 0) + val sequence = sequenceOf(0) + val set = setOf(0) + """ + assertThat(rule.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report no-arg custom function with same name as function with empty counterpart`() { - val code = """ - fun arrayOf(): Array = TODO() - fun listOf(): List = TODO() - fun listOfNotNull(): List = TODO() - fun mapOf(): Map = TODO() - fun sequenceOf(): Sequence = TODO() - fun setOf(): Set = TODO() + @Test + fun `does not report no-arg custom function with same name as function with empty counterpart`() { + val code = """ + fun arrayOf(): Array = TODO() + fun listOf(): List = TODO() + fun listOfNotNull(): List = TODO() + fun mapOf(): Map = TODO() + fun sequenceOf(): Sequence = TODO() + fun setOf(): Set = TODO() - val array = arrayOf() - val list = listOf() - val nonNullList = listOfNotNull() - val map = mapOf() - val sequence = sequenceOf() - val set = setOf() - """ - assertThat(rule.compileAndLintWithContext(env, code)).isEmpty() - } + val array = arrayOf() + val list = listOf() + val nonNullList = listOfNotNull() + val map = mapOf() + val sequence = sequenceOf() + val set = setOf() + """ + assertThat(rule.compileAndLintWithContext(env, code)).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseIfInsteadOfWhenSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseIfInsteadOfWhenSpec.kt index 58c15a33671..05d9a2a4861 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseIfInsteadOfWhenSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseIfInsteadOfWhenSpec.kt @@ -2,71 +2,66 @@ package io.gitlab.arturbosch.detekt.rules.style import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class UseIfInsteadOfWhenSpec { val subject = UseIfInsteadOfWhen() - @Nested - inner class `UseIfInsteadOfWhen rule` { - - @Test - fun `reports when using two branches`() { - val code = """ - fun function(): Boolean? { - val x = null - when (x) { - null -> return true - else -> return false - } + @Test + fun `reports when using two branches`() { + val code = """ + fun function(): Boolean? { + val x = null + when (x) { + null -> return true + else -> return false } - """ - assertThat(subject.compileAndLint(code)).hasSize(1) - } + } + """ + assertThat(subject.compileAndLint(code)).hasSize(1) + } - @Test - fun `does not report when using one branch`() { - val code = """ - fun function(): Boolean? { - val x = null - when (x) { - else -> return false - } + @Test + fun `does not report when using one branch`() { + val code = """ + fun function(): Boolean? { + val x = null + when (x) { + else -> return false } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report when using more than two branches`() { - val code = """ - fun function(): Boolean? { - val x = null - when (x) { - null -> return true - 3 -> return null - else -> return false - } + @Test + fun `does not report when using more than two branches`() { + val code = """ + fun function(): Boolean? { + val x = null + when (x) { + null -> return true + 3 -> return null + else -> return false } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } - @Test - fun `does not report when second branch is not 'else'`() { - val code = """ - fun function(): Boolean? { - val x = null - when (x) { - null -> return true - 3 -> return null - } - return false + @Test + fun `does not report when second branch is not 'else'`() { + val code = """ + fun function(): Boolean? { + val x = null + when (x) { + null -> return true + 3 -> return null } - """ - assertThat(subject.compileAndLint(code)).isEmpty() - } + return false + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseRequireNotNullSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseRequireNotNullSpec.kt index 7e07718b1d2..910c31ba78c 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseRequireNotNullSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseRequireNotNullSpec.kt @@ -4,46 +4,42 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class UseRequireNotNullSpec(val env: KotlinCoreEnvironment) { val subject = UseRequireNotNull() - @Nested - inner class `UseRequireNotNull rule` { - @Test - fun `reports 'require' calls with a non-null check`() { - val code = """ - fun test(i: Int?) { - require(i != null) - } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - } + @Test + fun `reports 'require' calls with a non-null check`() { + val code = """ + fun test(i: Int?) { + require(i != null) + } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + } - @Test - fun `reports 'require' calls with a non-null check that has 'null' on the left side`() { - val code = """ - fun test(i: Int?) { - require(null != i) - } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).hasSize(1) - } + @Test + fun `reports 'require' calls with a non-null check that has 'null' on the left side`() { + val code = """ + fun test(i: Int?) { + require(null != i) + } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).hasSize(1) + } - @Test - fun `does not report a 'require' call without a non-null check`() { - val code = """ - fun test(i: Int) { - require(i > 0) - } - """ - val actual = subject.compileAndLintWithContext(env, code) - assertThat(actual).isEmpty() - } + @Test + fun `does not report a 'require' call without a non-null check`() { + val code = """ + fun test(i: Int) { + require(i > 0) + } + """ + val actual = subject.compileAndLintWithContext(env, code) + assertThat(actual).isEmpty() } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseRequireSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseRequireSpec.kt index 572d8a61846..84d11edcc85 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseRequireSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseRequireSpec.kt @@ -14,95 +14,126 @@ import org.junit.jupiter.api.Test class UseRequireSpec(val env: KotlinCoreEnvironment) { val subject = UseRequire(Config.empty) - @Nested - inner class `UseRequire rule` { + @Test + fun `reports if a precondition throws an IllegalArgumentException`() { + val code = """ + fun x(a: Int) { + if (a < 0) throw IllegalArgumentException() + doSomething() + } + """ + assertThat(subject.lint(code)).hasSourceLocation(2, 16) + } - @Test - fun `reports if a precondition throws an IllegalArgumentException`() { - val code = """ - fun x(a: Int) { - if (a < 0) throw IllegalArgumentException() - doSomething() - } - """ - assertThat(subject.lint(code)).hasSourceLocation(2, 16) - } + @Test + fun `reports if a precondition throws an IllegalArgumentException with more details`() { + val code = """ + fun x(a: Int) { + if (a < 0) throw IllegalArgumentException("More details") + doSomething() + } + """ + assertThat(subject.lint(code)).hasSourceLocation(2, 16) + } - @Test - fun `reports if a precondition throws an IllegalArgumentException with more details`() { - val code = """ - fun x(a: Int) { - if (a < 0) throw IllegalArgumentException("More details") - doSomething() - } - """ - assertThat(subject.lint(code)).hasSourceLocation(2, 16) - } + @Test + fun `reports if a precondition throws a fully qualified IllegalArgumentException`() { + val code = """ + fun x(a: Int) { + if (a < 0) throw java.lang.IllegalArgumentException() + doSomething() + } + """ + assertThat(subject.lint(code)).hasSourceLocation(2, 16) + } - @Test - fun `reports if a precondition throws a fully qualified IllegalArgumentException`() { - val code = """ - fun x(a: Int) { - if (a < 0) throw java.lang.IllegalArgumentException() - doSomething() - } - """ - assertThat(subject.lint(code)).hasSourceLocation(2, 16) - } + @Test + fun `reports if a precondition throws a fully qualified IllegalArgumentException using the kotlin type alias`() { + val code = """ + fun x(a: Int) { + if (a < 0) throw kotlin.IllegalArgumentException() + doSomething() + } + """ + assertThat(subject.lint(code)).hasSourceLocation(2, 16) + } - @Test - fun `reports if a precondition throws a fully qualified IllegalArgumentException using the kotlin type alias`() { - val code = """ - fun x(a: Int) { - if (a < 0) throw kotlin.IllegalArgumentException() - doSomething() - } - """ - assertThat(subject.lint(code)).hasSourceLocation(2, 16) - } + @Test + fun `does not report if a precondition throws a different kind of exception`() { + val code = """ + fun x(a: Int) { + if (a < 0) throw SomeBusinessException() + doSomething() + } + """ + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `does not report if a precondition throws a different kind of exception`() { - val code = """ - fun x(a: Int) { - if (a < 0) throw SomeBusinessException() - doSomething() - } - """ - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `does not report an issue if the exception thrown has a message and a cause`() { + val code = """ + private fun x(a: Int): Nothing { + doSomething() + throw IllegalArgumentException("message", cause) + } + """ + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `does not report an issue if the exception thrown has a message and a cause`() { - val code = """ - private fun x(a: Int): Nothing { - doSomething() - throw IllegalArgumentException("message", cause) - } - """ - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `does not report an issue if the exception thrown as the only action in a block`() { + val code = """ + fun unsafeRunSync(): A = + foo.fold({ throw IllegalArgumentException("message") }, ::identity) + """ + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `does not report an issue if the exception thrown as the only action in a block`() { - val code = """ - fun unsafeRunSync(): A = - foo.fold({ throw IllegalArgumentException("message") }, ::identity) - """ - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `does not report an issue if the exception thrown unconditionally`() { + val code = """fun doThrow() = throw IllegalArgumentException("message")""" + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `does not report an issue if the exception thrown unconditionally`() { - val code = """fun doThrow() = throw IllegalArgumentException("message")""" - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `does not report an issue if the exception thrown unconditionally in a function block`() { + val code = """fun doThrow() { throw IllegalArgumentException("message") }""" + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `does not report an issue if the exception thrown unconditionally in a function block`() { - val code = """fun doThrow() { throw IllegalArgumentException("message") }""" - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `does not report if the exception thrown has a non-String argument`() { + val code = """ + fun test(throwable: Throwable) { + if (throwable !is NumberFormatException) throw IllegalArgumentException(throwable) + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report if the exception thrown has a String literal argument and a non-String argument`() { + val code = """ + fun test(throwable: Throwable) { + if (throwable !is NumberFormatException) throw IllegalArgumentException("a", throwable) + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Test + fun `does not report if the exception thrown has a non-String literal argument`() { + val code = """ + fun test(throwable: Throwable) { + val s = "" + if (throwable !is NumberFormatException) throw IllegalArgumentException(s) + } + """ + assertThat(subject.compileAndLint(code)).isEmpty() + } + + @Nested + inner class `with binding context` { @Test fun `does not report if the exception thrown has a non-String argument`() { @@ -111,7 +142,7 @@ class UseRequireSpec(val env: KotlinCoreEnvironment) { if (throwable !is NumberFormatException) throw IllegalArgumentException(throwable) } """ - assertThat(subject.compileAndLint(code)).isEmpty() + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } @Test @@ -121,107 +152,72 @@ class UseRequireSpec(val env: KotlinCoreEnvironment) { if (throwable !is NumberFormatException) throw IllegalArgumentException("a", throwable) } """ - assertThat(subject.compileAndLint(code)).isEmpty() + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } @Test - fun `does not report if the exception thrown has a non-String literal argument`() { + fun `reports if the exception thrown has a non-String literal argument`() { val code = """ fun test(throwable: Throwable) { val s = "" if (throwable !is NumberFormatException) throw IllegalArgumentException(s) } """ - assertThat(subject.compileAndLint(code)).isEmpty() + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) } - @Nested - inner class `with binding context` { - - @Test - fun `does not report if the exception thrown has a non-String argument`() { - val code = """ - fun test(throwable: Throwable) { - if (throwable !is NumberFormatException) throw IllegalArgumentException(throwable) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `does not report if the exception thrown has a String literal argument and a non-String argument`() { - val code = """ - fun test(throwable: Throwable) { - if (throwable !is NumberFormatException) throw IllegalArgumentException("a", throwable) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `reports if the exception thrown has a non-String literal argument`() { - val code = """ - fun test(throwable: Throwable) { - val s = "" - if (throwable !is NumberFormatException) throw IllegalArgumentException(s) - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `reports if the exception thrown has a String literal argument`() { - val code = """ - fun test(throwable: Throwable) { - if (throwable !is NumberFormatException) throw IllegalArgumentException("a") - } - """ - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } + @Test + fun `reports if the exception thrown has a String literal argument`() { + val code = """ + fun test(throwable: Throwable) { + if (throwable !is NumberFormatException) throw IllegalArgumentException("a") + } + """ + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) } + } - @Nested - inner class `throw is not after a precondition` { + @Nested + inner class `throw is not after a precondition` { - @Test - fun `does not report an issue if the exception is inside a when`() { - val code = """ - fun whenOrThrow(item : List<*>) = when(item) { - is ArrayList<*> -> 1 - is LinkedList<*> -> 2 - else -> throw IllegalArgumentException("Not supported List type") - } - """ - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `does not report an issue if the exception is inside a when`() { + val code = """ + fun whenOrThrow(item : List<*>) = when(item) { + is ArrayList<*> -> 1 + is LinkedList<*> -> 2 + else -> throw IllegalArgumentException("Not supported List type") + } + """ + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `does not report an issue if the exception is after a block`() { - val code = """ - fun doSomethingOrThrow(test: Int): Int { - var index = 0 - repeat(test){ - if (Math.random() == 1.0) { - return it - } + @Test + fun `does not report an issue if the exception is after a block`() { + val code = """ + fun doSomethingOrThrow(test: Int): Int { + var index = 0 + repeat(test){ + if (Math.random() == 1.0) { + return it } - throw IllegalArgumentException("Test was too big") } - """ - assertThat(subject.lint(code)).isEmpty() - } + throw IllegalArgumentException("Test was too big") + } + """ + assertThat(subject.lint(code)).isEmpty() + } - @Test - fun `does not report an issue if the exception is after a elvis operator`() { - val code = """ - fun tryToCastOrThrow(list: List<*>) : LinkedList<*> { - val subclass = list as? LinkedList - ?: throw IllegalArgumentException("List is not a LinkedList") - return subclass - } - """ - assertThat(subject.lint(code)).isEmpty() - } + @Test + fun `does not report an issue if the exception is after a elvis operator`() { + val code = """ + fun tryToCastOrThrow(list: List<*>) : LinkedList<*> { + val subclass = list as? LinkedList + ?: throw IllegalArgumentException("List is not a LinkedList") + return subclass + } + """ + assertThat(subject.lint(code)).isEmpty() } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UselessCallOnNotNullSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UselessCallOnNotNullSpec.kt index 922f2d06db3..ff6050099f3 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UselessCallOnNotNullSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UselessCallOnNotNullSpec.kt @@ -4,248 +4,244 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class UselessCallOnNotNullSpec(val env: KotlinCoreEnvironment) { val subject = UselessCallOnNotNull() - @Nested - inner class `UselessCallOnNotNull rule` { - @Test - fun `reports when calling orEmpty on a list`() { - val code = """val testList = listOf("string").orEmpty()""" - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).isEqualTo("Remove redundant call to orEmpty") - } - - @Test - fun `reports when calling orEmpty on a list with a safe call`() { - val code = """val testList = listOf("string")?.orEmpty()""" - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).isEqualTo("Remove redundant call to orEmpty") - } - - @Test - fun `reports when calling orEmpty on a list in a chain`() { - val code = """val testList = listOf("string").orEmpty().map { }""" - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).isEqualTo("Remove redundant call to orEmpty") - } - - @Test - fun `reports when calling orEmpty on a list with a platform type`() { - // System.getenv().keys.toList() will be of type List. - val code = """val testSequence = System.getenv().keys.toList().orEmpty()""" - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).isEqualTo("Remove redundant call to orEmpty") - } - - @Test - fun `does not report when calling orEmpty on a nullable list`() { - val code = """ - val testList: List? = listOf("string") - val nonNullableTestList = testList.orEmpty() - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `reports when calling isNullOrBlank on a string with a safe call`() { - val code = """val testString = ""?.isNullOrBlank()""" - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).isEqualTo("Replace isNullOrBlank with isBlank") - } - - @Test - fun `does not report when calling isNullOrBlank on a nullable string`() { - val code = """ - val testString: String? = "" - val nonNullableTestString = testString.isNullOrBlank() - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `reports when calling isNullOrEmpty on a string`() { - val code = """val testString = "".isNullOrEmpty()""" - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).isEqualTo("Replace isNullOrEmpty with isEmpty") - } - - @Test - fun `reports when calling isNullOrEmpty on a string with a safe call`() { - val code = """val testString = ""?.isNullOrEmpty()""" - assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) - } - - @Test - fun `does not report when calling isNullOrEmpty on a nullable string`() { - val code = """ - val testString: String? = "" - val nonNullableTestString = testString.isNullOrEmpty() - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `reports when calling orEmpty on a string`() { - val code = """val testString = "".orEmpty()""" - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).isEqualTo("Remove redundant call to orEmpty") - } - - @Test - fun `does not report when calling orEmpty on a nullable string`() { - val code = """ - val testString: String? = "" - val nonNullableTestString = testString.orEmpty() - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `reports when calling orEmpty on a sequence`() { - val code = """val testSequence = listOf(1).asSequence().orEmpty()""" - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).isEqualTo("Remove redundant call to orEmpty") - } - - @Test - fun `does not report when calling orEmpty on a nullable sequence`() { - val code = """ - val testSequence: Sequence? = listOf(1).asSequence() - val nonNullableTestSequence = testSequence.orEmpty() - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } - - @Test - fun `only reports on a Kotlin list`() { - val code = """ - fun String.orEmpty(): List = this.toCharArray().asList() - - val noList = "str".orEmpty() - val list = listOf(1, 2, 3).orEmpty() - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).isEqualTo("Remove redundant call to orEmpty") - } - - @Test - fun `reports when calling listOfNotNull on all non-nullable arguments`() { - val code = """ - val strings = listOfNotNull("string") - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).isEqualTo("Replace listOfNotNull with listOf") - } - - @Test - fun `reports when calling listOfNotNull with no arguments`() { - val code = """ - val strings = listOfNotNull() - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).isEqualTo("Replace listOfNotNull with listOf") - } - - @Test - fun `does not report when calling listOfNotNull on at least one nullable argument`() { - val code = """ - val strings = listOfNotNull("string", null) - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } - - @Test - fun `does not report when calling listOfNotNull with spread operator`() { - val code = """ - val nullableArray = arrayOf("string", null) - val strings = listOfNotNull(*nullableArray) - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } - - @Test - fun `reports when calling listOfNotNull with spread operator on all non-nullable arguments`() { - val code = """ - val nonNullableArray = arrayOf("string", "bar") - val strings = listOfNotNull(*nonNullableArray) - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).isEqualTo("Replace listOfNotNull with listOf") - } - - @Test - fun `does not report when calling listOfNotNull with a mix of null spread and non-null non-spread`() { - val code = """ - val nullableArray = arrayOf("string", null) - val nonNullableArray = arrayOf("string", "bar") - val strings = listOfNotNull("string", *nonNullableArray, "foo", *nullableArray) - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } - - @Test - fun `does not report when calling listOfNotNull with a mix of non-null spread and null non-spread`() { - val code = """ - val nonNullableArray = arrayOf("string", "bar") - val strings = listOfNotNull("string", *nonNullableArray, null) - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } - - @Test - fun `reports when calling listOfNotNull with a mix of spread and non-spread, all non-null`() { - val code = """ - val nonNullableArray = arrayOf("string", "bar") - val otherNonNullableArray = arrayOf("foobar") - val strings = listOfNotNull("string", *nonNullableArray, "foo", *otherNonNullableArray) - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).isEqualTo("Replace listOfNotNull with listOf") - } - - @Test - fun `does not report when calling custom function named listOfNotNull on all non-nullable arguments`() { - val code = """ - fun listOfNotNull(vararg elements: T?): List = TODO() - - val strings = listOfNotNull("string", null) - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } - - @Test - fun `reports when calling isNullOrEmpty on a list`() { - val code = """ - fun test(list: List) { - list.isNullOrEmpty() - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).isEqualTo("Replace isNullOrEmpty with isEmpty") - } + @Test + fun `reports when calling orEmpty on a list`() { + val code = """val testList = listOf("string").orEmpty()""" + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).isEqualTo("Remove redundant call to orEmpty") + } + + @Test + fun `reports when calling orEmpty on a list with a safe call`() { + val code = """val testList = listOf("string")?.orEmpty()""" + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).isEqualTo("Remove redundant call to orEmpty") + } + + @Test + fun `reports when calling orEmpty on a list in a chain`() { + val code = """val testList = listOf("string").orEmpty().map { }""" + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).isEqualTo("Remove redundant call to orEmpty") + } + + @Test + fun `reports when calling orEmpty on a list with a platform type`() { + // System.getenv().keys.toList() will be of type List. + val code = """val testSequence = System.getenv().keys.toList().orEmpty()""" + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).isEqualTo("Remove redundant call to orEmpty") + } + + @Test + fun `does not report when calling orEmpty on a nullable list`() { + val code = """ + val testList: List? = listOf("string") + val nonNullableTestList = testList.orEmpty() + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `reports when calling isNullOrBlank on a string with a safe call`() { + val code = """val testString = ""?.isNullOrBlank()""" + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).isEqualTo("Replace isNullOrBlank with isBlank") + } + + @Test + fun `does not report when calling isNullOrBlank on a nullable string`() { + val code = """ + val testString: String? = "" + val nonNullableTestString = testString.isNullOrBlank() + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `reports when calling isNullOrEmpty on a string`() { + val code = """val testString = "".isNullOrEmpty()""" + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).isEqualTo("Replace isNullOrEmpty with isEmpty") + } + + @Test + fun `reports when calling isNullOrEmpty on a string with a safe call`() { + val code = """val testString = ""?.isNullOrEmpty()""" + assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1) + } + + @Test + fun `does not report when calling isNullOrEmpty on a nullable string`() { + val code = """ + val testString: String? = "" + val nonNullableTestString = testString.isNullOrEmpty() + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `reports when calling orEmpty on a string`() { + val code = """val testString = "".orEmpty()""" + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).isEqualTo("Remove redundant call to orEmpty") + } + + @Test + fun `does not report when calling orEmpty on a nullable string`() { + val code = """ + val testString: String? = "" + val nonNullableTestString = testString.orEmpty() + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `reports when calling orEmpty on a sequence`() { + val code = """val testSequence = listOf(1).asSequence().orEmpty()""" + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).isEqualTo("Remove redundant call to orEmpty") + } + + @Test + fun `does not report when calling orEmpty on a nullable sequence`() { + val code = """ + val testSequence: Sequence? = listOf(1).asSequence() + val nonNullableTestSequence = testSequence.orEmpty() + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `only reports on a Kotlin list`() { + val code = """ + fun String.orEmpty(): List = this.toCharArray().asList() + + val noList = "str".orEmpty() + val list = listOf(1, 2, 3).orEmpty() + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).isEqualTo("Remove redundant call to orEmpty") + } + + @Test + fun `reports when calling listOfNotNull on all non-nullable arguments`() { + val code = """ + val strings = listOfNotNull("string") + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).isEqualTo("Replace listOfNotNull with listOf") + } + + @Test + fun `reports when calling listOfNotNull with no arguments`() { + val code = """ + val strings = listOfNotNull() + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).isEqualTo("Replace listOfNotNull with listOf") + } + + @Test + fun `does not report when calling listOfNotNull on at least one nullable argument`() { + val code = """ + val strings = listOfNotNull("string", null) + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } + + @Test + fun `does not report when calling listOfNotNull with spread operator`() { + val code = """ + val nullableArray = arrayOf("string", null) + val strings = listOfNotNull(*nullableArray) + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } + + @Test + fun `reports when calling listOfNotNull with spread operator on all non-nullable arguments`() { + val code = """ + val nonNullableArray = arrayOf("string", "bar") + val strings = listOfNotNull(*nonNullableArray) + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).isEqualTo("Replace listOfNotNull with listOf") + } + + @Test + fun `does not report when calling listOfNotNull with a mix of null spread and non-null non-spread`() { + val code = """ + val nullableArray = arrayOf("string", null) + val nonNullableArray = arrayOf("string", "bar") + val strings = listOfNotNull("string", *nonNullableArray, "foo", *nullableArray) + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } + + @Test + fun `does not report when calling listOfNotNull with a mix of non-null spread and null non-spread`() { + val code = """ + val nonNullableArray = arrayOf("string", "bar") + val strings = listOfNotNull("string", *nonNullableArray, null) + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } + + @Test + fun `reports when calling listOfNotNull with a mix of spread and non-spread, all non-null`() { + val code = """ + val nonNullableArray = arrayOf("string", "bar") + val otherNonNullableArray = arrayOf("foobar") + val strings = listOfNotNull("string", *nonNullableArray, "foo", *otherNonNullableArray) + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).isEqualTo("Replace listOfNotNull with listOf") + } + + @Test + fun `does not report when calling custom function named listOfNotNull on all non-nullable arguments`() { + val code = """ + fun listOfNotNull(vararg elements: T?): List = TODO() + + val strings = listOfNotNull("string", null) + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } + + @Test + fun `reports when calling isNullOrEmpty on a list`() { + val code = """ + fun test(list: List) { + list.isNullOrEmpty() + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).isEqualTo("Replace isNullOrEmpty with isEmpty") } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UtilityClassWithPublicConstructorSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UtilityClassWithPublicConstructorSpec.kt index 0dc51595745..c2dfceaaee5 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UtilityClassWithPublicConstructorSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UtilityClassWithPublicConstructorSpec.kt @@ -14,61 +14,57 @@ class UtilityClassWithPublicConstructorSpec { val subject = UtilityClassWithPublicConstructor(Config.empty) @Nested - inner class `UtilityClassWithPublicConstructor rule` { + inner class `several UtilityClassWithPublicConstructor rule violations` { - @Nested - inner class `several UtilityClassWithPublicConstructor rule violations` { + lateinit var findings: List - lateinit var findings: List - - @BeforeEach - fun beforeEachTest() { - findings = subject.lint(Case.UtilityClassesPositive.path()) - } + @BeforeEach + fun beforeEachTest() { + findings = subject.lint(Case.UtilityClassesPositive.path()) + } - @Test - fun `reports utility classes with a public constructor`() { - assertThat(findings).hasSize(6) - } + @Test + fun `reports utility classes with a public constructor`() { + assertThat(findings).hasSize(6) + } - @Test - fun `reports utility classes which are marked as open`() { - val count = - findings.count { it.message.contains("The utility class OpenUtilityClass should be final.") } - assertThat(count).isEqualTo(1) - } + @Test + fun `reports utility classes which are marked as open`() { + val count = + findings.count { it.message.contains("The utility class OpenUtilityClass should be final.") } + assertThat(count).isEqualTo(1) } + } - @Nested - inner class `several classes which adhere to the UtilityClassWithPublicConstructor rule` { + @Nested + inner class `several classes which adhere to the UtilityClassWithPublicConstructor rule` { - @Test - fun `does not report given classes`() { - val findings = subject.lint(Case.UtilityClassesNegative.path()) - assertThat(findings).isEmpty() - } + @Test + fun `does not report given classes`() { + val findings = subject.lint(Case.UtilityClassesNegative.path()) + assertThat(findings).isEmpty() } + } - @Nested - inner class `annotations class` { + @Nested + inner class `annotations class` { - @Test - fun `should not get triggered for utility class`() { - val code = """ - @Retention(AnnotationRetention.SOURCE) - @StringDef( - Gender.MALE, - Gender.FEMALE - ) - annotation class Gender { - companion object { - const val MALE = "male" - const val FEMALE = "female" - } + @Test + fun `should not get triggered for utility class`() { + val code = """ + @Retention(AnnotationRetention.SOURCE) + @StringDef( + Gender.MALE, + Gender.FEMALE + ) + annotation class Gender { + companion object { + const val MALE = "male" + const val FEMALE = "female" } - """ - assertThat(subject.lint(code)).isEmpty() } + """ + assertThat(subject.lint(code)).isEmpty() } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/WildcardImportSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/WildcardImportSpec.kt index 55448b4b6dc..d70d51de5d7 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/WildcardImportSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/WildcardImportSpec.kt @@ -13,103 +13,99 @@ private const val EXCLUDED_IMPORTS = "excludeImports" class WildcardImportSpec { @Nested - inner class `WildcardImport rule` { + inner class `a kt file with wildcard imports` { + val code = """ + import io.gitlab.arturbosch.detekt.* + import io.mockk.* - @Nested - inner class `a kt file with wildcard imports` { - val code = """ - import io.gitlab.arturbosch.detekt.* - import io.mockk.* - - class Test { - } - """ + class Test { + } + """ - @Test - fun `should not report anything when the rule is turned off`() { - val rule = WildcardImport(TestConfig(mapOf(Config.ACTIVE_KEY to "false"))) + @Test + fun `should not report anything when the rule is turned off`() { + val rule = WildcardImport(TestConfig(mapOf(Config.ACTIVE_KEY to "false"))) - val findings = rule.compileAndLint(code) - assertThat(findings).isEmpty() - } + val findings = rule.compileAndLint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should report all wildcard imports`() { - val rule = WildcardImport() + @Test + fun `should report all wildcard imports`() { + val rule = WildcardImport() - val findings = rule.compileAndLint(code) - assertThat(findings).hasSize(2) - } + val findings = rule.compileAndLint(code) + assertThat(findings).hasSize(2) + } - @Test - fun `should not report excluded wildcard imports`() { - val rule = WildcardImport(TestConfig(mapOf(EXCLUDED_IMPORTS to listOf("io.mockk.*")))) + @Test + fun `should not report excluded wildcard imports`() { + val rule = WildcardImport(TestConfig(mapOf(EXCLUDED_IMPORTS to listOf("io.mockk.*")))) - val findings = rule.compileAndLint(code) - assertThat(findings).hasSize(1) - } + val findings = rule.compileAndLint(code) + assertThat(findings).hasSize(1) + } - @Test - fun `should not report excluded wildcard imports when multiple are excluded`() { - val rule = WildcardImport( - TestConfig( - mapOf( - EXCLUDED_IMPORTS to listOf( - "io.mockk.*", - "io.gitlab.arturbosch.detekt" - ) + @Test + fun `should not report excluded wildcard imports when multiple are excluded`() { + val rule = WildcardImport( + TestConfig( + mapOf( + EXCLUDED_IMPORTS to listOf( + "io.mockk.*", + "io.gitlab.arturbosch.detekt" ) ) ) + ) - val findings = rule.compileAndLint(code) - assertThat(findings).isEmpty() - } + val findings = rule.compileAndLint(code) + assertThat(findings).isEmpty() + } - @Test - fun `should not report excluded wildcard imports when multiple are excluded using config string`() { - val rule = - WildcardImport(TestConfig(mapOf(EXCLUDED_IMPORTS to "io.mockk.*, io.gitlab.arturbosch.detekt"))) + @Test + fun `should not report excluded wildcard imports when multiple are excluded using config string`() { + val rule = + WildcardImport(TestConfig(mapOf(EXCLUDED_IMPORTS to "io.mockk.*, io.gitlab.arturbosch.detekt"))) - val findings = rule.compileAndLint(code) - assertThat(findings).isEmpty() - } + val findings = rule.compileAndLint(code) + assertThat(findings).isEmpty() + } - @Test - fun `ignores excludes that are not matching`() { - val rule = WildcardImport(TestConfig(mapOf(EXCLUDED_IMPORTS to listOf("other.test.*")))) + @Test + fun `ignores excludes that are not matching`() { + val rule = WildcardImport(TestConfig(mapOf(EXCLUDED_IMPORTS to listOf("other.test.*")))) - val findings = rule.compileAndLint(code) - assertThat(findings).hasSize(2) - } + val findings = rule.compileAndLint(code) + assertThat(findings).hasSize(2) + } - @Test - fun `ignores the default values`() { - val code2 = """ - import java.util.* - """ + @Test + fun `ignores the default values`() { + val code2 = """ + import java.util.* + """ - val findings = WildcardImport().lint(code2) - assertThat(findings).isEmpty() - } + val findings = WildcardImport().lint(code2) + assertThat(findings).isEmpty() } + } - @Nested - inner class `a kt file with no wildcard imports` { - val code = """ - package org + @Nested + inner class `a kt file with no wildcard imports` { + val code = """ + package org - import io.mockk.mockk + import io.mockk.mockk - class Test { - } - """ + class Test { + } + """ - @Test - fun `should not report any issues`() { - val findings = WildcardImport().compileAndLint(code) - assertThat(findings).isEmpty() - } + @Test + fun `should not report any issues`() { + val findings = WildcardImport().compileAndLint(code) + assertThat(findings).isEmpty() } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/optional/OptionalUnitSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/optional/OptionalUnitSpec.kt index 5887cb6b4d6..e097381adf8 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/optional/OptionalUnitSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/optional/OptionalUnitSpec.kt @@ -16,398 +16,395 @@ class OptionalUnitSpec(val env: KotlinCoreEnvironment) { val subject = OptionalUnit(Config.empty) - @Nested - inner class `OptionalUnit rule` { - @Test - fun `should report when a function has an explicit Unit return type with context`() { - val code = """ - fun foo(): Unit { } - """.trimIndent() - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + @Test + fun `should report when a function has an explicit Unit return type with context`() { + val code = """ + fun foo(): Unit { } + """.trimIndent() + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } - @Test - fun `should not report when a function has a non-unit body expression`() { - val code = """ - fun foo() = String - """.trimIndent() - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + @Test + fun `should not report when a function has a non-unit body expression`() { + val code = """ + fun foo() = String + """.trimIndent() + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Nested - inner class `several functions which return Unit` { + @Nested + inner class `several functions which return Unit` { - val code = """ - fun returnsUnit1(): Unit { - fun returnsUnitNested(): Unit { - return Unit - } + val code = """ + fun returnsUnit1(): Unit { + fun returnsUnitNested(): Unit { return Unit } - - fun returnsUnit2() = Unit - """ - lateinit var findings: List - - @BeforeEach - fun beforeEachTest() { - findings = subject.compileAndLint(code) + return Unit } - @Test - fun `should report functions returning Unit`() { - assertThat(findings).hasSize(3) - } + fun returnsUnit2() = Unit + """ + lateinit var findings: List - @Test - fun `should report the correct violation message`() { - findings.forEach { - assertThat(it.message).endsWith( - " defines a return type of Unit. This is unnecessary and can safely be removed." - ) - } - } + @BeforeEach + fun beforeEachTest() { + findings = subject.compileAndLint(code) } - @Nested - inner class `an overridden function which returns Unit` { + @Test + fun `should report functions returning Unit`() { + assertThat(findings).hasSize(3) + } - @Test - fun `should not report Unit return type in overridden function`() { - val code = """ - interface I { - fun returnsUnit() - } - class C : I { - override fun returnsUnit() = Unit - } - """ - val findings = subject.compileAndLint(code) - assertThat(findings).isEmpty() + @Test + fun `should report the correct violation message`() { + findings.forEach { + assertThat(it.message).endsWith( + " defines a return type of Unit. This is unnecessary and can safely be removed." + ) } } + } - @Nested - inner class `several lone Unit statements` { + @Nested + inner class `an overridden function which returns Unit` { + @Test + fun `should not report Unit return type in overridden function`() { val code = """ - fun returnsNothing() { - Unit - val i: (Int) -> Unit = { _ -> Unit } - if (true) { - Unit - } + interface I { + fun returnsUnit() } - - class A { - init { - Unit - } + class C : I { + override fun returnsUnit() = Unit } """ - lateinit var findings: List + val findings = subject.compileAndLint(code) + assertThat(findings).isEmpty() + } + } - @BeforeEach - fun beforeEachTest() { - findings = subject.compileAndLint(code) - } + @Nested + inner class `several lone Unit statements` { - @Test - fun `should report lone Unit statement`() { - assertThat(findings).hasSize(4) + val code = """ + fun returnsNothing() { + Unit + val i: (Int) -> Unit = { _ -> Unit } + if (true) { + Unit + } } - @Test - fun `should report the correct violation message`() { - findings.forEach { - assertThat(it.message).isEqualTo("A single Unit expression is unnecessary and can safely be removed.") + class A { + init { + Unit } } + """ + lateinit var findings: List + + @BeforeEach + fun beforeEachTest() { + findings = subject.compileAndLint(code) } - @Nested - inner class `several Unit references` { - - @Test - fun `should not report Unit reference`() { - val findings = subject.compileAndLint( - """ - fun returnsNothing(u: Unit, us: () -> String) { - val u1 = u is Unit - val u2: Unit = Unit - val Unit = 1 - Unit.equals(null) - val i: (Int) -> Unit = { _ -> } - } - """ - ) - assertThat(findings).isEmpty() + @Test + fun `should report lone Unit statement`() { + assertThat(findings).hasSize(4) + } + + @Test + fun `should report the correct violation message`() { + findings.forEach { + assertThat(it.message).isEqualTo("A single Unit expression is unnecessary and can safely be removed.") } } + } - @Nested - inner class `a default interface implementation` { - @Test - fun `should report Unit as part of default interface implementations`() { - val code = """ - interface Foo { - fun method(i: Int) = Unit - } + @Nested + inner class `several Unit references` { + + @Test + fun `should not report Unit reference`() { + val findings = subject.compileAndLint( """ - val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(1) - } + fun returnsNothing(u: Unit, us: () -> String) { + val u1 = u is Unit + val u2: Unit = Unit + val Unit = 1 + Unit.equals(null) + val i: (Int) -> Unit = { _ -> } + } + """ + ) + assertThat(findings).isEmpty() } + } - @Nested - inner class `last statement in block - #2452` { - @Test - fun `unused as an expression`() { - val code = """ - fun test(i: Int, b: Boolean) { - when (i) { - 0 -> println(1) - else -> { - if (b) { - println(2) - } - Unit + @Nested + inner class `a default interface implementation` { + @Test + fun `should report Unit as part of default interface implementations`() { + val code = """ + interface Foo { + fun method(i: Int) = Unit + } + """ + val findings = subject.compileAndLint(code) + assertThat(findings).hasSize(1) + } + } + + @Nested + inner class `last statement in block - #2452` { + @Test + fun `unused as an expression`() { + val code = """ + fun test(i: Int, b: Boolean) { + when (i) { + 0 -> println(1) + else -> { + if (b) { + println(2) } + Unit } } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } - @Test - fun `used as an expression and the previous expression is not a Unit type`() { - val code = """ - fun T.foo() { - println(this) - } - - fun test(i: Int, b: Boolean) { - when (i) { - 0 -> println(1) - else -> { - 1 - Unit - } - }.foo() - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + @Test + fun `used as an expression and the previous expression is not a Unit type`() { + val code = """ + fun T.foo() { + println(this) + } + + fun test(i: Int, b: Boolean) { + when (i) { + 0 -> println(1) + else -> { + 1 + Unit + } + }.foo() + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `used as an expression and the previous expression cannot be used as a value`() { - val code = """ - fun T.foo() { - println(this) - } - - fun test(i: Int, j: Int) { - when (i) { - 0 -> println(1) - else -> { - if (j == 1) { - println(2) - } else if (j == 2) { - println(3) - } else if (j == 3) { - println(4) - } - Unit + @Test + fun `used as an expression and the previous expression cannot be used as a value`() { + val code = """ + fun T.foo() { + println(this) + } + + fun test(i: Int, j: Int) { + when (i) { + 0 -> println(1) + else -> { + if (j == 1) { + println(2) + } else if (j == 2) { + println(3) + } else if (j == 3) { + println(4) } - }.foo() - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + Unit + } + }.foo() + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `used as an expression and the previous expression cannot be used as a value 2`() { - val code = """ - fun T.foo() { - println(this) - } - - fun test(i: Int, j: Int) { - when (i) { - 0 -> println(1) - else -> { - when (j) { - 1 -> println(2) - 2 -> println(3) - 3 -> println(4) - } - Unit + @Test + fun `used as an expression and the previous expression cannot be used as a value 2`() { + val code = """ + fun T.foo() { + println(this) + } + + fun test(i: Int, j: Int) { + when (i) { + 0 -> println(1) + else -> { + when (j) { + 1 -> println(2) + 2 -> println(3) + 3 -> println(4) } - }.foo() - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + Unit + } + }.foo() + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `used as an expression and the previous expression can be used as a value`() { - val code = """ - fun T.foo() { - println(this) - } - - fun test(i: Int, j: Int) { - when (i) { - 0 -> println(1) - else -> { - if (j == 1) { - println(2) - } else if (j == 2) { - println(3) - } else if (j == 3) { - println(4) - } else { - println(5) - } - Unit + @Test + fun `used as an expression and the previous expression can be used as a value`() { + val code = """ + fun T.foo() { + println(this) + } + + fun test(i: Int, j: Int) { + when (i) { + 0 -> println(1) + else -> { + if (j == 1) { + println(2) + } else if (j == 2) { + println(3) + } else if (j == 3) { + println(4) + } else { + println(5) } - }.foo() - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + Unit + } + }.foo() + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } - @Test - fun `used as an expression and the previous expression can be used as a value 2`() { - val code = """ - fun T.foo() { - println(this) - } - - fun test(i: Int, j: Int) { - when (i) { - 0 -> println(1) - else -> { - when (j) { - 1 -> println(2) - 2 -> println(3) - 3 -> println(4) - else -> println(5) - } - Unit + @Test + fun `used as an expression and the previous expression can be used as a value 2`() { + val code = """ + fun T.foo() { + println(this) + } + + fun test(i: Int, j: Int) { + when (i) { + 0 -> println(1) + else -> { + when (j) { + 1 -> println(2) + 2 -> println(3) + 3 -> println(4) + else -> println(5) } - }.foo() - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + Unit + } + }.foo() + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } - @Test - fun `used as an expression and the previous expression can be used as a value 3`() { - val code = """ - fun T.foo() { - println(this) - } - - enum class E { A, B } - - fun test(i: Int, e: E) { - when (i) { - 0 -> println(1) - else -> { - when (e) { - E.A -> println(1) - E.B -> println(2) - } - Unit + @Test + fun `used as an expression and the previous expression can be used as a value 3`() { + val code = """ + fun T.foo() { + println(this) + } + + enum class E { A, B } + + fun test(i: Int, e: E) { + when (i) { + 0 -> println(1) + else -> { + when (e) { + E.A -> println(1) + E.B -> println(2) } - }.foo() - } - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + Unit + } + }.foo() + } + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } - @Test - fun `another object is used as the last expression`() { - val code = """ - fun foo() { - String - } - """.trimIndent() - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + @Test + fun `another object is used as the last expression`() { + val code = """ + fun foo() { + String + } + """.trimIndent() + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() } + } - @Nested - inner class `function initializers` { - @Test - fun `should not report when function initializer is Nothing`() { - val code = """ - fun test(): Unit = throw UnsupportedOperationException() - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + @Nested + inner class `function initializers` { + @Test + fun `should not report when function initializer is Nothing`() { + val code = """ + fun test(): Unit = throw UnsupportedOperationException() + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `should not report when the function initializer requires a type`() { - val code = """ - fun foo(block: (List) -> Unit): T { - val list = listOf() - block(list) - return list.first() - } - - fun doFoo(): Unit = foo {} - """.trimIndent() - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).isEmpty() - } + @Test + fun `should not report when the function initializer requires a type`() { + val code = """ + fun foo(block: (List) -> Unit): T { + val list = listOf() + block(list) + return list.first() + } - @Test - fun `should report on function initializers when there is no context`() { - val code = """ - fun test(): Unit = throw UnsupportedOperationException() - """ - val findings = subject.compileAndLint(code) - assertThat(findings).hasSize(1) - } + fun doFoo(): Unit = foo {} + """.trimIndent() + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).isEmpty() + } - @Test - fun `should report when the function initializer takes in the type Nothing`() { - val code = """ - fun foo(block: (List) -> Unit): T { - val list = listOf() - block(list) - return list.first() - } - - fun doFoo(): Unit = foo {} - """.trimIndent() - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + @Test + fun `should report on function initializers when there is no context`() { + val code = """ + fun test(): Unit = throw UnsupportedOperationException() + """ + val findings = subject.compileAndLint(code) + assertThat(findings).hasSize(1) + } - @Test - fun `should report when the function initializer does not provide a different type`() { - val code = """ - fun foo() {} - - fun doFoo(): Unit = foo() - """.trimIndent() - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - } + @Test + fun `should report when the function initializer takes in the type Nothing`() { + val code = """ + fun foo(block: (List) -> Unit): T { + val list = listOf() + block(list) + return list.first() + } + + fun doFoo(): Unit = foo {} + """.trimIndent() + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + } + + @Test + fun `should report when the function initializer does not provide a different type`() { + val code = """ + fun foo() {} + + fun doFoo(): Unit = foo() + """.trimIndent() + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) } } } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/optional/PreferToOverPairSyntaxSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/optional/PreferToOverPairSyntaxSpec.kt index b0760e95ba2..50aaf676d75 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/optional/PreferToOverPairSyntaxSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/optional/PreferToOverPairSyntaxSpec.kt @@ -5,65 +5,60 @@ import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @KotlinCoreEnvironmentTest class PreferToOverPairSyntaxSpec(val env: KotlinCoreEnvironment) { val subject = PreferToOverPairSyntax(Config.empty) - @Nested - inner class `PreferToOverPairSyntax rule` { + @Test + fun `reports if pair is created using pair constructor`() { + val code = """ + val pair1 = Pair(1, 2) + val pair2: Pair = Pair(1, 2) + val pair3 = Pair(Pair(1, 2), Pair(3, 4)) + """ - @Test - fun `reports if pair is created using pair constructor`() { - val code = """ - val pair1 = Pair(1, 2) - val pair2: Pair = Pair(1, 2) - val pair3 = Pair(Pair(1, 2), Pair(3, 4)) - """ - - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(5) - assertThat(findings[0].message).endsWith("`1 to 2`.") - } + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(5) + assertThat(findings[0].message).endsWith("`1 to 2`.") + } - @Test - fun `reports if pair is created using a function that uses pair constructor`() { - val code = """ - val pair = createPair() - fun createPair() = Pair(1, 2) - """ - val findings = subject.compileAndLintWithContext(env, code) - assertThat(findings).hasSize(1) - assertThat(findings[0].message).endsWith("`1 to 2`.") - } + @Test + fun `reports if pair is created using a function that uses pair constructor`() { + val code = """ + val pair = createPair() + fun createPair() = Pair(1, 2) + """ + val findings = subject.compileAndLintWithContext(env, code) + assertThat(findings).hasSize(1) + assertThat(findings[0].message).endsWith("`1 to 2`.") + } - @Test - fun `does not report if it is created using the to syntax`() { - val code = "val pair = 1 to 2" - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does not report if it is created using the to syntax`() { + val code = "val pair = 1 to 2" + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report if a non-Kotlin Pair class was used`() { - val code = """ - val pair1 = Pair(1, 2) - val pair2: Pair = Pair(1, 2) - val pair3 = Pair(Pair(1, 2), Pair(3, 4)) + @Test + fun `does not report if a non-Kotlin Pair class was used`() { + val code = """ + val pair1 = Pair(1, 2) + val pair2: Pair = Pair(1, 2) + val pair3 = Pair(Pair(1, 2), Pair(3, 4)) - data class Pair(val int1: T, val int2: Z) - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + data class Pair(val int1: T, val int2: Z) + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } - @Test - fun `does not report if pair is created using a function that uses the to syntax`() { - val code = """ - val pair = createPair() - fun createPair() = 1 to 2 - """ - assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() - } + @Test + fun `does not report if pair is created using a function that uses the to syntax`() { + val code = """ + val pair = createPair() + fun createPair() = 1 to 2 + """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } } diff --git a/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/RuleProviderConfigSpec.kt b/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/RuleProviderConfigSpec.kt index aaaede2dabf..c83ef0b9e9a 100644 --- a/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/RuleProviderConfigSpec.kt +++ b/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/RuleProviderConfigSpec.kt @@ -4,31 +4,26 @@ import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.internal.DefaultRuleSetProvider import io.gitlab.arturbosch.detekt.test.TestConfig import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import org.reflections.Reflections class RuleProviderConfigSpec { - @Nested - inner class `RuleProvider config test` { + @Test + fun `should test if the config has been passed to all rules`() { + val config = TestConfig() + val reflections = Reflections("io.gitlab.arturbosch.detekt.rules") + val providers = reflections.getSubTypesOf(DefaultRuleSetProvider::class.java) - @Test - fun `should test if the config has been passed to all rules`() { - val config = TestConfig() - val reflections = Reflections("io.gitlab.arturbosch.detekt.rules") - val providers = reflections.getSubTypesOf(DefaultRuleSetProvider::class.java) - - providers.forEach { - val provider = it.getDeclaredConstructor().newInstance() - val ruleSet = provider.instance(config) - ruleSet.rules.forEach { baseRule -> - val rule = baseRule as? Rule - if (rule != null) { - assertThat(rule.ruleSetConfig) - .withFailMessage("No config was passed to ${rule.javaClass.name}") - .isEqualTo(config) - } + providers.forEach { + val provider = it.getDeclaredConstructor().newInstance() + val ruleSet = provider.instance(config) + ruleSet.rules.forEach { baseRule -> + val rule = baseRule as? Rule + if (rule != null) { + assertThat(rule.ruleSetConfig) + .withFailMessage("No config was passed to ${rule.javaClass.name}") + .isEqualTo(config) } } } diff --git a/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/RuleProviderSpec.kt b/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/RuleProviderSpec.kt index 536aae0d204..51ee19e6bb5 100644 --- a/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/RuleProviderSpec.kt +++ b/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/RuleProviderSpec.kt @@ -16,31 +16,26 @@ import io.gitlab.arturbosch.detekt.rules.naming.NamingProvider import io.gitlab.arturbosch.detekt.rules.performance.PerformanceProvider import io.gitlab.arturbosch.detekt.rules.style.StyleGuideProvider import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import org.reflections.Reflections import java.lang.reflect.Modifier class RuleProviderSpec { - @Nested - inner class `Rule Provider` { - - @Test - fun `checks whether all rules are called in the corresponding RuleSetProvider`() { - val reflections = Reflections("io.gitlab.arturbosch.detekt.rules") - val providers = reflections.getSubTypesOf(DefaultRuleSetProvider::class.java) - providers.forEach { providerType -> - val packageName = getRulesPackageNameForProvider(providerType) - val provider = providerType.getDeclaredConstructor().newInstance() - val rules = getRules(provider) - val classes = getClasses(packageName) - classes.forEach { clazz -> - val rule = rules.singleOrNull { it.javaClass.simpleName == clazz.simpleName } - assertThat(rule).withFailMessage( - "Rule $clazz is not called in the corresponding RuleSetProvider $providerType" - ).isNotNull() - } + @Test + fun `checks whether all rules are called in the corresponding RuleSetProvider`() { + val reflections = Reflections("io.gitlab.arturbosch.detekt.rules") + val providers = reflections.getSubTypesOf(DefaultRuleSetProvider::class.java) + providers.forEach { providerType -> + val packageName = getRulesPackageNameForProvider(providerType) + val provider = providerType.getDeclaredConstructor().newInstance() + val rules = getRules(provider) + val classes = getClasses(packageName) + classes.forEach { clazz -> + val rule = rules.singleOrNull { it.javaClass.simpleName == clazz.simpleName } + assertThat(rule).withFailMessage( + "Rule $clazz is not called in the corresponding RuleSetProvider $providerType" + ).isNotNull() } } } diff --git a/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/SuppressingSpec.kt b/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/SuppressingSpec.kt index 1b005bc4314..0db56623c14 100644 --- a/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/SuppressingSpec.kt +++ b/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/SuppressingSpec.kt @@ -12,58 +12,53 @@ import io.gitlab.arturbosch.detekt.rules.complexity.TooManyFunctions import io.gitlab.arturbosch.detekt.test.TestConfig import io.gitlab.arturbosch.detekt.test.lint import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test class SuppressingSpec { - @Nested - inner class `Rule suppression` { + @Test + fun `all findings are suppressed on element levels`() { + val ktFile = compileForTest(resourceAsPath("SuppressedByElementAnnotation.kt")) + val ruleSet = RuleSet("Test", listOf(LongMethod(), LongParameterList(), ComplexCondition())) - @Test - fun `all findings are suppressed on element levels`() { - val ktFile = compileForTest(resourceAsPath("SuppressedByElementAnnotation.kt")) - val ruleSet = RuleSet("Test", listOf(LongMethod(), LongParameterList(), ComplexCondition())) + val findings = ruleSet.visitFile(ktFile) - val findings = ruleSet.visitFile(ktFile) - - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `all findings are suppressed on file levels`() { - val ktFile = compileForTest(resourceAsPath("SuppressedElementsByFileAnnotation.kt")) - val ruleSet = RuleSet("Test", listOf(LongMethod(), LongParameterList(), ComplexCondition())) + @Test + fun `all findings are suppressed on file levels`() { + val ktFile = compileForTest(resourceAsPath("SuppressedElementsByFileAnnotation.kt")) + val ruleSet = RuleSet("Test", listOf(LongMethod(), LongParameterList(), ComplexCondition())) - val findings = ruleSet.visitFile(ktFile) + val findings = ruleSet.visitFile(ktFile) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `all findings are suppressed on class levels`() { - val ktFile = compileForTest(resourceAsPath("SuppressedElementsByClassAnnotation.kt")) - val ruleSet = RuleSet("Test", listOf(LongMethod(), LongParameterList(), ComplexCondition())) + @Test + fun `all findings are suppressed on class levels`() { + val ktFile = compileForTest(resourceAsPath("SuppressedElementsByClassAnnotation.kt")) + val ruleSet = RuleSet("Test", listOf(LongMethod(), LongParameterList(), ComplexCondition())) - val findings = ruleSet.visitFile(ktFile) + val findings = ruleSet.visitFile(ktFile) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `should suppress TooManyFunctionsRule on class level`() { - val rule = TooManyFunctions(TestConfig(mapOf("thresholdInClass" to "0"))) + @Test + fun `should suppress TooManyFunctionsRule on class level`() { + val rule = TooManyFunctions(TestConfig(mapOf("thresholdInClass" to "0"))) - val findings = rule.lint(resourceAsPath("SuppressedElementsByClassAnnotation.kt")) + val findings = rule.lint(resourceAsPath("SuppressedElementsByClassAnnotation.kt")) - assertThat(findings).isEmpty() - } + assertThat(findings).isEmpty() + } - @Test - fun `should suppress StringLiteralDuplication on class level`() { - val path = resourceAsPath("SuppressStringLiteralDuplication.kt") + @Test + fun `should suppress StringLiteralDuplication on class level`() { + val path = resourceAsPath("SuppressStringLiteralDuplication.kt") - assertThat(StringLiteralDuplication().lint(path)).isEmpty() - } + assertThat(StringLiteralDuplication().lint(path)).isEmpty() } } diff --git a/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/LicenceHeaderLoaderExtensionSpec.kt b/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/LicenceHeaderLoaderExtensionSpec.kt index 8b6f5ade7d9..3a0474dfb3b 100644 --- a/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/LicenceHeaderLoaderExtensionSpec.kt +++ b/detekt-rules/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/documentation/LicenceHeaderLoaderExtensionSpec.kt @@ -6,7 +6,6 @@ import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.api.SetupContext import io.gitlab.arturbosch.detekt.api.UnstableApi import org.assertj.core.api.Assertions.assertThatCode -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import java.io.PrintStream import java.net.URI @@ -14,21 +13,17 @@ import java.net.URI @OptIn(UnstableApi::class) class LicenceHeaderLoaderExtensionSpec { - @Nested - inner class `Licence header extension - #2503` { - - @Test - fun `should not crash when using resources`() { - assertThatCode { - LicenceHeaderLoaderExtension().init(object : SetupContext { - override val configUris: Collection = listOf(resource("extensions/config.yml")) - override val config: Config = Config.empty - override val outputChannel: PrintStream = NullPrintStream() - override val errorChannel: PrintStream = NullPrintStream() - override val properties: Map = HashMap() - override fun register(key: String, value: Any) = Unit - }) - }.doesNotThrowAnyException() - } + @Test + fun `should not crash when using resources - #2503`() { + assertThatCode { + LicenceHeaderLoaderExtension().init(object : SetupContext { + override val configUris: Collection = listOf(resource("extensions/config.yml")) + override val config: Config = Config.empty + override val outputChannel: PrintStream = NullPrintStream() + override val errorChannel: PrintStream = NullPrintStream() + override val properties: Map = HashMap() + override fun register(key: String, value: Any) = Unit + }) + }.doesNotThrowAnyException() } } diff --git a/detekt-tooling/src/test/kotlin/io/github/detekt/tooling/api/DefaultConfigurationProviderSpec.kt b/detekt-tooling/src/test/kotlin/io/github/detekt/tooling/api/DefaultConfigurationProviderSpec.kt index 617e6ccfd4b..00c3deeb0dc 100644 --- a/detekt-tooling/src/test/kotlin/io/github/detekt/tooling/api/DefaultConfigurationProviderSpec.kt +++ b/detekt-tooling/src/test/kotlin/io/github/detekt/tooling/api/DefaultConfigurationProviderSpec.kt @@ -5,22 +5,17 @@ import io.github.detekt.tooling.api.spec.ExtensionId import io.github.detekt.tooling.api.spec.ExtensionsSpec import io.gitlab.arturbosch.detekt.api.Config import org.assertj.core.api.Assertions.assertThatCode -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import java.nio.file.Path class DefaultConfigurationProviderSpec { - @Nested - inner class `default configuration` { - - @Test - fun `loads first found instance`() { - assertThatCode { - DefaultConfigurationProvider.load(Spec) - .copy(createTempFileForTest("test", "test")) - }.doesNotThrowAnyException() - } + @Test + fun `loads first found instance`() { + assertThatCode { + DefaultConfigurationProvider.load(Spec) + .copy(createTempFileForTest("test", "test")) + }.doesNotThrowAnyException() } } diff --git a/detekt-tooling/src/test/kotlin/io/github/detekt/tooling/api/PluginsSpec.kt b/detekt-tooling/src/test/kotlin/io/github/detekt/tooling/api/PluginsSpec.kt index 6861470b570..e0241cec59d 100644 --- a/detekt-tooling/src/test/kotlin/io/github/detekt/tooling/api/PluginsSpec.kt +++ b/detekt-tooling/src/test/kotlin/io/github/detekt/tooling/api/PluginsSpec.kt @@ -3,42 +3,37 @@ package io.github.detekt.tooling.api import io.github.detekt.tooling.dsl.ExtensionsSpecBuilder import io.github.detekt.tooling.internal.PluginsHolder import org.assertj.core.api.Assertions.assertThatCode -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import java.nio.file.Paths class PluginsSpec { - @Nested - inner class `either plugins loaded from Paths or a ClassLoader are supported` { + @Test + fun `throws when both sources are supplied via dsl`() { + assertThatCode { + ExtensionsSpecBuilder().apply { + fromPaths { emptyList() } + fromClassloader { javaClass.classLoader } + }.build() + }.isInstanceOf(IllegalArgumentException::class.java) - @Test - fun `throws when both sources are supplied via dsl`() { - assertThatCode { - ExtensionsSpecBuilder().apply { - fromPaths { emptyList() } - fromClassloader { javaClass.classLoader } - }.build() - }.isInstanceOf(IllegalArgumentException::class.java) - - assertThatCode { - ExtensionsSpecBuilder().apply { - fromClassloader { javaClass.classLoader } - fromPaths { emptyList() } - }.build() - }.isInstanceOf(IllegalArgumentException::class.java) - } + assertThatCode { + ExtensionsSpecBuilder().apply { + fromClassloader { javaClass.classLoader } + fromPaths { emptyList() } + }.build() + }.isInstanceOf(IllegalArgumentException::class.java) + } - @Test - fun `throws when both sources are supplied via internal helper class`() { - assertThatCode { PluginsHolder(emptyList(), javaClass.classLoader) } - .isInstanceOf(IllegalArgumentException::class.java) - } + @Test + fun `throws when both sources are supplied via internal helper class`() { + assertThatCode { PluginsHolder(emptyList(), javaClass.classLoader) } + .isInstanceOf(IllegalArgumentException::class.java) + } - @Test - fun `plugins from paths must exist`() { - assertThatCode { PluginsHolder(listOf(Paths.get("/does/not/exist")), null) } - .isInstanceOf(IllegalArgumentException::class.java) - } + @Test + fun `plugins from paths must exist`() { + assertThatCode { PluginsHolder(listOf(Paths.get("/does/not/exist")), null) } + .isInstanceOf(IllegalArgumentException::class.java) } }