[FIR] Introduce CheckerContext for call and declaration checkers
This commit is contained in:
+3
-7
@@ -5,19 +5,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.call
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.ImplicitReceiverStack
|
||||
|
||||
abstract class FirExpressionChecker<in E : FirExpression> {
|
||||
abstract fun check(functionCall: E, reporter: DiagnosticReporter)
|
||||
abstract fun check(functionCall: E, context: CheckerContext, reporter: DiagnosticReporter)
|
||||
}
|
||||
|
||||
typealias FirFunctionCallChecker = FirExpressionChecker<FirFunctionCall>
|
||||
typealias FirQualifiedAccessChecker = FirExpressionChecker<FirQualifiedAccessExpression>
|
||||
|
||||
class FirExpressionCheckerContext(
|
||||
val implicitReceiverStack: ImplicitReceiverStack
|
||||
)
|
||||
typealias FirQualifiedAccessChecker = FirExpressionChecker<FirQualifiedAccessExpression>
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.fir.analysis.checkers.context
|
||||
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.resolve.ImplicitReceiverStack
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
abstract class CheckerContext {
|
||||
abstract val implicitReceiverStack: ImplicitReceiverStack
|
||||
abstract val containingDeclarations: List<FirDeclaration>
|
||||
}
|
||||
|
||||
class PersistentCheckerContext(
|
||||
override val implicitReceiverStack: PersistentImplicitReceiverStack,
|
||||
override val containingDeclarations: PersistentList<FirDeclaration>
|
||||
) : CheckerContext() {
|
||||
constructor() : this(
|
||||
PersistentImplicitReceiverStack(),
|
||||
persistentListOf()
|
||||
)
|
||||
|
||||
fun addImplicitReceiver(name: Name?, value: ImplicitReceiverValue<*>): PersistentCheckerContext {
|
||||
return PersistentCheckerContext(
|
||||
implicitReceiverStack.add(name, value),
|
||||
containingDeclarations
|
||||
)
|
||||
}
|
||||
|
||||
fun addDeclaration(declaration: FirDeclaration): PersistentCheckerContext {
|
||||
return PersistentCheckerContext(
|
||||
implicitReceiverStack,
|
||||
containingDeclarations.add(declaration)
|
||||
)
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.fir.analysis.checkers.context
|
||||
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.PersistentMap
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.persistentMapOf
|
||||
import org.jetbrains.kotlin.fir.resolve.ImplicitReceiverStack
|
||||
import org.jetbrains.kotlin.fir.resolve.PersistentSetMultimap
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class PersistentImplicitReceiverStack private constructor(
|
||||
private val stack: PersistentList<ImplicitReceiverValue<*>>,
|
||||
// This multi-map holds indexes of the stack ^
|
||||
private val indexesPerLabel: PersistentSetMultimap<Name, Int>,
|
||||
private val indexesPerSymbol: PersistentMap<FirBasedSymbol<*>, Int>
|
||||
) : ImplicitReceiverStack(), Iterable<ImplicitReceiverValue<*>> {
|
||||
val size: Int get() = stack.size
|
||||
|
||||
constructor() : this(
|
||||
persistentListOf(),
|
||||
PersistentSetMultimap(),
|
||||
persistentMapOf()
|
||||
)
|
||||
|
||||
fun add(name: Name?, value: ImplicitReceiverValue<*>): PersistentImplicitReceiverStack {
|
||||
val stack = stack.add(value)
|
||||
val index = stack.size - 1
|
||||
val indexesPerLabel = name?.let { indexesPerLabel.put(it, index) } ?: indexesPerLabel
|
||||
val indexesPerSymbol = indexesPerSymbol.put(value.boundSymbol, index)
|
||||
return PersistentImplicitReceiverStack(
|
||||
stack,
|
||||
indexesPerLabel,
|
||||
indexesPerSymbol
|
||||
)
|
||||
}
|
||||
|
||||
override operator fun get(name: String?): ImplicitReceiverValue<*>? {
|
||||
if (name == null) return stack.lastOrNull()
|
||||
return indexesPerLabel[Name.identifier(name)].lastOrNull()?.let { stack[it] }
|
||||
}
|
||||
|
||||
override fun lastDispatchReceiver(): ImplicitDispatchReceiverValue? {
|
||||
return stack.filterIsInstance<ImplicitDispatchReceiverValue>().lastOrNull()
|
||||
}
|
||||
|
||||
override fun receiversAsReversed(): List<ImplicitReceiverValue<*>> = stack.asReversed()
|
||||
|
||||
override operator fun iterator(): Iterator<ImplicitReceiverValue<*>> {
|
||||
return stack.iterator()
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -5,9 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
|
||||
abstract class FirDeclarationChecker<in D : FirDeclaration> {
|
||||
abstract fun check(declaration: D, reporter: DiagnosticReporter)
|
||||
abstract fun check(declaration: D, context: CheckerContext, reporter: DiagnosticReporter)
|
||||
}
|
||||
+2
-1
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
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.onSource
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
@@ -14,7 +15,7 @@ import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.isInfix
|
||||
|
||||
object FirInfixFunctionDeclarationChecker : FirDeclarationChecker<FirMemberDeclaration>() {
|
||||
override fun check(declaration: FirMemberDeclaration, reporter: DiagnosticReporter) {
|
||||
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (declaration is FirSimpleFunction && declaration.isInfix) {
|
||||
if (declaration.valueParameters.size != 1 || declaration.receiverTypeRef == null) {
|
||||
reporter.report(declaration.source)
|
||||
|
||||
+115
-3
@@ -6,16 +6,30 @@
|
||||
package org.jetbrains.kotlin.fir.analysis.collectors
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.PersistentCheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.components.AbstractDiagnosticCollectorComponent
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.components.DeclarationCheckersDiagnosticComponent
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.components.ErrorNodeDiagnosticCollectorComponent
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.components.ExpressionCheckersDiagnosticComponent
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.SessionHolder
|
||||
import org.jetbrains.kotlin.fir.resolve.collectImplicitReceivers
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
abstract class AbstractDiagnosticCollector {
|
||||
abstract class AbstractDiagnosticCollector(
|
||||
override val session: FirSession,
|
||||
override val scopeSession: ScopeSession = ScopeSession()
|
||||
) : SessionHolder {
|
||||
fun collectDiagnostics(firFile: FirFile): Iterable<ConeDiagnostic> {
|
||||
if (!componentsInitialized) {
|
||||
throw IllegalStateException("Components are not initialized")
|
||||
@@ -33,6 +47,8 @@ abstract class AbstractDiagnosticCollector {
|
||||
private var componentsInitialized = false
|
||||
private val visitor = Visitor()
|
||||
|
||||
private var context = PersistentCheckerContext()
|
||||
|
||||
fun initializeComponents(vararg components: AbstractDiagnosticCollectorComponent) {
|
||||
if (componentsInitialized) {
|
||||
throw IllegalStateException()
|
||||
@@ -44,7 +60,7 @@ abstract class AbstractDiagnosticCollector {
|
||||
private inner class Visitor : FirVisitorVoid() {
|
||||
private fun <T : FirElement> T.runComponents() {
|
||||
components.forEach {
|
||||
this.accept(it)
|
||||
this.accept(it, context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +68,102 @@ abstract class AbstractDiagnosticCollector {
|
||||
element.runComponents()
|
||||
element.acceptChildren(this)
|
||||
}
|
||||
|
||||
override fun visitRegularClass(regularClass: FirRegularClass) {
|
||||
val typeRef = buildResolvedTypeRef {
|
||||
type = regularClass.defaultType()
|
||||
}
|
||||
visitWithDeclarationAndReceiver(regularClass, regularClass.name, typeRef)
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) {
|
||||
visitWithDeclarationAndReceiver(simpleFunction, simpleFunction.name, simpleFunction.receiverTypeRef)
|
||||
}
|
||||
|
||||
override fun visitConstructor(constructor: FirConstructor) {
|
||||
visitWithDeclaration(constructor)
|
||||
}
|
||||
|
||||
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction) {
|
||||
val labelName = anonymousFunction.label?.name?.let { Name.identifier(it) }
|
||||
visitWithDeclarationAndReceiver(
|
||||
anonymousFunction,
|
||||
labelName,
|
||||
anonymousFunction.receiverTypeRef
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitProperty(property: FirProperty) {
|
||||
visitWithDeclaration(property)
|
||||
}
|
||||
|
||||
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor) {
|
||||
val property = context.containingDeclarations.last() as FirProperty
|
||||
visitWithDeclarationAndReceiver(propertyAccessor, property.name, property.receiverTypeRef)
|
||||
}
|
||||
|
||||
override fun visitValueParameter(valueParameter: FirValueParameter) {
|
||||
visitWithDeclaration(valueParameter)
|
||||
}
|
||||
|
||||
override fun visitEnumEntry(enumEntry: FirEnumEntry) {
|
||||
visitWithDeclaration(enumEntry)
|
||||
}
|
||||
|
||||
override fun visitFile(file: FirFile) {
|
||||
visitWithDeclaration(file)
|
||||
}
|
||||
|
||||
private fun visitWithDeclaration(declaration: FirDeclaration) {
|
||||
declaration.runComponents()
|
||||
withDeclaration(declaration) {
|
||||
declaration.acceptChildren(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun visitWithDeclarationAndReceiver(declaration: FirDeclaration, labelName: Name?, receiverTypeRef: FirTypeRef?) {
|
||||
declaration.runComponents()
|
||||
withDeclaration(declaration) {
|
||||
withLabelAndReceiverType(
|
||||
labelName,
|
||||
declaration,
|
||||
receiverTypeRef?.coneTypeSafe()
|
||||
) {
|
||||
declaration.acceptChildren(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <R> withDeclaration(declaration: FirDeclaration, block: () -> R): R {
|
||||
val existingContext = context
|
||||
context = context.addDeclaration(declaration)
|
||||
try {
|
||||
return block()
|
||||
} finally {
|
||||
context = existingContext
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <R> withLabelAndReceiverType(
|
||||
labelName: Name?,
|
||||
owner: FirDeclaration,
|
||||
type: ConeKotlinType?,
|
||||
block: () -> R
|
||||
): R {
|
||||
val (implicitReceiverValue, implicitCompanionValues) = collectImplicitReceivers(type, owner)
|
||||
val existingContext = context
|
||||
implicitCompanionValues.forEach { value ->
|
||||
context = context.addImplicitReceiver(null, value)
|
||||
}
|
||||
implicitReceiverValue?.let {
|
||||
context = context.addImplicitReceiver(labelName, it)
|
||||
}
|
||||
try {
|
||||
return block()
|
||||
} finally {
|
||||
context = existingContext
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -5,17 +5,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.collectors
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
|
||||
object FirDiagnosticsCollector {
|
||||
fun create(): AbstractDiagnosticCollector {
|
||||
val collector = SimpleDiagnosticsCollector()
|
||||
fun create(session: FirSession): AbstractDiagnosticCollector {
|
||||
val collector = SimpleDiagnosticsCollector(session)
|
||||
collector.registerAllComponents()
|
||||
return collector
|
||||
}
|
||||
|
||||
// Use in CLI compiler
|
||||
@Suppress("unused")
|
||||
fun createParallel(): AbstractDiagnosticCollector {
|
||||
val collector = ParallelDiagnosticsCollector(4)
|
||||
fun createParallel(session: FirSession): AbstractDiagnosticCollector {
|
||||
val collector = ParallelDiagnosticsCollector(session, numberOfThreads = 4)
|
||||
collector.registerAllComponents()
|
||||
return collector
|
||||
}
|
||||
|
||||
+2
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.collectors
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.SimpleDiagnosticReporter
|
||||
@@ -13,7 +14,7 @@ import java.util.concurrent.Executors
|
||||
import java.util.concurrent.Future
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
class ParallelDiagnosticsCollector(private val numberOfThreads: Int) : AbstractDiagnosticCollector() {
|
||||
class ParallelDiagnosticsCollector(session: FirSession, private val numberOfThreads: Int) : AbstractDiagnosticCollector(session) {
|
||||
init {
|
||||
require(numberOfThreads >= 1) {
|
||||
"Number of threads should be at least 1"
|
||||
|
||||
+2
-1
@@ -5,11 +5,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.collectors
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.SimpleDiagnosticReporter
|
||||
|
||||
class SimpleDiagnosticsCollector : AbstractDiagnosticCollector() {
|
||||
class SimpleDiagnosticsCollector(session: FirSession) : AbstractDiagnosticCollector(session) {
|
||||
private var reporter = SimpleDiagnosticReporter()
|
||||
|
||||
override fun initializeCollector() {
|
||||
|
||||
+4
-3
@@ -6,12 +6,13 @@
|
||||
package org.jetbrains.kotlin.fir.analysis.collectors.components
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
|
||||
abstract class AbstractDiagnosticCollectorComponent(private val collector: AbstractDiagnosticCollector) : FirVisitorVoid() {
|
||||
override fun visitElement(element: FirElement) {}
|
||||
abstract class AbstractDiagnosticCollectorComponent(private val collector: AbstractDiagnosticCollector) : FirVisitor<Unit, CheckerContext>() {
|
||||
override fun visitElement(element: FirElement, data: CheckerContext) {}
|
||||
|
||||
protected fun runCheck(block: (DiagnosticReporter) -> Unit) {
|
||||
collector.runCheck(block)
|
||||
|
||||
+21
-20
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.collectors.components
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||
@@ -12,45 +13,45 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
|
||||
class DeclarationCheckersDiagnosticComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
|
||||
override fun visitProperty(property: FirProperty) {
|
||||
runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(property, it) }
|
||||
override fun visitProperty(property: FirProperty, data: CheckerContext) {
|
||||
runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(property, data, it) }
|
||||
}
|
||||
|
||||
override fun visitRegularClass(regularClass: FirRegularClass) {
|
||||
runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(regularClass, it) }
|
||||
override fun visitRegularClass(regularClass: FirRegularClass, data: CheckerContext) {
|
||||
runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(regularClass, data, it) }
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) {
|
||||
runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(simpleFunction, it) }
|
||||
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: CheckerContext) {
|
||||
runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(simpleFunction, data, it) }
|
||||
}
|
||||
|
||||
override fun visitTypeAlias(typeAlias: FirTypeAlias) {
|
||||
runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(typeAlias, it) }
|
||||
override fun visitTypeAlias(typeAlias: FirTypeAlias, data: CheckerContext) {
|
||||
runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(typeAlias, data, it) }
|
||||
}
|
||||
|
||||
override fun visitConstructor(constructor: FirConstructor) {
|
||||
runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(constructor, it) }
|
||||
override fun visitConstructor(constructor: FirConstructor, data: CheckerContext) {
|
||||
runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(constructor, data, it) }
|
||||
}
|
||||
|
||||
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction) {
|
||||
runCheck { DeclarationCheckers.DECLARATIONS.check(anonymousFunction, it) }
|
||||
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: CheckerContext) {
|
||||
runCheck { DeclarationCheckers.DECLARATIONS.check(anonymousFunction, data, it) }
|
||||
}
|
||||
|
||||
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor) {
|
||||
runCheck { DeclarationCheckers.DECLARATIONS.check(propertyAccessor, it) }
|
||||
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: CheckerContext) {
|
||||
runCheck { DeclarationCheckers.DECLARATIONS.check(propertyAccessor, data, it) }
|
||||
}
|
||||
|
||||
override fun visitValueParameter(valueParameter: FirValueParameter) {
|
||||
runCheck { DeclarationCheckers.DECLARATIONS.check(valueParameter, it) }
|
||||
override fun visitValueParameter(valueParameter: FirValueParameter, data: CheckerContext) {
|
||||
runCheck { DeclarationCheckers.DECLARATIONS.check(valueParameter, data, it) }
|
||||
}
|
||||
|
||||
override fun visitEnumEntry(enumEntry: FirEnumEntry) {
|
||||
runCheck { DeclarationCheckers.DECLARATIONS.check(enumEntry, it) }
|
||||
override fun visitEnumEntry(enumEntry: FirEnumEntry, data: CheckerContext) {
|
||||
runCheck { DeclarationCheckers.DECLARATIONS.check(enumEntry, data, it) }
|
||||
}
|
||||
|
||||
private fun <D : FirDeclaration> List<FirDeclarationChecker<D>>.check(declaration: D, reporter: DiagnosticReporter) {
|
||||
private fun <D : FirDeclaration> List<FirDeclarationChecker<D>>.check(declaration: D, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
for (checker in this) {
|
||||
checker.check(declaration, reporter)
|
||||
checker.check(declaration, context, reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-6
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
@@ -16,8 +17,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.onSource
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirStubDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirStubDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirErrorLoop
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
@@ -25,27 +26,27 @@ import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
|
||||
|
||||
class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
|
||||
override fun visitErrorLoop(errorLoop: FirErrorLoop) {
|
||||
override fun visitErrorLoop(errorLoop: FirErrorLoop, data: CheckerContext) {
|
||||
val source = errorLoop.source ?: return
|
||||
runCheck { reportFirDiagnostic(errorLoop.diagnostic, source, it) }
|
||||
}
|
||||
|
||||
override fun visitErrorTypeRef(errorTypeRef: FirErrorTypeRef) {
|
||||
override fun visitErrorTypeRef(errorTypeRef: FirErrorTypeRef, data: CheckerContext) {
|
||||
val source = errorTypeRef.source ?: return
|
||||
runCheck { reportFirDiagnostic(errorTypeRef.diagnostic, source, it) }
|
||||
}
|
||||
|
||||
override fun visitErrorNamedReference(errorNamedReference: FirErrorNamedReference) {
|
||||
override fun visitErrorNamedReference(errorNamedReference: FirErrorNamedReference, data: CheckerContext) {
|
||||
val source = errorNamedReference.source ?: return
|
||||
runCheck { reportFirDiagnostic(errorNamedReference.diagnostic, source, it) }
|
||||
}
|
||||
|
||||
override fun visitErrorExpression(errorExpression: FirErrorExpression) {
|
||||
override fun visitErrorExpression(errorExpression: FirErrorExpression, data: CheckerContext) {
|
||||
val source = errorExpression.source ?: return
|
||||
runCheck { reportFirDiagnostic(errorExpression.diagnostic, source, it) }
|
||||
}
|
||||
|
||||
override fun visitErrorFunction(errorFunction: FirErrorFunction) {
|
||||
override fun visitErrorFunction(errorFunction: FirErrorFunction, data: CheckerContext) {
|
||||
val source = errorFunction.source ?: return
|
||||
runCheck { reportFirDiagnostic(errorFunction.diagnostic, source, it) }
|
||||
}
|
||||
|
||||
+35
-34
@@ -7,78 +7,79 @@ package org.jetbrains.kotlin.fir.analysis.collectors.components
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.call.CallCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.call.FirExpressionChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
|
||||
class ExpressionCheckersDiagnosticComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
|
||||
override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(typeOperatorCall, it) }
|
||||
override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: CheckerContext) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(typeOperatorCall, data, it) }
|
||||
}
|
||||
|
||||
override fun <T> visitConstExpression(constExpression: FirConstExpression<T>) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(constExpression, it) }
|
||||
override fun <T> visitConstExpression(constExpression: FirConstExpression<T>, data: CheckerContext) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(constExpression, data, it) }
|
||||
}
|
||||
|
||||
override fun visitAnnotationCall(annotationCall: FirAnnotationCall) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(annotationCall, it) }
|
||||
override fun visitAnnotationCall(annotationCall: FirAnnotationCall, data: CheckerContext) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(annotationCall, data, it) }
|
||||
}
|
||||
|
||||
override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression) {
|
||||
runCheck { CallCheckers.QUALIFIED_ACCESS.check(qualifiedAccessExpression, it) }
|
||||
override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: CheckerContext) {
|
||||
runCheck { CallCheckers.QUALIFIED_ACCESS.check(qualifiedAccessExpression, data, it) }
|
||||
}
|
||||
|
||||
override fun visitFunctionCall(functionCall: FirFunctionCall) {
|
||||
runCheck { CallCheckers.FUNCTION_CALLS.check(functionCall, it) }
|
||||
override fun visitFunctionCall(functionCall: FirFunctionCall, data: CheckerContext) {
|
||||
runCheck { CallCheckers.FUNCTION_CALLS.check(functionCall, data, it) }
|
||||
}
|
||||
|
||||
override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess) {
|
||||
runCheck { CallCheckers.QUALIFIED_ACCESS.check(callableReferenceAccess, it) }
|
||||
override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: CheckerContext) {
|
||||
runCheck { CallCheckers.QUALIFIED_ACCESS.check(callableReferenceAccess, data, it) }
|
||||
}
|
||||
|
||||
override fun visitThisReceiverExpression(thisReceiverExpression: FirThisReceiverExpression) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(thisReceiverExpression, it) }
|
||||
override fun visitThisReceiverExpression(thisReceiverExpression: FirThisReceiverExpression, data: CheckerContext) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(thisReceiverExpression, data, it) }
|
||||
}
|
||||
|
||||
override fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(resolvedQualifier, it) }
|
||||
override fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier, data: CheckerContext) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(resolvedQualifier, data, it) }
|
||||
}
|
||||
|
||||
override fun visitWhenExpression(whenExpression: FirWhenExpression) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(whenExpression, it) }
|
||||
override fun visitWhenExpression(whenExpression: FirWhenExpression, data: CheckerContext) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(whenExpression, data, it) }
|
||||
}
|
||||
|
||||
override fun visitBinaryLogicExpression(binaryLogicExpression: FirBinaryLogicExpression) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(binaryLogicExpression, it) }
|
||||
override fun visitBinaryLogicExpression(binaryLogicExpression: FirBinaryLogicExpression, data: CheckerContext) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(binaryLogicExpression, data, it) }
|
||||
}
|
||||
|
||||
override fun visitArrayOfCall(arrayOfCall: FirArrayOfCall) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(arrayOfCall, it) }
|
||||
override fun visitArrayOfCall(arrayOfCall: FirArrayOfCall, data: CheckerContext) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(arrayOfCall, data, it) }
|
||||
}
|
||||
|
||||
override fun visitStringConcatenationCall(stringConcatenationCall: FirStringConcatenationCall) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(stringConcatenationCall, it) }
|
||||
override fun visitStringConcatenationCall(stringConcatenationCall: FirStringConcatenationCall, data: CheckerContext) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(stringConcatenationCall, data, it) }
|
||||
}
|
||||
|
||||
override fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(checkNotNullCall, it) }
|
||||
override fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: CheckerContext) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(checkNotNullCall, data, it) }
|
||||
}
|
||||
|
||||
override fun visitTryExpression(tryExpression: FirTryExpression) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(tryExpression, it) }
|
||||
override fun visitTryExpression(tryExpression: FirTryExpression, data: CheckerContext) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(tryExpression, data, it) }
|
||||
}
|
||||
|
||||
override fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(classReferenceExpression, it) }
|
||||
override fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression, data: CheckerContext) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(classReferenceExpression, data, it) }
|
||||
}
|
||||
|
||||
override fun visitGetClassCall(getClassCall: FirGetClassCall) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(getClassCall, it) }
|
||||
override fun visitGetClassCall(getClassCall: FirGetClassCall, data: CheckerContext) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(getClassCall, data, it) }
|
||||
}
|
||||
|
||||
private fun <E : FirExpression> List<FirExpressionChecker<E>>.check(expression: E, reporter: DiagnosticReporter) {
|
||||
private fun <E : FirExpression> List<FirExpressionChecker<E>>.check(expression: E, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
for (checker in this) {
|
||||
checker.check(expression, reporter)
|
||||
checker.check(expression, context, reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
+61
-16
@@ -9,11 +9,8 @@ import kotlinx.collections.immutable.PersistentList
|
||||
import org.jetbrains.kotlin.fir.FirCallResolver
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSymbolOwner
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionStageRunner
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.FirDataFlowAnalyzer
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.FirCallCompleter
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.InferenceComponents
|
||||
@@ -22,19 +19,13 @@ import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
|
||||
typealias FirLocalScopes = PersistentList<FirLocalScope>
|
||||
|
||||
class FirLocalContext(
|
||||
val localScopes: FirLocalScopes,
|
||||
val implicitReceiverStack: MutableImplicitReceiverStack
|
||||
)
|
||||
|
||||
typealias LocalContextForAnonymousFunctions = Map<FirAnonymousFunctionSymbol, FirLocalContext>
|
||||
|
||||
interface SessionHolder {
|
||||
val session: FirSession
|
||||
val scopeSession: ScopeSession
|
||||
}
|
||||
|
||||
interface BodyResolveComponents : SessionHolder {
|
||||
@@ -49,7 +40,6 @@ interface BodyResolveComponents : SessionHolder {
|
||||
val container: FirDeclaration
|
||||
val inferenceComponents: InferenceComponents
|
||||
val resolutionStageRunner: ResolutionStageRunner
|
||||
val scopeSession: ScopeSession
|
||||
val samResolver: FirSamResolver
|
||||
val callResolver: FirCallResolver
|
||||
val callCompleter: FirCallCompleter
|
||||
@@ -64,4 +54,59 @@ interface BodyResolveComponents : SessionHolder {
|
||||
|
||||
fun saveContextForAnonymousFunction(anonymousFunction: FirAnonymousFunction)
|
||||
fun dropContextForAnonymousFunction(anonymousFunction: FirAnonymousFunction)
|
||||
}
|
||||
}
|
||||
|
||||
typealias FirLocalScopes = PersistentList<FirLocalScope>
|
||||
|
||||
class FirLocalContext(
|
||||
val localScopes: FirLocalScopes,
|
||||
val implicitReceiverStack: MutableImplicitReceiverStack
|
||||
)
|
||||
|
||||
typealias LocalContextForAnonymousFunctions = Map<FirAnonymousFunctionSymbol, FirLocalContext>
|
||||
|
||||
// --------------------------------------- Utils ---------------------------------------
|
||||
|
||||
data class ImplicitReceivers(
|
||||
val implicitReceiverValue: ImplicitReceiverValue<*>?,
|
||||
val implicitCompanionValues: List<ImplicitReceiverValue<*>>
|
||||
)
|
||||
|
||||
fun SessionHolder.collectImplicitReceivers(
|
||||
type: ConeKotlinType?,
|
||||
owner: FirDeclaration
|
||||
): ImplicitReceivers {
|
||||
if (type == null) return ImplicitReceivers(null, emptyList())
|
||||
|
||||
val implicitCompanionValues = mutableListOf<ImplicitReceiverValue<*>>()
|
||||
val implicitReceiverValue = when (owner) {
|
||||
is FirClass<*> -> {
|
||||
// Questionable: performance
|
||||
(owner as? FirRegularClass)?.companionObject?.let { companion ->
|
||||
implicitCompanionValues += ImplicitDispatchReceiverValue(
|
||||
companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION
|
||||
)
|
||||
}
|
||||
lookupSuperTypes(owner, lookupInterfaces = false, deep = true, useSiteSession = session).mapNotNull {
|
||||
val superClass = (it as? ConeClassLikeType)?.lookupTag?.toSymbol(session)?.fir as? FirRegularClass
|
||||
superClass?.companionObject?.let { companion ->
|
||||
implicitCompanionValues += ImplicitDispatchReceiverValue(
|
||||
companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION_FROM_SUPERTYPE
|
||||
)
|
||||
}
|
||||
}
|
||||
// ---
|
||||
ImplicitDispatchReceiverValue(owner.symbol, type, session, scopeSession)
|
||||
}
|
||||
is FirFunction<*> -> {
|
||||
ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession)
|
||||
}
|
||||
is FirVariable<*> -> {
|
||||
ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession)
|
||||
}
|
||||
else -> {
|
||||
throw IllegalArgumentException("Incorrect label & receiver owner: ${owner.javaClass}")
|
||||
}
|
||||
}
|
||||
return ImplicitReceivers(implicitReceiverValue, implicitCompanionValues.asReversed())
|
||||
}
|
||||
+7
-41
@@ -19,7 +19,7 @@ import org.jetbrains.kotlin.fir.expressions.builder.buildReturnExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildUnitExpression
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.FirDelegatedPropertyInferenceSession
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.extractLambdaInfoFromFunctionalType
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
@@ -621,53 +621,19 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
|
||||
type: ConeKotlinType?,
|
||||
block: () -> T
|
||||
): T {
|
||||
val implicitCompanionValues: List<ImplicitReceiverValue<*>>
|
||||
if (type != null) {
|
||||
implicitCompanionValues = mutableListOf()
|
||||
val implicitReceiverValue = when (owner) {
|
||||
is FirClass<*> -> {
|
||||
// Questionable: performance
|
||||
(owner as? FirRegularClass)?.companionObject?.let { companion ->
|
||||
implicitCompanionValues += ImplicitDispatchReceiverValue(
|
||||
companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION
|
||||
)
|
||||
}
|
||||
lookupSuperTypes(owner, lookupInterfaces = false, deep = true, useSiteSession = session).mapNotNull {
|
||||
val superClass = (it as? ConeClassLikeType)?.lookupTag?.toSymbol(session)?.fir as? FirRegularClass
|
||||
superClass?.companionObject?.let { companion ->
|
||||
implicitCompanionValues += ImplicitDispatchReceiverValue(
|
||||
companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION_FROM_SUPERTYPE
|
||||
)
|
||||
}
|
||||
}
|
||||
// ---
|
||||
ImplicitDispatchReceiverValue(owner.symbol, type, session, scopeSession)
|
||||
}
|
||||
is FirFunction<*> -> {
|
||||
ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession)
|
||||
}
|
||||
is FirVariable<*> -> {
|
||||
ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession)
|
||||
}
|
||||
else -> {
|
||||
throw IllegalArgumentException("Incorrect label & receiver owner: ${owner.javaClass}")
|
||||
}
|
||||
}
|
||||
for (implicitCompanionValue in implicitCompanionValues.asReversed()) {
|
||||
implicitReceiverStack.add(null, implicitCompanionValue)
|
||||
}
|
||||
implicitReceiverStack.add(labelName, implicitReceiverValue)
|
||||
} else {
|
||||
implicitCompanionValues = emptyList()
|
||||
val (implicitReceiverValue, implicitCompanionValues) = components.collectImplicitReceivers(type, owner)
|
||||
implicitCompanionValues.forEach { value ->
|
||||
implicitReceiverStack.add(null, value)
|
||||
}
|
||||
implicitReceiverValue?.let { implicitReceiverStack.add(labelName, it) }
|
||||
|
||||
try {
|
||||
return block()
|
||||
} finally {
|
||||
if (type != null) {
|
||||
implicitReceiverStack.pop(labelName)
|
||||
for (implicitCompanionValue in implicitCompanionValues) {
|
||||
for (i in implicitCompanionValues.indices)
|
||||
implicitReceiverStack.pop(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,11 +78,13 @@ abstract class AbstractFirDiagnosticsTest : AbstractFirBaseDiagnosticsTest() {
|
||||
}
|
||||
|
||||
protected fun checkDiagnostics(file: File, testFiles: List<TestFile>, firFiles: List<FirFile>) {
|
||||
val collector = createCollector()
|
||||
val collectors = mutableMapOf<FirSession, AbstractDiagnosticCollector>()
|
||||
val actualText = StringBuilder()
|
||||
for (testFile in testFiles) {
|
||||
val firFile = firFiles.firstOrNull { it.psi == testFile.ktFile }
|
||||
if (firFile != null) {
|
||||
val session = firFile.session
|
||||
val collector = collectors.computeIfAbsent(session) { createCollector(session) }
|
||||
val coneDiagnostics = collector.collectDiagnostics(firFile)
|
||||
testFile.getActualText(coneDiagnostics, actualText)
|
||||
} else {
|
||||
@@ -92,8 +94,8 @@ abstract class AbstractFirDiagnosticsTest : AbstractFirBaseDiagnosticsTest() {
|
||||
KotlinTestUtils.assertEqualsToFile(file, actualText.toString())
|
||||
}
|
||||
|
||||
protected fun createCollector(): AbstractDiagnosticCollector {
|
||||
return FirDiagnosticsCollector.create()
|
||||
protected fun createCollector(session: FirSession): AbstractDiagnosticCollector {
|
||||
return FirDiagnosticsCollector.create(session)
|
||||
}
|
||||
|
||||
private fun checkCfg(testDataFile: File, firFiles: List<FirFile>) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.fir
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.registerAllComponents
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.ConeDiagnostic
|
||||
@@ -12,7 +13,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
|
||||
class FirIdeDiagnosticsCollector(private val resolveState: FirModuleResolveState) : AbstractDiagnosticCollector() {
|
||||
class FirIdeDiagnosticsCollector(session: FirSession, private val resolveState: FirModuleResolveState) : AbstractDiagnosticCollector(session) {
|
||||
|
||||
init {
|
||||
registerAllComponents()
|
||||
|
||||
@@ -157,7 +157,7 @@ fun KtFile.getOrBuildFirWithDiagnostics(state: FirModuleResolveState): FirFile {
|
||||
ProgressIndicatorProvider.checkCanceled() // ???
|
||||
if (state.hasDiagnosticsForFile(this)) return firFile
|
||||
|
||||
FirIdeDiagnosticsCollector(state).collectDiagnostics(firFile)
|
||||
FirIdeDiagnosticsCollector(firFile.session, state).collectDiagnostics(firFile)
|
||||
state.setDiagnosticsForFile(this, firFile)
|
||||
return firFile
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user