FIR: temporarily drop parent manipulation code around super type entries

This commit is contained in:
Mikhail Glukhikh
2021-03-24 18:51:13 +03:00
parent ff4d193891
commit 648bf99842
10 changed files with 36 additions and 92 deletions
@@ -102,6 +102,9 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED by error<FirSourceElement, PsiElement>()
val CYCLIC_CONSTRUCTOR_DELEGATION_CALL by warning<FirSourceElement, PsiElement>()
val PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED by warning<FirSourceElement, PsiElement>(PositioningStrategy.SECONDARY_CONSTRUCTOR_DELEGATION_CALL)
// TODO: change it to KtSuperTypeEntry when possible (after re-targeter implementation)
val SUPERTYPE_NOT_INITIALIZED by error<FirSourceElement, KtTypeReference>()
val SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR by error<FirSourceElement, PsiElement>()
val DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR by warning<FirSourceElement, PsiElement>()
val PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS by error<FirSourceElement, KtNamedDeclaration>(PositioningStrategy.DECLARATION_NAME)
@@ -168,10 +171,6 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
}
}
val CLASSES_AND_INTERFACES by object : DiagnosticGroup("Classes and interfaces") {
val SUPERTYPE_NOT_INITIALIZED by error<FirSourceElement, KtSuperTypeEntry>()
}
val INLINE_CLASSES by object : DiagnosticGroup("Inline classes") {
val INLINE_CLASS_NOT_TOP_LEVEL by error<FirSourceElement, KtDeclaration>(PositioningStrategy.INLINE_OR_VALUE_MODIFIER)
val INLINE_CLASS_NOT_FINAL by error<FirSourceElement, KtDeclaration>(PositioningStrategy.MODALITY_MODIFIER)
@@ -41,7 +41,6 @@ import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPropertyAccessor
import org.jetbrains.kotlin.psi.KtPropertyDelegate
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.psi.KtSuperTypeEntry
import org.jetbrains.kotlin.psi.KtTypeParameter
import org.jetbrains.kotlin.psi.KtTypeParameterList
import org.jetbrains.kotlin.psi.KtTypeReference
@@ -106,6 +105,7 @@ object FirErrors {
val NON_PRIVATE_OR_PROTECTED_CONSTRUCTOR_IN_SEALED by error0<FirSourceElement, PsiElement>()
val CYCLIC_CONSTRUCTOR_DELEGATION_CALL by warning0<FirSourceElement, PsiElement>()
val PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED by warning0<FirSourceElement, PsiElement>(SourceElementPositioningStrategies.SECONDARY_CONSTRUCTOR_DELEGATION_CALL)
val SUPERTYPE_NOT_INITIALIZED by error0<FirSourceElement, KtTypeReference>()
val SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR by error0<FirSourceElement, PsiElement>()
val DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR by warning0<FirSourceElement, PsiElement>()
val PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS by error0<FirSourceElement, KtNamedDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
@@ -150,9 +150,6 @@ object FirErrors {
val REDUNDANT_OPEN_IN_INTERFACE by warning0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.OPEN_MODIFIER)
val WRONG_MODIFIER_TARGET by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, String>()
// Classes and interfaces
val SUPERTYPE_NOT_INITIALIZED by error0<FirSourceElement, KtSuperTypeEntry>()
// Inline classes
val INLINE_CLASS_NOT_TOP_LEVEL by error0<FirSourceElement, KtDeclaration>(SourceElementPositioningStrategies.INLINE_OR_VALUE_MODIFIER)
val INLINE_CLASS_NOT_FINAL by error0<FirSourceElement, KtDeclaration>(SourceElementPositioningStrategies.MODALITY_MODIFIER)
@@ -5,8 +5,6 @@
package org.jetbrains.kotlin.fir.analysis
import com.intellij.lang.LighterASTNode
import com.intellij.psi.PsiElement
import com.intellij.psi.tree.IElementType
import com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.fir.*
@@ -38,54 +36,6 @@ private fun FirPsiSourceElement<*>.getChild(types: Set<IElementType>, index: Int
private fun FirLightSourceElement.getChild(types: Set<IElementType>, index: Int, depth: Int): FirSourceElement? {
val visitor = LighterTreeElementFinderByType(treeStructure, types, index, depth)
return visitor.find(lighterASTNode)?.let { withNode(it) }
return visitor.find(lighterASTNode)?.toFirLightSourceElement(treeStructure)
}
fun FirSourceElement.getParent(type: IElementType, includingSelf: Boolean = false): FirSourceElement? {
return getParent(setOf(type), includingSelf)
}
fun FirSourceElement.getParent(types: TokenSet, includingSelf: Boolean = false): FirSourceElement? {
return getParent(types.types.toSet(), includingSelf)
}
fun FirSourceElement.getParent(types: Set<IElementType>, includingSelf: Boolean = false): FirSourceElement? {
return when (this) {
is FirPsiSourceElement<*> -> {
getParent(types, includingSelf)
}
is FirLightSourceElement -> {
getParent(types, includingSelf)
}
else -> null
}
}
private fun FirPsiSourceElement<*>.getParent(types: Set<IElementType>, includingSelf: Boolean): FirSourceElement? {
var parent: PsiElement? = if (includingSelf) psi else psi.parent
while (parent != null && parent.node.elementType !in types) {
parent = parent.parent
}
return parent?.toFirPsiSourceElement()
}
private fun FirLightSourceElement.getParent(types: Set<IElementType>, includingSelf: Boolean): FirSourceElement? {
var parent: LighterASTNode? = if (includingSelf) lighterASTNode else treeStructure.getParent(lighterASTNode)
while (parent != null && parent.tokenType !in types) {
parent = treeStructure.getParent(parent)
}
return parent?.let { withNode(it) }
}
private fun FirLightSourceElement.withNode(newNode: LighterASTNode): FirLightSourceElement {
// It seems sometimes the `startOffset` from a `LighterASTNode` could count from some partial sub tree of the file. If this is the case,
// we need to compute the delta between the corresponding position in this partial tree and the file start. The latter can be retrieved
// from `FirLightSourceElement`.
val startDelta = this.startOffset - lighterASTNode.startOffset
val endDelta = this.endOffset - lighterASTNode.endOffset
return newNode.toFirLightSourceElement(
treeStructure,
startOffset = startDelta + newNode.startOffset,
endOffset = endDelta + newNode.endOffset
)
}
@@ -6,17 +6,18 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClass
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.getParent
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.isInterface
import org.jetbrains.kotlin.fir.declarations.primaryConstructor
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.FirImplicitAnyTypeRef
import org.jetbrains.kotlin.utils.addToStdlib.lastIsInstanceOrNull
@@ -54,8 +55,9 @@ object FirPrimaryConstructorSuperTypeChecker : FirRegularClassChecker() {
val containingClass = context.containingDeclarations.lastIsInstanceOrNull<FirRegularClass>()
val delegatedConstructorCall = primaryConstructor.delegatedConstructor ?: return
// No need to check implicit call to the constructor of `kotlin.Any`.
if (delegatedConstructorCall.constructedTypeRef is FirImplicitAnyTypeRef) return
val superClass = delegatedConstructorCall.constructedTypeRef.coneType.toRegularClass(context.session) ?: return
val constructedTypeRef = delegatedConstructorCall.constructedTypeRef
if (constructedTypeRef is FirImplicitAnyTypeRef) return
val superClass = constructedTypeRef.coneType.toRegularClass(context.session) ?: return
// Subclassing a singleton should be reported as SINGLETON_IN_SUPERTYPE
if (superClass.classKind.isSingleton) return
if (regularClass.isEffectivelyExpect(containingClass, context) ||
@@ -63,12 +65,11 @@ object FirPrimaryConstructorSuperTypeChecker : FirRegularClassChecker() {
) {
return
}
if (delegatedConstructorCall.source?.elementType != KtNodeTypes.SUPER_TYPE_CALL_ENTRY) {
reporter.reportOn(
delegatedConstructorCall.constructedTypeRef.source?.getParent(KtNodeTypes.SUPER_TYPE_ENTRY),
FirErrors.SUPERTYPE_NOT_INITIALIZED,
context
)
val delegatedCallSource = delegatedConstructorCall.source ?: return
if (delegatedCallSource.kind !is FirFakeSourceElementKind) return
if (superClass.symbol.classId == StandardClassIds.Enum) return
if (delegatedCallSource.elementType != KtNodeTypes.SUPER_TYPE_CALL_ENTRY) {
reporter.reportOn(constructedTypeRef.source, FirErrors.SUPERTYPE_NOT_INITIALIZED, context)
}
}
@@ -2,7 +2,7 @@ open class Foo() {
}
class Barrr() : Foo by Foo() {}
class Barrr() : <!SUPERTYPE_NOT_INITIALIZED!>Foo<!> by Foo() {}
interface T {}
@@ -1,4 +1,4 @@
// JAVAC_EXPECTED_FILE
class TestIface(r : Runnable) : Runnable by r {}
class TestObject(o : Object) : Object by o {}
class TestObject(o : Object) : <!SUPERTYPE_NOT_INITIALIZED!>Object<!> by o {}
@@ -11,4 +11,4 @@ public abstract class A {
// FILE: main.kt
import foo.A
class DelegatedA(val a: A) : A by a
class DelegatedA(val a: A) : <!SUPERTYPE_NOT_INITIALIZED!>A<!> by a
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPropertyAccessor
import org.jetbrains.kotlin.psi.KtPropertyDelegate
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.psi.KtSuperTypeEntry
import org.jetbrains.kotlin.psi.KtTypeParameter
import org.jetbrains.kotlin.psi.KtTypeParameterList
import org.jetbrains.kotlin.psi.KtTypeReference
@@ -296,6 +295,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.SUPERTYPE_NOT_INITIALIZED) { firDiagnostic ->
SupertypeNotInitializedImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR) { firDiagnostic ->
SupertypeInitializedWithoutPrimaryConstructorImpl(
firDiagnostic as FirPsiDiagnostic<*>,
@@ -555,12 +560,6 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.SUPERTYPE_NOT_INITIALIZED) { firDiagnostic ->
SupertypeNotInitializedImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.INLINE_CLASS_NOT_TOP_LEVEL) { firDiagnostic ->
InlineClassNotTopLevelImpl(
firDiagnostic as FirPsiDiagnostic<*>,
@@ -36,7 +36,6 @@ import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPropertyAccessor
import org.jetbrains.kotlin.psi.KtPropertyDelegate
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.psi.KtSuperTypeEntry
import org.jetbrains.kotlin.psi.KtTypeParameter
import org.jetbrains.kotlin.psi.KtTypeParameterList
import org.jetbrains.kotlin.psi.KtTypeReference
@@ -219,6 +218,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = PrimaryConstructorDelegationCallExpected::class
}
abstract class SupertypeNotInitialized : KtFirDiagnostic<KtTypeReference>() {
override val diagnosticClass get() = SupertypeNotInitialized::class
}
abstract class SupertypeInitializedWithoutPrimaryConstructor : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = SupertypeInitializedWithoutPrimaryConstructor::class
}
@@ -404,10 +407,6 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val target: String
}
abstract class SupertypeNotInitialized : KtFirDiagnostic<KtSuperTypeEntry>() {
override val diagnosticClass get() = SupertypeNotInitialized::class
}
abstract class InlineClassNotTopLevel : KtFirDiagnostic<KtDeclaration>() {
override val diagnosticClass get() = InlineClassNotTopLevel::class
}
@@ -38,7 +38,6 @@ import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPropertyAccessor
import org.jetbrains.kotlin.psi.KtPropertyDelegate
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.psi.KtSuperTypeEntry
import org.jetbrains.kotlin.psi.KtTypeParameter
import org.jetbrains.kotlin.psi.KtTypeParameterList
import org.jetbrains.kotlin.psi.KtTypeReference
@@ -343,6 +342,13 @@ internal class PrimaryConstructorDelegationCallExpectedImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class SupertypeNotInitializedImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.SupertypeNotInitialized(), KtAbstractFirDiagnostic<KtTypeReference> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class SupertypeInitializedWithoutPrimaryConstructorImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
@@ -639,13 +645,6 @@ internal class WrongModifierTargetImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class SupertypeNotInitializedImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.SupertypeNotInitialized(), KtAbstractFirDiagnostic<KtSuperTypeEntry> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class InlineClassNotTopLevelImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,