FIR IDE: add TypeInfoProvider and mixin to host type utils
This commit is contained in:
committed by
Ilya Kirillov
parent
4d505f4393
commit
1496c82108
-1
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.idea.api.applicator.applicator
|
||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtTypeRendererOptions
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.isUnit
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
|
||||
-1
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.idea.fir.api.applicator.inputProvider
|
||||
import org.jetbrains.kotlin.idea.fir.api.applicator.presentation
|
||||
import org.jetbrains.kotlin.idea.fir.applicators.ApplicabilityRanges
|
||||
import org.jetbrains.kotlin.idea.fir.applicators.CallableReturnTypeUpdaterApplicator
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.isUnit
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
|
||||
internal class HLRedundantUnitReturnTypeInspection :
|
||||
|
||||
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.idea.quickfix.fixes
|
||||
|
||||
import org.jetbrains.kotlin.idea.fir.api.fixes.diagnosticFixFactory
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.diagnostics.KtFirDiagnostic
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.isPrimitive
|
||||
import org.jetbrains.kotlin.idea.quickfix.AddModifierFix
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
|
||||
-1
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.idea.api.applicator.applicator
|
||||
import org.jetbrains.kotlin.idea.fir.api.fixes.HLQuickFix
|
||||
import org.jetbrains.kotlin.idea.fir.api.fixes.diagnosticFixFactory
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.diagnostics.KtFirDiagnostic
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.defaultInitializer
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
|
||||
@@ -33,6 +33,7 @@ abstract class KtAnalysisSession(final override val token: ValidityToken) : Vali
|
||||
KtSymbolDeclarationOverridesProviderMixIn,
|
||||
KtExpressionTypeProviderMixIn,
|
||||
KtTypeProviderMixIn,
|
||||
KtTypeInfoProviderMixIn,
|
||||
KtSymbolProviderMixIn,
|
||||
KtSymbolContainingDeclarationProviderMixIn,
|
||||
KtSubtypingComponentMixIn,
|
||||
@@ -83,6 +84,9 @@ abstract class KtAnalysisSession(final override val token: ValidityToken) : Vali
|
||||
internal val typeProvider: KtTypeProvider get() = typeProviderImpl
|
||||
protected abstract val typeProviderImpl: KtTypeProvider
|
||||
|
||||
internal val typeInfoProvider: KtTypeInfoProvider get() = typeInfoProviderImpl
|
||||
protected abstract val typeInfoProviderImpl: KtTypeInfoProvider
|
||||
|
||||
internal val subtypingComponent: KtSubtypingComponent get() = subtypingComponentImpl
|
||||
protected abstract val subtypingComponentImpl: KtSubtypingComponent
|
||||
|
||||
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.idea.frontend.api.components
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtClassType
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeNullability
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeWithNullability
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
|
||||
abstract class KtTypeInfoProvider : KtAnalysisSessionComponent() {
|
||||
abstract fun canBeNull(type: KtType): Boolean
|
||||
}
|
||||
|
||||
interface KtTypeInfoProviderMixIn : KtAnalysisSessionMixIn {
|
||||
/**
|
||||
* Returns true if a value of this type can potentially be null. This means this type is not a subtype of [Any]. However, it does not
|
||||
* mean one can assign `null` to a variable of this type because it may be unknown if this type can accept `null`. For example, a value
|
||||
* of type `T:Any?` can potentially be null. But one can not assign `null` to such a variable because the instantiated type may not be
|
||||
* nullable.
|
||||
*/
|
||||
val KtType.canBeNull: Boolean get() = analysisSession.typeInfoProvider.canBeNull(this)
|
||||
|
||||
/** Returns true if the type is explicitly marked as nullable. This means it's safe to assign `null` to a variable with this type. */
|
||||
val KtType.isMarkedNullable: Boolean get() = (this as? KtTypeWithNullability)?.nullability == KtTypeNullability.NULLABLE
|
||||
|
||||
val KtType.isUnit: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.UNIT)
|
||||
val KtType.isInt: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.INT)
|
||||
val KtType.isLong: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.LONG)
|
||||
val KtType.isShort: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.SHORT)
|
||||
val KtType.isByte: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.BYTE)
|
||||
val KtType.isFloat: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.FLOAT)
|
||||
val KtType.isDouble: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.DOUBLE)
|
||||
val KtType.isChar: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.CHAR)
|
||||
val KtType.isBoolean: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.BOOLEAN)
|
||||
val KtType.isString: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.STRING)
|
||||
|
||||
val KtType.isUInt: Boolean get() = isClassTypeWithClassId(StandardNames.FqNames.uInt)
|
||||
val KtType.isULong: Boolean get() = isClassTypeWithClassId(StandardNames.FqNames.uLong)
|
||||
val KtType.isUShort: Boolean get() = isClassTypeWithClassId(StandardNames.FqNames.uShort)
|
||||
val KtType.isUByte: Boolean get() = isClassTypeWithClassId(StandardNames.FqNames.uByte)
|
||||
|
||||
fun KtType.isClassTypeWithClassId(classId: ClassId): Boolean {
|
||||
if (this !is KtClassType) return false
|
||||
return this.classId == classId
|
||||
}
|
||||
|
||||
val KtType.isPrimitive: Boolean
|
||||
get() {
|
||||
if (this !is KtClassType) return false
|
||||
return this.classId in DefaultTypeClassIds.PRIMITIVES
|
||||
}
|
||||
|
||||
val KtType.defaultInitializer: String?
|
||||
get() = when {
|
||||
isMarkedNullable -> "null"
|
||||
isInt || isLong || isShort || isByte -> "0"
|
||||
isFloat -> "0.0f"
|
||||
isDouble -> "0.0"
|
||||
isChar -> "'\\u0000'"
|
||||
isBoolean -> "false"
|
||||
isUnit -> "Unit"
|
||||
isString -> "\"\""
|
||||
isUInt -> "0.toUInt()"
|
||||
isULong -> "0.toULong()"
|
||||
isUShort -> "0.toUShort()"
|
||||
isUByte -> "0.toUByte()"
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
object DefaultTypeClassIds {
|
||||
val UNIT = ClassId.topLevel(StandardNames.FqNames.unit.toSafe())
|
||||
val INT = ClassId.topLevel(StandardNames.FqNames._int.toSafe())
|
||||
val LONG = ClassId.topLevel(StandardNames.FqNames._long.toSafe())
|
||||
val SHORT = ClassId.topLevel(StandardNames.FqNames._short.toSafe())
|
||||
val BYTE = ClassId.topLevel(StandardNames.FqNames._byte.toSafe())
|
||||
val FLOAT = ClassId.topLevel(StandardNames.FqNames._float.toSafe())
|
||||
val DOUBLE = ClassId.topLevel(StandardNames.FqNames._double.toSafe())
|
||||
val CHAR = ClassId.topLevel(StandardNames.FqNames._char.toSafe())
|
||||
val BOOLEAN = ClassId.topLevel(StandardNames.FqNames._boolean.toSafe())
|
||||
val STRING = ClassId.topLevel(StandardNames.FqNames.string.toSafe())
|
||||
val PRIMITIVES = setOf(INT, LONG, SHORT, BYTE, FLOAT, DOUBLE, CHAR, BOOLEAN)
|
||||
}
|
||||
-3
@@ -32,9 +32,6 @@ interface KtTypeProviderMixIn : KtAnalysisSessionMixIn {
|
||||
|
||||
fun KtNamedClassOrObjectSymbol.buildSelfClassType(): KtType =
|
||||
analysisSession.typeProvider.buildSelfClassType(this)
|
||||
|
||||
val KtType.canBeNull: Boolean
|
||||
|
||||
}
|
||||
|
||||
@Suppress("PropertyName")
|
||||
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.idea.frontend.api.types
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
|
||||
val KtType.isMarkedNullable: Boolean get() = (this as? KtTypeWithNullability)?.nullability == KtTypeNullability.NULLABLE
|
||||
|
||||
val KtType.isUnit: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.UNIT)
|
||||
val KtType.isInt: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.INT)
|
||||
val KtType.isLong: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.LONG)
|
||||
val KtType.isShort: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.SHORT)
|
||||
val KtType.isByte: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.BYTE)
|
||||
val KtType.isFloat: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.FLOAT)
|
||||
val KtType.isDouble: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.DOUBLE)
|
||||
val KtType.isChar: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.CHAR)
|
||||
val KtType.isBoolean: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.BOOLEAN)
|
||||
val KtType.isString: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.STRING)
|
||||
|
||||
val KtType.isUInt: Boolean get() = isClassTypeWithClassId(StandardNames.FqNames.uInt)
|
||||
val KtType.isULong: Boolean get() = isClassTypeWithClassId(StandardNames.FqNames.uLong)
|
||||
val KtType.isUShort: Boolean get() = isClassTypeWithClassId(StandardNames.FqNames.uShort)
|
||||
val KtType.isUByte: Boolean get() = isClassTypeWithClassId(StandardNames.FqNames.uByte)
|
||||
|
||||
|
||||
fun KtType.isClassTypeWithClassId(classId: ClassId): Boolean {
|
||||
if (this !is KtClassType) return false
|
||||
return this.classId == classId
|
||||
}
|
||||
|
||||
val KtType.isPrimitive: Boolean
|
||||
get() {
|
||||
if (this !is KtClassType) return false
|
||||
return this.classId in DefaultTypeClassIds.PRIMITIVES
|
||||
}
|
||||
|
||||
private object DefaultTypeClassIds {
|
||||
val UNIT = ClassId.topLevel(StandardNames.FqNames.unit.toSafe())
|
||||
val INT = ClassId.topLevel(StandardNames.FqNames._int.toSafe())
|
||||
val LONG = ClassId.topLevel(StandardNames.FqNames._long.toSafe())
|
||||
val SHORT = ClassId.topLevel(StandardNames.FqNames._short.toSafe())
|
||||
val BYTE = ClassId.topLevel(StandardNames.FqNames._byte.toSafe())
|
||||
val FLOAT = ClassId.topLevel(StandardNames.FqNames._float.toSafe())
|
||||
val DOUBLE = ClassId.topLevel(StandardNames.FqNames._double.toSafe())
|
||||
val CHAR = ClassId.topLevel(StandardNames.FqNames._char.toSafe())
|
||||
val BOOLEAN = ClassId.topLevel(StandardNames.FqNames._boolean.toSafe())
|
||||
val STRING = ClassId.topLevel(StandardNames.FqNames.string.toSafe())
|
||||
val PRIMITIVES = setOf(INT, LONG, SHORT, BYTE, FLOAT, DOUBLE, CHAR, BOOLEAN)
|
||||
}
|
||||
|
||||
val KtType.defaultInitializer: String?
|
||||
get() = when {
|
||||
isMarkedNullable -> "null"
|
||||
isInt || isLong || isShort || isByte -> "0"
|
||||
isFloat -> "0.0f"
|
||||
isDouble -> "0.0"
|
||||
isChar -> "'\\u0000'"
|
||||
isBoolean -> "false"
|
||||
isUnit -> "Unit"
|
||||
isString -> "\"\""
|
||||
isUInt -> "0.toUInt()"
|
||||
isULong -> "0.toULong()"
|
||||
isUShort -> "0.toUShort()"
|
||||
isUByte -> "0.toUByte()"
|
||||
else -> null
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.withFirDeclaration
|
||||
import org.jetbrains.kotlin.idea.frontend.api.components.DefaultTypeClassIds
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirType
|
||||
@@ -35,6 +36,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.*
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||
import java.text.StringCharacterIterator
|
||||
@@ -305,6 +307,12 @@ internal fun KtType.getTypeNullability(context: KtSymbol, phase: FirResolvePhase
|
||||
return if (isNotPrimitiveType) NullabilityType.NotNull else NullabilityType.Unknown
|
||||
}
|
||||
|
||||
internal val KtType.isUnit get() = isClassTypeWithClassId(DefaultTypeClassIds.UNIT)
|
||||
|
||||
internal fun KtType.isClassTypeWithClassId(classId: ClassId): Boolean {
|
||||
if (this !is KtClassType) return false
|
||||
return this.classId == classId
|
||||
}
|
||||
|
||||
private fun escapeString(str: String): String = buildString {
|
||||
str.forEach { char ->
|
||||
|
||||
-1
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.idea.asJava.elements.FirLightTypeParameterListForSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.isValid
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.isUnit
|
||||
import org.jetbrains.kotlin.idea.util.ifTrue
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import java.util.*
|
||||
|
||||
+2
-5
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.types.canBeNull
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.LowLevelFirApiFacadeForCompletion
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getFirFile
|
||||
@@ -21,11 +20,9 @@ import org.jetbrains.kotlin.idea.frontend.api.tokens.ReadActionConfinementValidi
|
||||
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.components.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbolProvider
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirType
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.EnclosingDeclarationContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.recordCompletionContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.threadLocal
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
@@ -62,10 +59,10 @@ private constructor(
|
||||
|
||||
override val expressionInfoProviderImpl = KtFirExpressionInfoProvider(this, token)
|
||||
|
||||
override val KtType.canBeNull: Boolean get() = (this as KtFirType).coneType.canBeNull
|
||||
|
||||
override val typeProviderImpl = KtFirTypeProvider(this, token)
|
||||
|
||||
override val typeInfoProviderImpl = KtFirTypeInfoProvider(this, token)
|
||||
|
||||
override val subtypingComponentImpl = KtFirSubtypingComponent(this, token)
|
||||
|
||||
override fun createContextDependentCopy(originalKtFile: KtFile, fakeKtElement: KtElement): KtAnalysisSession {
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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.idea.frontend.api.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.fir.types.canBeNull
|
||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtTypeInfoProvider
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirType
|
||||
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||
|
||||
internal class KtFirTypeInfoProvider(
|
||||
override val analysisSession: KtFirAnalysisSession,
|
||||
override val token: ValidityToken,
|
||||
) : KtTypeInfoProvider(), KtFirAnalysisSessionComponent {
|
||||
|
||||
override fun canBeNull(type: KtType): Boolean = (type as KtFirType).coneType.canBeNull
|
||||
}
|
||||
Reference in New Issue
Block a user