[FIR] Add stack of all FIR elements to CheckerContext
^KT-56472 Fixed
This commit is contained in:
committed by
Space Team
parent
41192b022d
commit
f3fd4b3e01
+1
@@ -35,6 +35,7 @@ abstract class CheckerContext : DiagnosticContext {
|
|||||||
abstract val qualifiedAccessOrAssignmentsOrAnnotationCalls: List<FirStatement>
|
abstract val qualifiedAccessOrAssignmentsOrAnnotationCalls: List<FirStatement>
|
||||||
abstract val getClassCalls: List<FirGetClassCall>
|
abstract val getClassCalls: List<FirGetClassCall>
|
||||||
abstract val annotationContainers: List<FirAnnotationContainer>
|
abstract val annotationContainers: List<FirAnnotationContainer>
|
||||||
|
abstract val containingElements: List<FirElement>
|
||||||
abstract val isContractBody: Boolean
|
abstract val isContractBody: Boolean
|
||||||
|
|
||||||
// Suppress
|
// Suppress
|
||||||
|
|||||||
+4
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers.context
|
package org.jetbrains.kotlin.fir.analysis.checkers.context
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||||
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
||||||
@@ -69,4 +70,7 @@ abstract class CheckerContextForProvider(
|
|||||||
|
|
||||||
abstract fun exitFile(file: FirFile): CheckerContextForProvider
|
abstract fun exitFile(file: FirFile): CheckerContextForProvider
|
||||||
|
|
||||||
|
abstract fun addElement(element: FirElement): CheckerContextForProvider
|
||||||
|
|
||||||
|
abstract fun dropElement()
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-4
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.context
|
|||||||
import kotlinx.collections.immutable.PersistentSet
|
import kotlinx.collections.immutable.PersistentSet
|
||||||
import kotlinx.collections.immutable.persistentSetOf
|
import kotlinx.collections.immutable.persistentSetOf
|
||||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||||
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
||||||
@@ -24,6 +25,7 @@ class MutableCheckerContext private constructor(
|
|||||||
override val qualifiedAccessOrAssignmentsOrAnnotationCalls: MutableList<FirStatement>,
|
override val qualifiedAccessOrAssignmentsOrAnnotationCalls: MutableList<FirStatement>,
|
||||||
override val getClassCalls: MutableList<FirGetClassCall>,
|
override val getClassCalls: MutableList<FirGetClassCall>,
|
||||||
override val annotationContainers: MutableList<FirAnnotationContainer>,
|
override val annotationContainers: MutableList<FirAnnotationContainer>,
|
||||||
|
override val containingElements: MutableList<FirElement>,
|
||||||
override var isContractBody: Boolean,
|
override var isContractBody: Boolean,
|
||||||
override var containingFile: FirFile?,
|
override var containingFile: FirFile?,
|
||||||
sessionHolder: SessionHolder,
|
sessionHolder: SessionHolder,
|
||||||
@@ -39,6 +41,7 @@ class MutableCheckerContext private constructor(
|
|||||||
mutableListOf(),
|
mutableListOf(),
|
||||||
mutableListOf(),
|
mutableListOf(),
|
||||||
mutableListOf(),
|
mutableListOf(),
|
||||||
|
mutableListOf(),
|
||||||
isContractBody = false,
|
isContractBody = false,
|
||||||
containingFile = null,
|
containingFile = null,
|
||||||
sessionHolder,
|
sessionHolder,
|
||||||
@@ -56,6 +59,7 @@ class MutableCheckerContext private constructor(
|
|||||||
qualifiedAccessOrAssignmentsOrAnnotationCalls,
|
qualifiedAccessOrAssignmentsOrAnnotationCalls,
|
||||||
getClassCalls,
|
getClassCalls,
|
||||||
annotationContainers,
|
annotationContainers,
|
||||||
|
containingElements,
|
||||||
isContractBody,
|
isContractBody,
|
||||||
containingFile,
|
containingFile,
|
||||||
sessionHolder,
|
sessionHolder,
|
||||||
@@ -73,7 +77,7 @@ class MutableCheckerContext private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun dropDeclaration() {
|
override fun dropDeclaration() {
|
||||||
containingDeclarations.removeAt(containingDeclarations.size - 1)
|
containingDeclarations.removeLast()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addQualifiedAccessOrAnnotationCall(qualifiedAccessOrAnnotationCall: FirStatement): MutableCheckerContext {
|
override fun addQualifiedAccessOrAnnotationCall(qualifiedAccessOrAnnotationCall: FirStatement): MutableCheckerContext {
|
||||||
@@ -82,7 +86,7 @@ class MutableCheckerContext private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun dropQualifiedAccessOrAnnotationCall() {
|
override fun dropQualifiedAccessOrAnnotationCall() {
|
||||||
qualifiedAccessOrAssignmentsOrAnnotationCalls.removeAt(qualifiedAccessOrAssignmentsOrAnnotationCalls.size - 1)
|
qualifiedAccessOrAssignmentsOrAnnotationCalls.removeLast()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addGetClassCall(getClassCall: FirGetClassCall): MutableCheckerContext {
|
override fun addGetClassCall(getClassCall: FirGetClassCall): MutableCheckerContext {
|
||||||
@@ -91,7 +95,7 @@ class MutableCheckerContext private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun dropGetClassCall() {
|
override fun dropGetClassCall() {
|
||||||
getClassCalls.removeAt(getClassCalls.size - 1)
|
getClassCalls.removeLast()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addAnnotationContainer(annotationContainer: FirAnnotationContainer): CheckerContextForProvider {
|
override fun addAnnotationContainer(annotationContainer: FirAnnotationContainer): CheckerContextForProvider {
|
||||||
@@ -100,7 +104,17 @@ class MutableCheckerContext private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun dropAnnotationContainer() {
|
override fun dropAnnotationContainer() {
|
||||||
annotationContainers.removeAt(annotationContainers.size - 1)
|
annotationContainers.removeLast()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addElement(element: FirElement): CheckerContextForProvider {
|
||||||
|
assert(containingElements.lastOrNull() !== element)
|
||||||
|
containingElements.add(element)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dropElement() {
|
||||||
|
containingElements.removeLast()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addSuppressedDiagnostics(
|
override fun addSuppressedDiagnostics(
|
||||||
@@ -116,6 +130,7 @@ class MutableCheckerContext private constructor(
|
|||||||
qualifiedAccessOrAssignmentsOrAnnotationCalls,
|
qualifiedAccessOrAssignmentsOrAnnotationCalls,
|
||||||
getClassCalls,
|
getClassCalls,
|
||||||
annotationContainers,
|
annotationContainers,
|
||||||
|
containingElements,
|
||||||
isContractBody,
|
isContractBody,
|
||||||
containingFile,
|
containingFile,
|
||||||
sessionHolder,
|
sessionHolder,
|
||||||
|
|||||||
+24
-13
@@ -10,6 +10,7 @@ import kotlinx.collections.immutable.PersistentSet
|
|||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.persistentSetOf
|
import kotlinx.collections.immutable.persistentSetOf
|
||||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||||
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
||||||
@@ -26,6 +27,7 @@ class PersistentCheckerContext private constructor(
|
|||||||
override val qualifiedAccessOrAssignmentsOrAnnotationCalls: PersistentList<FirStatement>,
|
override val qualifiedAccessOrAssignmentsOrAnnotationCalls: PersistentList<FirStatement>,
|
||||||
override val getClassCalls: PersistentList<FirGetClassCall>,
|
override val getClassCalls: PersistentList<FirGetClassCall>,
|
||||||
override val annotationContainers: PersistentList<FirAnnotationContainer>,
|
override val annotationContainers: PersistentList<FirAnnotationContainer>,
|
||||||
|
override val containingElements: PersistentList<FirElement>,
|
||||||
override val isContractBody: Boolean,
|
override val isContractBody: Boolean,
|
||||||
sessionHolder: SessionHolder,
|
sessionHolder: SessionHolder,
|
||||||
returnTypeCalculator: ReturnTypeCalculator,
|
returnTypeCalculator: ReturnTypeCalculator,
|
||||||
@@ -41,6 +43,7 @@ class PersistentCheckerContext private constructor(
|
|||||||
persistentListOf(),
|
persistentListOf(),
|
||||||
persistentListOf(),
|
persistentListOf(),
|
||||||
persistentListOf(),
|
persistentListOf(),
|
||||||
|
persistentListOf(),
|
||||||
isContractBody = false,
|
isContractBody = false,
|
||||||
sessionHolder,
|
sessionHolder,
|
||||||
returnTypeCalculator,
|
returnTypeCalculator,
|
||||||
@@ -57,8 +60,7 @@ class PersistentCheckerContext private constructor(
|
|||||||
override fun addDeclaration(declaration: FirDeclaration): PersistentCheckerContext =
|
override fun addDeclaration(declaration: FirDeclaration): PersistentCheckerContext =
|
||||||
copy(containingDeclarations = containingDeclarations.add(declaration))
|
copy(containingDeclarations = containingDeclarations.add(declaration))
|
||||||
|
|
||||||
override fun dropDeclaration() {
|
override fun dropDeclaration() {}
|
||||||
}
|
|
||||||
|
|
||||||
override fun addQualifiedAccessOrAnnotationCall(qualifiedAccessOrAnnotationCall: FirStatement): PersistentCheckerContext =
|
override fun addQualifiedAccessOrAnnotationCall(qualifiedAccessOrAnnotationCall: FirStatement): PersistentCheckerContext =
|
||||||
copy(
|
copy(
|
||||||
@@ -66,22 +68,22 @@ class PersistentCheckerContext private constructor(
|
|||||||
qualifiedAccessOrAssignmentsOrAnnotationCalls.add(qualifiedAccessOrAnnotationCall)
|
qualifiedAccessOrAssignmentsOrAnnotationCalls.add(qualifiedAccessOrAnnotationCall)
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun dropQualifiedAccessOrAnnotationCall() {
|
override fun dropQualifiedAccessOrAnnotationCall() {}
|
||||||
}
|
|
||||||
|
|
||||||
override fun addGetClassCall(getClassCall: FirGetClassCall): PersistentCheckerContext =
|
override fun addGetClassCall(getClassCall: FirGetClassCall): PersistentCheckerContext =
|
||||||
copy(
|
copy(getClassCalls = getClassCalls.add(getClassCall))
|
||||||
getClassCalls = getClassCalls.add(getClassCall),
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun dropGetClassCall() {
|
override fun dropGetClassCall() {}
|
||||||
}
|
|
||||||
|
|
||||||
override fun addAnnotationContainer(annotationContainer: FirAnnotationContainer): PersistentCheckerContext =
|
override fun addAnnotationContainer(annotationContainer: FirAnnotationContainer): PersistentCheckerContext =
|
||||||
copy(annotationContainers = annotationContainers.add(annotationContainer))
|
copy(annotationContainers = annotationContainers.add(annotationContainer))
|
||||||
|
|
||||||
override fun dropAnnotationContainer() {
|
override fun dropAnnotationContainer() {}
|
||||||
}
|
|
||||||
|
override fun addElement(element: FirElement): PersistentCheckerContext =
|
||||||
|
copy(containingElements = containingElements.add(element))
|
||||||
|
|
||||||
|
override fun dropElement() {}
|
||||||
|
|
||||||
override fun addSuppressedDiagnostics(
|
override fun addSuppressedDiagnostics(
|
||||||
diagnosticNames: Collection<String>,
|
diagnosticNames: Collection<String>,
|
||||||
@@ -103,6 +105,7 @@ class PersistentCheckerContext private constructor(
|
|||||||
qualifiedAccessOrAssignmentsOrAnnotationCalls: PersistentList<FirStatement> = this.qualifiedAccessOrAssignmentsOrAnnotationCalls,
|
qualifiedAccessOrAssignmentsOrAnnotationCalls: PersistentList<FirStatement> = this.qualifiedAccessOrAssignmentsOrAnnotationCalls,
|
||||||
getClassCalls: PersistentList<FirGetClassCall> = this.getClassCalls,
|
getClassCalls: PersistentList<FirGetClassCall> = this.getClassCalls,
|
||||||
annotationContainers: PersistentList<FirAnnotationContainer> = this.annotationContainers,
|
annotationContainers: PersistentList<FirAnnotationContainer> = this.annotationContainers,
|
||||||
|
containingElements: PersistentList<FirElement> = this.containingElements,
|
||||||
containingDeclarations: PersistentList<FirDeclaration> = this.containingDeclarations,
|
containingDeclarations: PersistentList<FirDeclaration> = this.containingDeclarations,
|
||||||
isContractBody: Boolean = this.isContractBody,
|
isContractBody: Boolean = this.isContractBody,
|
||||||
allInfosSuppressed: Boolean = this.allInfosSuppressed,
|
allInfosSuppressed: Boolean = this.allInfosSuppressed,
|
||||||
@@ -112,8 +115,16 @@ class PersistentCheckerContext private constructor(
|
|||||||
containingFile: FirFile? = this.containingFile,
|
containingFile: FirFile? = this.containingFile,
|
||||||
): PersistentCheckerContext {
|
): PersistentCheckerContext {
|
||||||
return PersistentCheckerContext(
|
return PersistentCheckerContext(
|
||||||
implicitReceiverStack, containingDeclarations, qualifiedAccessOrAssignmentsOrAnnotationCalls,
|
implicitReceiverStack,
|
||||||
getClassCalls, annotationContainers, isContractBody, sessionHolder, returnTypeCalculator, suppressedDiagnostics,
|
containingDeclarations,
|
||||||
|
qualifiedAccessOrAssignmentsOrAnnotationCalls,
|
||||||
|
getClassCalls,
|
||||||
|
annotationContainers,
|
||||||
|
containingElements,
|
||||||
|
isContractBody,
|
||||||
|
sessionHolder,
|
||||||
|
returnTypeCalculator,
|
||||||
|
suppressedDiagnostics,
|
||||||
allInfosSuppressed, allWarningsSuppressed, allErrorsSuppressed, containingFile,
|
allInfosSuppressed, allWarningsSuppressed, allErrorsSuppressed, containingFile,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-25
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.collectors
|
package org.jetbrains.kotlin.fir.analysis.collectors
|
||||||
|
|
||||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
|
||||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||||
@@ -35,16 +34,16 @@ abstract class AbstractDiagnosticCollectorVisitor(
|
|||||||
protected abstract fun checkElement(element: FirElement)
|
protected abstract fun checkElement(element: FirElement)
|
||||||
|
|
||||||
override fun visitElement(element: FirElement, data: Nothing?) {
|
override fun visitElement(element: FirElement, data: Nothing?) {
|
||||||
if (element is FirAnnotationContainer) {
|
when (element) {
|
||||||
withAnnotationContainer(element) {
|
is FirAnnotationContainer -> withAnnotationContainer(element) {
|
||||||
|
checkElement(element)
|
||||||
|
visitNestedElements(element)
|
||||||
|
}
|
||||||
|
else -> withElement(element) {
|
||||||
checkElement(element)
|
checkElement(element)
|
||||||
visitNestedElements(element)
|
visitNestedElements(element)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkElement(element)
|
|
||||||
visitNestedElements(element)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitAnnotationContainer(annotationContainer: FirAnnotationContainer, data: Nothing?) {
|
override fun visitAnnotationContainer(annotationContainer: FirAnnotationContainer, data: Nothing?) {
|
||||||
@@ -166,18 +165,18 @@ abstract class AbstractDiagnosticCollectorVisitor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer, data: Nothing?) {
|
override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer, data: Nothing?) {
|
||||||
visitWithDeclaration(anonymousInitializer)
|
withElement(anonymousInitializer) {
|
||||||
|
visitWithDeclaration(anonymousInitializer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitBlock(block: FirBlock, data: Nothing?) {
|
override fun visitBlock(block: FirBlock, data: Nothing?) {
|
||||||
withAnnotationContainer(block) {
|
if (block is FirContractCallBlock) {
|
||||||
if (block is FirContractCallBlock) {
|
insideContractBody {
|
||||||
insideContractBody {
|
|
||||||
visitExpression(block, data)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
visitExpression(block, data)
|
visitExpression(block, data)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
visitExpression(block, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,6 +340,19 @@ abstract class AbstractDiagnosticCollectorVisitor(
|
|||||||
context = existingContext
|
context = existingContext
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@OptIn(PrivateForInline::class)
|
||||||
|
inline fun <T> withElement(element: FirElement, block: () -> T): T {
|
||||||
|
val existingContext = context
|
||||||
|
context = context.addElement(element)
|
||||||
|
return try {
|
||||||
|
whileAnalysing(context.session, element) {
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
existingContext.dropElement()
|
||||||
|
context = existingContext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(PrivateForInline::class)
|
@OptIn(PrivateForInline::class)
|
||||||
inline fun <R> withLabelAndReceiverType(
|
inline fun <R> withLabelAndReceiverType(
|
||||||
@@ -367,19 +379,21 @@ abstract class AbstractDiagnosticCollectorVisitor(
|
|||||||
|
|
||||||
@OptIn(PrivateForInline::class)
|
@OptIn(PrivateForInline::class)
|
||||||
inline fun <R> withAnnotationContainer(annotationContainer: FirAnnotationContainer, block: () -> R): R {
|
inline fun <R> withAnnotationContainer(annotationContainer: FirAnnotationContainer, block: () -> R): R {
|
||||||
val existingContext = context
|
return withElement(annotationContainer) {
|
||||||
addSuppressedDiagnosticsToContext(annotationContainer)
|
val existingContext = context
|
||||||
val notEmptyAnnotations = annotationContainer.annotations.isNotEmpty()
|
addSuppressedDiagnosticsToContext(annotationContainer)
|
||||||
if (notEmptyAnnotations) {
|
val notEmptyAnnotations = annotationContainer.annotations.isNotEmpty()
|
||||||
context = context.addAnnotationContainer(annotationContainer)
|
|
||||||
}
|
|
||||||
return try {
|
|
||||||
block()
|
|
||||||
} finally {
|
|
||||||
if (notEmptyAnnotations) {
|
if (notEmptyAnnotations) {
|
||||||
existingContext.dropAnnotationContainer()
|
context = context.addAnnotationContainer(annotationContainer)
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
block()
|
||||||
|
} finally {
|
||||||
|
if (notEmptyAnnotations) {
|
||||||
|
existingContext.dropAnnotationContainer()
|
||||||
|
}
|
||||||
|
context = existingContext
|
||||||
}
|
}
|
||||||
context = existingContext
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user