[FIR] Add REDUNDANT_NULLABLE diagnostics
This commit is contained in:
committed by
TeamCityServer
parent
4caf3c5e83
commit
51b73bb6ae
+2
@@ -655,6 +655,8 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<String>("description")
|
||||
parameter<Boolean>("isCastToNotNull")
|
||||
}
|
||||
|
||||
val REDUNDANT_NULLABLE by warning<KtTypeReference>(PositioningStrategy.REDUNDANT_NULLABLE)
|
||||
}
|
||||
|
||||
val REFLECTION by object : DiagnosticGroup("Reflection") {
|
||||
|
||||
+1
@@ -111,6 +111,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
|
||||
PROPERTY_DELEGATE,
|
||||
IMPORT_ALIAS,
|
||||
DECLARATION_START_TO_NAME,
|
||||
REDUNDANT_NULLABLE,
|
||||
|
||||
;
|
||||
|
||||
|
||||
@@ -395,6 +395,7 @@ object FirErrors {
|
||||
val TYPE_VARIANCE_CONFLICT by error4<PsiElement, FirTypeParameterSymbol, Variance, Variance, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
||||
val TYPE_VARIANCE_CONFLICT_IN_EXPANDED_TYPE by error4<PsiElement, FirTypeParameterSymbol, Variance, Variance, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
||||
val SMARTCAST_IMPOSSIBLE by error4<KtExpression, ConeKotlinType, FirExpression, String, Boolean>()
|
||||
val REDUNDANT_NULLABLE by warning0<KtTypeReference>(SourceElementPositioningStrategies.REDUNDANT_NULLABLE)
|
||||
|
||||
// Reflection
|
||||
val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1<KtExpression, FirCallableSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
|
||||
+1
-1
@@ -12,6 +12,6 @@ object CommonTypeCheckers : TypeCheckers() {
|
||||
FirTypeAnnotationChecker,
|
||||
FirSuspendModifierChecker,
|
||||
FirDeprecatedTypeChecker,
|
||||
FirOptInUsageTypeRefChecker,
|
||||
FirOptInUsageTypeRefChecker
|
||||
)
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.extended.RedundantNullableChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.type.*
|
||||
|
||||
object ExtendedTypeCheckers : TypeCheckers() {
|
||||
override val typeRefCheckers: Set<FirTypeRefChecker> = setOf(
|
||||
RedundantNullableChecker
|
||||
)
|
||||
}
|
||||
+24
-4
@@ -6,13 +6,11 @@
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers
|
||||
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.openapi.util.Ref
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiNameIdentifierOwner
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
import org.jetbrains.kotlin.KtLightSourceElement
|
||||
import org.jetbrains.kotlin.KtPsiSourceElement
|
||||
import org.jetbrains.kotlin.KtSourceElement
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.*
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.diagnostics.getAncestors
|
||||
import org.jetbrains.kotlin.diagnostics.nameIdentifier
|
||||
@@ -40,6 +38,8 @@ interface SourceNavigator {
|
||||
|
||||
fun FirValueParameterSymbol.isCatchElementParameter(): Boolean
|
||||
|
||||
fun FirTypeRef.isRedundantNullable(): Boolean
|
||||
|
||||
companion object {
|
||||
|
||||
private val lightTreeInstance = LightTreeSourceNavigator()
|
||||
@@ -90,6 +90,19 @@ open class LightTreeSourceNavigator : SourceNavigator {
|
||||
return source?.getParentOfParent()?.tokenType == KtNodeTypes.CATCH
|
||||
}
|
||||
|
||||
override fun FirTypeRef.isRedundantNullable(): Boolean {
|
||||
val source = source ?: return false
|
||||
val ref = Ref<Array<LighterASTNode?>>()
|
||||
val firstChild = getNullableChild(source, source.lighterASTNode, ref) ?: return false
|
||||
return getNullableChild(source, firstChild, ref) != null
|
||||
}
|
||||
|
||||
private fun getNullableChild(source: KtSourceElement, node: LighterASTNode, ref: Ref<Array<LighterASTNode?>>): LighterASTNode? {
|
||||
source.treeStructure.getChildren(node, ref)
|
||||
val firstChild = ref.get().firstOrNull() ?: return null
|
||||
return if (firstChild.tokenType != KtNodeTypes.NULLABLE_TYPE) null else firstChild
|
||||
}
|
||||
|
||||
private fun KtSourceElement?.getParentOfParent(): LighterASTNode? {
|
||||
val source = this ?: return null
|
||||
var parent = source.treeStructure.getParent(source.lighterASTNode)
|
||||
@@ -131,4 +144,11 @@ object PsiSourceNavigator : LightTreeSourceNavigator() {
|
||||
override fun FirValueParameterSymbol.isCatchElementParameter(): Boolean {
|
||||
return source?.psi<PsiElement>()?.parent?.parent is KtCatchClause
|
||||
}
|
||||
|
||||
override fun FirTypeRef.isRedundantNullable(): Boolean {
|
||||
val source = source ?: return false
|
||||
val typeReference = (source.psi as? KtTypeReference) ?: return false
|
||||
val typeElement = typeReference.typeElement as? KtNullableType ?: return false
|
||||
return typeElement.innerType is KtNullableType
|
||||
}
|
||||
}
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.extended
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.SourceNavigator
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.toClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.type.FirTypeRefChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_NULLABLE
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
|
||||
object RedundantNullableChecker : FirTypeRefChecker() {
|
||||
override fun check(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (typeRef !is FirResolvedTypeRef || typeRef.isMarkedNullable != true) return
|
||||
|
||||
var symbol = typeRef.toClassLikeSymbol(context.session)
|
||||
if (symbol is FirTypeAliasSymbol) {
|
||||
while (symbol is FirTypeAliasSymbol) {
|
||||
val resolvedExpandedTypeRef = symbol.resolvedExpandedTypeRef
|
||||
if (resolvedExpandedTypeRef.type.isMarkedNullable) {
|
||||
reporter.reportOn(typeRef.source, REDUNDANT_NULLABLE, context)
|
||||
break
|
||||
} else {
|
||||
symbol = resolvedExpandedTypeRef.toClassLikeSymbol(context.session)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
with(SourceNavigator.forElement(typeRef)) {
|
||||
if (typeRef.isRedundantNullable()) {
|
||||
reporter.reportOn(typeRef.source, REDUNDANT_NULLABLE, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-7
@@ -236,14 +236,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFIX_MODIFIER_RE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INITIALIZATION_BEFORE_DECLARATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INITIALIZER_TYPE_MISMATCH
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CANNOT_BE_RECURSIVE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CANNOT_EXTEND_CLASSES
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CANNOT_IMPLEMENT_INTERFACE_BY_DELEGATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INLINE_CLASS_CONSTRUCTOR_WRONG_PARAMETERS_SIZE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_HAS_INAPPLICABLE_PARAMETER_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_NOT_FINAL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_NOT_TOP_LEVEL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INLINE_PROPERTY_WITH_BACKING_FIELD
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INNER_CLASS_INSIDE_VALUE_CLASS
|
||||
@@ -394,6 +387,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_LABEL_W
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_MODALITY_MODIFIER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_MODIFIER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_MODIFIER_FOR_TARGET
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_NULLABLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_OPEN_IN_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_PROJECTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_RETURN_UNIT_TYPE
|
||||
@@ -501,6 +495,13 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_ELVIS_RIG
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_IS_CHECK
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_VARARG_ON_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CANNOT_BE_CLONEABLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CANNOT_BE_RECURSIVE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CANNOT_EXTEND_CLASSES
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CANNOT_IMPLEMENT_INTERFACE_BY_DELEGATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_HAS_INAPPLICABLE_PARAMETER_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_NOT_FINAL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_NOT_TOP_LEVEL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAL_OR_VAR_ON_CATCH_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAL_OR_VAR_ON_FUN_PARAMETER
|
||||
@@ -622,6 +623,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
map.put(SUPERTYPE_IS_EXTENSION_FUNCTION_TYPE, "Extension function type is not allowed as supertypes")
|
||||
map.put(SINGLETON_IN_SUPERTYPE, "Cannot inherit from a singleton")
|
||||
map.put(NULLABLE_SUPERTYPE, "A supertype cannot be nullable")
|
||||
map.put(REDUNDANT_NULLABLE, "Redundant '?'")
|
||||
map.put(MANY_CLASSES_IN_SUPERTYPE_LIST, "Only one class may appear in a supertype list")
|
||||
map.put(SUPERTYPE_APPEARS_TWICE, "A supertype appears twice")
|
||||
map.put(CLASS_IN_SUPERTYPE_FOR_ENUM, "Enum class cannot inherit from classes")
|
||||
|
||||
Reference in New Issue
Block a user