mirror of
https://github.com/jlengrand/detekt.git
synced 2026-03-10 08:11:23 +00:00
Replace getJetTypeFqName with fqNameOrNull extension (#3613)
* Replace getJetTypeFqName with fqNameOrNull extension * Remove usage of nameIfStandardType This is from the org.jetbrains.kotlin.js package which should be avoided while detekt is limited to Kotlin/JVM analysis only. * Use KotlinType.fqNameOrNull extension to simplify rule
This commit is contained in:
@@ -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."
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<KotlinType> {
|
||||
val result = mutableSetOf<KotlinType>()
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<KtExpression>): Boolean {
|
||||
val lambdaDescriptor = bindingContext[BindingContext.FUNCTION, this] ?: return false
|
||||
|
||||
@@ -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<ClassDescriptor>()?.fqNameOrNull()
|
||||
private fun KtSimpleNameExpression.classFqName() = getType(bindingContext)?.fqNameOrNull()
|
||||
|
||||
private fun KtSimpleNameExpression.isCollectionOrArrayOrString(): Boolean {
|
||||
val classFqName = classFqName() ?: return false
|
||||
|
||||
Reference in New Issue
Block a user