From 7b1052296ef223efb243030b84959c33d6b3e0bb Mon Sep 17 00:00:00 2001 From: Roman Golyshev Date: Thu, 1 Jul 2021 23:42:43 +0300 Subject: [PATCH] Do not try to create a light class for classes in unexpected positions Example of such class declaration would be `10 < class A` expression The expression is uncompilable, but parsable. Unfortunately, the FIR compiler does not save `class A` reference in it (because it is not an expression, and only an expression can be a LHS or RHS of binary expression `10 < ...`) When we try to build light classes, we will try to find/build FIR declaration for this class, but we won't be able to, and this will throw an error Adding this check should fix few `FirKotlinHighlightingPassTestGenerated$Regression` tests --- .../KtLightClassForSourceDeclaration.kt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt index 158f61d50fb..dd5e3932f98 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt @@ -570,6 +570,7 @@ fun KtClassOrObject.shouldNotBeVisibleAsLightClass(): Boolean { if (isLocal) { if (containingFile.virtualFile == null) return true if (hasParseErrorsAround(this) || PsiUtilCore.hasErrorElementChild(this)) return true + if (classDeclaredInUnexpectedPosition(this)) return true } if (isEnumEntryWithoutBody(this)) { @@ -579,6 +580,23 @@ fun KtClassOrObject.shouldNotBeVisibleAsLightClass(): Boolean { return false } +/** + * If class is declared in some strange context (for example, in expression like `10 < class A`), + * we don't want to try to build a light class for it. + * + * The expression itself is incorrect and won't compile, but the parser is able the parse the class nonetheless. + * + * This does not concern objects, since object literals are expressions and can be used almost anywhere. + */ +private fun classDeclaredInUnexpectedPosition(classOrObject: KtClassOrObject): Boolean { + if (classOrObject is KtObjectDeclaration) return false + + val classParent = classOrObject.parent + + return classParent !is KtBlockExpression && + classParent !is KtDeclarationContainer +} + private fun isEnumEntryWithoutBody(classOrObject: KtClassOrObject): Boolean { if (classOrObject !is KtEnumEntry) { return false