diff --git a/custom-checks/src/main/kotlin/io/github/detekt/custom/SpekTestDiscovery.kt b/custom-checks/src/main/kotlin/io/github/detekt/custom/SpekTestDiscovery.kt index 4e0dd4ad1..2b9a3929b 100644 --- a/custom-checks/src/main/kotlin/io/github/detekt/custom/SpekTestDiscovery.kt +++ b/custom-checks/src/main/kotlin/io/github/detekt/custom/SpekTestDiscovery.kt @@ -8,7 +8,7 @@ import io.gitlab.arturbosch.detekt.api.Issue import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity import io.gitlab.arturbosch.detekt.api.internal.valueOrDefaultCommaSeparated -import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName +import io.gitlab.arturbosch.detekt.rules.fqNameOrNull import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtLambdaExpression @@ -98,13 +98,14 @@ class SpekTestDiscovery(config: Config = Config.empty) : Rule(config) { if (!property.hasDelegate()) { val initExpr = property.initializer val fqType = initExpr?.getType(bindingContext) - ?.getJetTypeFqName(false) + ?.fqNameOrNull() + ?.asString() if (fqType != null && fqType !in allowedTypes) { report( CodeSmell( issue, Entity.atName(property), - "Variable declarations which do not met the allowed types should be memoized." + "Variable declarations which do not meet the allowed types should be memoized." ) ) } diff --git a/detekt-psi-utils/api/detekt-psi-utils.api b/detekt-psi-utils/api/detekt-psi-utils.api index d93c35d81..f2973caec 100644 --- a/detekt-psi-utils/api/detekt-psi-utils.api +++ b/detekt-psi-utils/api/detekt-psi-utils.api @@ -126,3 +126,7 @@ public final class io/gitlab/arturbosch/detekt/rules/TraversingKt { public static final fun isPublicInherited (Lorg/jetbrains/kotlin/psi/KtNamedDeclaration;)Z } +public final class io/gitlab/arturbosch/detekt/rules/TypeUtilsKt { + public static final fun fqNameOrNull (Lorg/jetbrains/kotlin/types/KotlinType;)Lorg/jetbrains/kotlin/name/FqName; +} + diff --git a/detekt-psi-utils/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/TypeUtils.kt b/detekt-psi-utils/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/TypeUtils.kt new file mode 100644 index 000000000..c731dc917 --- /dev/null +++ b/detekt-psi-utils/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/TypeUtils.kt @@ -0,0 +1,10 @@ +package io.gitlab.arturbosch.detekt.rules + +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeUtils + +fun KotlinType.fqNameOrNull(): FqName? { + return TypeUtils.getClassDescriptor(this)?.fqNameOrNull() +} diff --git a/detekt-rules-coroutines/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/SuspendFunWithFlowReturnType.kt b/detekt-rules-coroutines/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/SuspendFunWithFlowReturnType.kt index b99138265..c2ec61a29 100644 --- a/detekt-rules-coroutines/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/SuspendFunWithFlowReturnType.kt +++ b/detekt-rules-coroutines/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/coroutines/SuspendFunWithFlowReturnType.kt @@ -8,7 +8,7 @@ import io.gitlab.arturbosch.detekt.api.Issue import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity import io.gitlab.arturbosch.detekt.api.internal.RequiresTypeResolution -import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName +import io.gitlab.arturbosch.detekt.rules.fqNameOrNull import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.resolve.BindingContext @@ -92,7 +92,7 @@ class SuspendFunWithFlowReturnType(config: Config) : Rule(config) { yield(this@isCoroutinesFlow) yieldAll(this@isCoroutinesFlow.supertypes()) } - .map { it.getJetTypeFqName(printTypeArguments = false) } + .mapNotNull { it.fqNameOrNull()?.asString() } .contains("kotlinx.coroutines.flow.Flow") } } diff --git a/detekt-rules-errorprone/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DontDowncastCollectionTypes.kt b/detekt-rules-errorprone/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DontDowncastCollectionTypes.kt index 4ca2bfafb..54d18af62 100644 --- a/detekt-rules-errorprone/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DontDowncastCollectionTypes.kt +++ b/detekt-rules-errorprone/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/bugs/DontDowncastCollectionTypes.kt @@ -8,8 +8,8 @@ import io.gitlab.arturbosch.detekt.api.Issue import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity import io.gitlab.arturbosch.detekt.api.internal.RequiresTypeResolution +import io.gitlab.arturbosch.detekt.rules.fqNameOrNull import io.gitlab.arturbosch.detekt.rules.safeAs -import org.jetbrains.kotlin.js.descriptorUtils.nameIfStandardType import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtIsExpression @@ -66,8 +66,9 @@ class DontDowncastCollectionTypes(config: Config) : Rule(config) { private fun checkForDowncast(parent: KtExpression, left: KtExpression, right: KtTypeReference?) { val lhsType = left .getType(bindingContext) - ?.nameIfStandardType - ?.identifier + ?.fqNameOrNull() + ?.shortName() + ?.asString() val rhsType = right ?.typeElement diff --git a/detekt-rules-naming/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NonBooleanPropertyPrefixedWithIs.kt b/detekt-rules-naming/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NonBooleanPropertyPrefixedWithIs.kt index 4626733e0..206ff5d51 100644 --- a/detekt-rules-naming/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NonBooleanPropertyPrefixedWithIs.kt +++ b/detekt-rules-naming/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/naming/NonBooleanPropertyPrefixedWithIs.kt @@ -8,8 +8,8 @@ import io.gitlab.arturbosch.detekt.api.Issue import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity import io.gitlab.arturbosch.detekt.api.internal.RequiresTypeResolution +import io.gitlab.arturbosch.detekt.rules.fqNameOrNull import io.gitlab.arturbosch.detekt.rules.identifierName -import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName import org.jetbrains.kotlin.psi.KtCallableDeclaration import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtProperty @@ -88,6 +88,7 @@ class NonBooleanPropertyPrefixedWithIs(config: Config = Config.empty) : Rule(con private fun getTypeName(parameter: KtCallableDeclaration): String? { return parameter.createTypeBindingForReturnType(bindingContext) ?.type - ?.getJetTypeFqName(false) + ?.fqNameOrNull() + ?.asString() } } diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ExplicitCollectionElementAccessMethod.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ExplicitCollectionElementAccessMethod.kt index f34d4c338..d3f3b730c 100644 --- a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ExplicitCollectionElementAccessMethod.kt +++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ExplicitCollectionElementAccessMethod.kt @@ -7,7 +7,7 @@ import io.gitlab.arturbosch.detekt.api.Entity import io.gitlab.arturbosch.detekt.api.Issue import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity -import org.jetbrains.kotlin.js.descriptorUtils.nameIfStandardType +import io.gitlab.arturbosch.detekt.rules.fqNameOrNull import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtDotQualifiedExpression import org.jetbrains.kotlin.psi.KtElement @@ -34,7 +34,12 @@ import org.jetbrains.kotlin.types.typeUtil.supertypes */ class ExplicitCollectionElementAccessMethod(config: Config = Config.empty) : Rule(config) { - private val ktCollections = setOf("Map", "MutableMap", "List", "MutableList") + private val ktCollections = setOf( + "kotlin.collections.Map", + "kotlin.collections.MutableMap", + "kotlin.collections.List", + "kotlin.collections.MutableList" + ) private val mapAccessMethods = setOf("get", "put") @@ -72,23 +77,7 @@ class ExplicitCollectionElementAccessMethod(config: Config = Config.empty) : Rul } private fun KotlinType?.isEligibleCollection(): Boolean { - this?.nameIfStandardType?.let { - return it.toString() in ktCollections - } - return this?.collectTypes()?.any { it.constructor.toString() in ktAndJavaCollections } == true - } - - private fun KotlinType.collectTypes(): Set { - val result = mutableSetOf() - this - .constructor - .supertypes - .forEach { type -> - result.add(type) - type.supertypes().forEach { - result.addAll(it.collectTypes()) - } - } - return result + if (this?.fqNameOrNull()?.asString() in ktCollections) return true + return this?.supertypes()?.any { it.constructor.toString() in ktAndJavaCollections } == true } } diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenMethodCall.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenMethodCall.kt index f61ef3759..3023c0a4e 100644 --- a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenMethodCall.kt +++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenMethodCall.kt @@ -10,7 +10,7 @@ import io.gitlab.arturbosch.detekt.api.Severity import io.gitlab.arturbosch.detekt.api.internal.RequiresTypeResolution import io.gitlab.arturbosch.detekt.api.internal.valueOrDefaultCommaSeparated import io.gitlab.arturbosch.detekt.rules.extractMethodNameAndParams -import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName +import io.gitlab.arturbosch.detekt.rules.fqNameOrNull import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtExpression @@ -79,7 +79,7 @@ class ForbiddenMethodCall(config: Config = Config.empty) : Rule(config) { val resolvedCall = expression.getResolvedCall(bindingContext) ?: return val methodName = resolvedCall.resultingDescriptor.fqNameOrNull()?.asString() val encounteredParamTypes = resolvedCall.resultingDescriptor.valueParameters - .map { it.type.getJetTypeFqName(false) } + .map { it.type.fqNameOrNull()?.asString() } if (methodName != null) { forbiddenMethods diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenVoid.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenVoid.kt index 2e4c9e918..781141871 100644 --- a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenVoid.kt +++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/ForbiddenVoid.kt @@ -8,7 +8,9 @@ import io.gitlab.arturbosch.detekt.api.Issue import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity import io.gitlab.arturbosch.detekt.api.internal.RequiresTypeResolution +import io.gitlab.arturbosch.detekt.rules.fqNameOrNull import io.gitlab.arturbosch.detekt.rules.isOverride +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtTypeArgumentList @@ -17,7 +19,6 @@ import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.bindingContextUtil.getAbbreviatedTypeOrType -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull /** * This rule detects usages of `Void` and reports them as forbidden. @@ -53,7 +54,7 @@ class ForbiddenVoid(config: Config = Config.empty) : Rule(config) { if (bindingContext == BindingContext.EMPTY) return val kotlinType = typeReference.getAbbreviatedTypeOrType(bindingContext) ?: return - if (kotlinType.constructor.declarationDescriptor?.fqNameOrNull()?.asString() == VOID_CLASS_NAME) { + if (kotlinType.fqNameOrNull() == VOID_FQ_NAME) { if (ruleSetConfig.valueOrDefault(IGNORE_OVERRIDDEN, false) && typeReference.isPartOfOverriddenSignature()) { return } @@ -84,6 +85,6 @@ class ForbiddenVoid(config: Config = Config.empty) : Rule(config) { companion object { const val IGNORE_OVERRIDDEN = "ignoreOverridden" const val IGNORE_USAGE_IN_GENERICS = "ignoreUsageInGenerics" - const val VOID_CLASS_NAME = "java.lang.Void" + val VOID_FQ_NAME = FqName("java.lang.Void") } } diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/RedundantHigherOrderMapUsage.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/RedundantHigherOrderMapUsage.kt index 049361d2d..d5cc512d5 100644 --- a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/RedundantHigherOrderMapUsage.kt +++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/RedundantHigherOrderMapUsage.kt @@ -8,6 +8,7 @@ import io.gitlab.arturbosch.detekt.api.Issue import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity import io.gitlab.arturbosch.detekt.api.internal.RequiresTypeResolution +import io.gitlab.arturbosch.detekt.rules.fqNameOrNull import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtCallExpression @@ -22,8 +23,8 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.bindingContextUtil.getTargetFunctionDescriptor import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes /** * Redundant maps add complexity to the code and accomplish nothing. They should be removed or replaced with the proper @@ -74,7 +75,7 @@ import org.jetbrains.kotlin.types.KotlinType @Suppress("ReturnCount") class RedundantHigherOrderMapUsage(config: Config = Config.empty) : Rule(config) { override val issue: Issue = Issue( - "RedundantHigherOrderMapUsage", + javaClass.simpleName, Severity.Style, "Checks for Redundant 'map' calls.", Debt.FIVE_MINS @@ -115,13 +116,8 @@ class RedundantHigherOrderMapUsage(config: Config = Config.empty) : Rule(config) return lambda } - private fun KotlinType.isInheritorOf(fqName: FqName): Boolean { - return isTypeOf(fqName) || constructor.supertypes.any { it.isTypeOf(fqName) } - } - - private fun KotlinType.isTypeOf(fqName: FqName): Boolean { - return constructor.declarationDescriptor?.fqNameSafe == fqName - } + private fun KotlinType.isInheritorOf(fqName: FqName): Boolean = + fqNameOrNull() == fqName || immediateSupertypes().any { it.fqNameOrNull() == fqName } private fun KtFunctionLiteral.isRedundant(lambdaStatements: List): Boolean { val lambdaDescriptor = bindingContext[BindingContext.FUNCTION, this] ?: return false diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseIsNullOrEmpty.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseIsNullOrEmpty.kt index 96e248588..148bb9e31 100644 --- a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseIsNullOrEmpty.kt +++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/UseIsNullOrEmpty.kt @@ -8,8 +8,8 @@ import io.gitlab.arturbosch.detekt.api.Issue import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity import io.gitlab.arturbosch.detekt.api.internal.RequiresTypeResolution +import io.gitlab.arturbosch.detekt.rules.fqNameOrNull import org.jetbrains.kotlin.builtins.StandardNames -import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtBinaryExpression @@ -138,8 +138,7 @@ class UseIsNullOrEmpty(config: Config = Config.empty) : Rule(config) { callExpression.getResolvedCall(bindingContext)?.resultingDescriptor?.fqNameOrNull() in fqNames } - private fun KtSimpleNameExpression.classFqName() = - getType(bindingContext)?.constructor?.declarationDescriptor.safeAs()?.fqNameOrNull() + private fun KtSimpleNameExpression.classFqName() = getType(bindingContext)?.fqNameOrNull() private fun KtSimpleNameExpression.isCollectionOrArrayOrString(): Boolean { val classFqName = classFqName() ?: return false