FIR checkers: simplify hasPrimaryConstructor by source element check

This commit is contained in:
Mikhail Glukhikh
2020-11-19 15:38:47 +03:00
parent 0838ab7fe7
commit 1e3621a896
6 changed files with 12 additions and 45 deletions
@@ -10,7 +10,7 @@ interface C {
fun baz()
}
interface Inv<K, T>() {
interface <!CONSTRUCTOR_IN_INTERFACE!>Inv<K, T>()<!> {
fun k(): K
fun t(): T
}
@@ -5,22 +5,14 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import com.intellij.lang.LighterASTNode
import com.intellij.openapi.util.Ref
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiErrorElement
import com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.KtNodeTypes.PRIMARY_CONSTRUCTOR
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirLightSourceElement
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.hasPrimaryConstructor
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.psi.KtPrimaryConstructor
object FirConstructorInInterfaceChecker : FirBasicDeclarationChecker() {
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -33,34 +25,6 @@ object FirConstructorInInterfaceChecker : FirBasicDeclarationChecker() {
}
}
private fun FirSourceElement.hasPrimaryConstructor(): Boolean {
val localPsi = psi
val localLightNode = lighterASTNode
if (localPsi != null && localPsi !is PsiErrorElement) {
return localPsi.hasPrimaryConstructor()
} else if (this is FirLightSourceElement) {
return localLightNode.hasPrimaryConstructor(treeStructure)
}
return false
}
private fun PsiElement.hasPrimaryConstructor(): Boolean {
return lastChild !is PsiErrorElement && lastChild is KtPrimaryConstructor
}
private fun LighterASTNode.hasPrimaryConstructor(tree: FlyweightCapableTreeStructure<LighterASTNode>): Boolean {
val children = getChildren(tree)
return children.lastOrNull()?.tokenType == PRIMARY_CONSTRUCTOR
}
private fun LighterASTNode.getChildren(tree: FlyweightCapableTreeStructure<LighterASTNode>): List<LighterASTNode> {
val children = Ref<Array<LighterASTNode?>>()
val count = tree.getChildren(this, children)
return if (count > 0) children.get().filterNotNull() else emptyList()
}
private fun DiagnosticReporter.report(source: FirSourceElement?) {
source?.let { report(FirErrors.CONSTRUCTOR_IN_INTERFACE.on(it)) }
}
@@ -150,6 +150,9 @@ fun FirSourceElement.hasValOrVar(): Boolean =
fun FirSourceElement.hasVar(): Boolean =
treeStructure.findChildByType(lighterASTNode, KtTokens.VAR_KEYWORD) != null
fun FirSourceElement.hasPrimaryConstructor(): Boolean =
treeStructure.primaryConstructor(lighterASTNode) != null
private fun FlyweightCapableTreeStructure<LighterASTNode>.constructorKeyword(node: LighterASTNode): LighterASTNode? =
findChildByType(node, KtTokens.CONSTRUCTOR_KEYWORD)
@@ -21,7 +21,7 @@ interface T1 {}
interface T2<T> {}
interface Test() {
interface <!CONSTRUCTOR_IN_INTERFACE!>Test()<!> {
}
interface Test1 : <!INTERFACE_WITH_SUPERCLASS, SUPERTYPE_INITIALIZED_IN_INTERFACE!>C2<!>() {}
@@ -2,11 +2,11 @@
class C(val a: String) {}
interface T1(val x: String) {}
interface <!CONSTRUCTOR_IN_INTERFACE!>T1(val x: String)<!> {}
interface T2 constructor() {}
interface <!CONSTRUCTOR_IN_INTERFACE!>T2 constructor()<!> {}
interface T3 private constructor(a: Int) {}
interface <!CONSTRUCTOR_IN_INTERFACE!>T3 private constructor(a: Int)<!> {}
interface T4 {
<!CONSTRUCTOR_IN_INTERFACE!>constructor(a: Int)<!> {
@@ -14,5 +14,5 @@ interface T4 {
}
}
interface T5 private () : T4 {}
interface T6 private<!SYNTAX!><!> : T5 {}
interface <!CONSTRUCTOR_IN_INTERFACE!>T5 private ()<!> : T4 {}
interface <!CONSTRUCTOR_IN_INTERFACE!>T6<!> private<!SYNTAX!><!> : T5 {}
@@ -1,6 +1,6 @@
open class bar()
interface Foo() : <!INTERFACE_WITH_SUPERCLASS!>bar<!>(), bar, bar {
interface <!CONSTRUCTOR_IN_INTERFACE!>Foo()<!> : <!INTERFACE_WITH_SUPERCLASS!>bar<!>(), bar, bar {
}
interface Foo2 : <!INTERFACE_WITH_SUPERCLASS!>bar<!>, Foo {