K2 scripting: fix containing decl for last script expression

Generally the wrapping anonymous initializer can be used as a
"containing declaration" for some elements, but since the initialiser
for the last script expression could be dropped (the expression could
be converted to the result property), this may lead to the surprises,
e.g. as described in KT-65984
This fix marks the last initialiser as local, preventing it from being
referenced as "containing declaration".

#KT-65984
This commit is contained in:
Ilya Chernikov
2024-02-19 15:24:08 +01:00
committed by Space Team
parent 0c5b700523
commit 9ea775cbed
13 changed files with 481 additions and 7 deletions
@@ -31976,6 +31976,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/script/SimpleScript.kts");
}
@Test
@TestMetadata("SuppressAnnoInLastExpression.kts")
public void testSuppressAnnoInLastExpression() {
runTest("compiler/testData/diagnostics/tests/script/SuppressAnnoInLastExpression.kts");
}
@Test
@TestMetadata("topLevelInlineFun.kts")
public void testTopLevelInlineFun() {
@@ -1305,6 +1305,9 @@ open class PsiRawFirBuilder(
// the last one need to be analyzed in script configurator to decide on result property
// therefore no lazy conversion in this case
allowLazyBody = !isLast,
// the last anonymous initializer could be converted to a property and its symbol will be dropped
// therefore we should not rely on it as a containing declaration symbol, and use the parent one instead
isLocal = isLast,
)
declarations.add(initializer)
@@ -2212,12 +2215,21 @@ open class PsiRawFirBuilder(
return buildAnonymousInitializer(initializer, containingDeclarationSymbol = null)
}
/**
* Builds [FirAnonymousInitializer] from [KtAnonymousInitializer]
*
* @param initializer Source [KtAnonymousInitializer]
* @param containingDeclarationSymbol containing declaration symbol, if any
* @param allowLazyBody if `true`, [FirLazyBlock] is used in the IDE mode
* @param isLocal if `true`, the initializer is not used as a containing declaration for the contents of the initializer
*/
protected fun buildAnonymousInitializer(
initializer: KtAnonymousInitializer,
containingDeclarationSymbol: FirBasedSymbol<*>?,
allowLazyBody: Boolean = true,
isLocal: Boolean = false,
) = buildAnonymousInitializer {
withContainerSymbol(symbol) {
withContainerSymbol(symbol, isLocal) {
source = initializer.toFirSourceElement()
moduleData = baseModuleData
origin = FirDeclarationOrigin.Source
@@ -1,23 +1,23 @@
@DestrAnno(<strcat>(String(destr 1 ), prop#))
owner -> FirAnonymousInitializerSymbol <init>
owner -> FirScriptSymbol util.<script-scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts>
context -> FirPropertySymbol <local>/<destruct> from FirAnonymousInitializerSymbol <init> from FirScriptSymbol util.<script-scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts> from FirFileSymbol scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts
@LeftAnno(<strcat>(String(a ), prop#))
owner -> FirAnonymousInitializerSymbol <init>
owner -> FirScriptSymbol util.<script-scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts>
context -> FirPropertySymbol <local>/a from FirAnonymousInitializerSymbol <init> from FirScriptSymbol util.<script-scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts> from FirFileSymbol scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts
@RightAnno(<strcat>(String(b ), prop#))
owner -> FirAnonymousInitializerSymbol <init>
owner -> FirScriptSymbol util.<script-scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts>
context -> FirPropertySymbol <local>/b from FirAnonymousInitializerSymbol <init> from FirScriptSymbol util.<script-scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts> from FirFileSymbol scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts
@Destr2Anno(<strcat>(String(destr 1 ), prop#))
owner -> FirAnonymousInitializerSymbol <init>
owner -> FirScriptSymbol util.<script-scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts>
context -> FirPropertySymbol <local>/<destruct> from FirAnonymousInitializerSymbol <init> from FirScriptSymbol util.<script-scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts> from FirFileSymbol scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts
@SecondLeftAnno(<strcat>(String(c ), prop#))
owner -> FirAnonymousInitializerSymbol <init>
owner -> FirScriptSymbol util.<script-scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts>
context -> FirPropertySymbol <local>/c from FirAnonymousInitializerSymbol <init> from FirScriptSymbol util.<script-scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts> from FirFileSymbol scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts
@SecondRightAnno(<strcat>(String(d ), prop#))
owner -> FirAnonymousInitializerSymbol <init>
owner -> FirScriptSymbol util.<script-scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts>
context -> FirPropertySymbol <local>/d from FirAnonymousInitializerSymbol <init> from FirScriptSymbol util.<script-scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts> from FirFileSymbol scriptStatementLevelDestructuringWithAnnotationAsLastStatement.kts