diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt index 79616725d0c..861ab2abb73 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/DeclarationsConverter.kt @@ -103,9 +103,7 @@ class DeclarationsConverter( when (it.tokenType) { //TODO("not implemented") BLOCK -> "" - BINARY_EXPRESSION -> firStatements += expressionConverter.convertBinaryExpression(it) - PREFIX_EXPRESSION, POSTFIX_EXPRESSION -> firStatements += expressionConverter.convertUnaryExpression(it) - else -> if (it.isExpression()) firStatements += expressionConverter.visitExpression(it) + else -> if (it.isExpression()) firStatements += expressionConverter.getAsFirExpression(it) } } return FirBlockImpl(session, null).apply { @@ -263,7 +261,7 @@ class DeclarationsConverter( /** * @see org.jetbrains.kotlin.parsing.KotlinParsing.parseAnnotationOrList */ - private fun convertAnnotation(annotationNode: LighterASTNode): List { + fun convertAnnotation(annotationNode: LighterASTNode): List { var annotationTarget: AnnotationUseSiteTarget? = null return annotationNode.forEachChildrenReturnList { node, container -> when (node.tokenType) { @@ -299,7 +297,7 @@ class DeclarationsConverter( * @see org.jetbrains.kotlin.parsing.KotlinParsing.parseAnnotation * can be treated as unescapedAnnotation */ - private fun convertAnnotationEntry( + fun convertAnnotationEntry( unescapedAnnotation: LighterASTNode, defaultAnnotationUseSiteTarget: AnnotationUseSiteTarget? = null ): FirAnnotationCall { @@ -429,16 +427,16 @@ class DeclarationsConverter( var modifiers = Modifier(session) lateinit var identifier: String var hasInitializerList = false - val enumSuperTypeCallEntry = mutableListOf() //TODO get from INITIALIZER_LIST + val enumSuperTypeCallEntry = mutableListOf() val firDeclarations = mutableListOf() enumEntry.forEachChildren { when (it.tokenType) { MODIFIER_LIST -> modifiers = convertModifierList(it) IDENTIFIER -> identifier = it.getAsString() - INITIALIZER_LIST -> hasInitializerList = true //TODO implement - /*enumSuperTypeCallEntry += initializerList.valueParameters.map { firValueParameter -> - firValueParameter.toFirExpression(stubMode) - }*/ + INITIALIZER_LIST -> { + hasInitializerList = true + enumSuperTypeCallEntry += convertInitializerList(it) + } CLASS_BODY -> firDeclarations += convertClassBody(it, classWrapper) } } @@ -469,6 +467,22 @@ class DeclarationsConverter( } } + /** + * @see org.jetbrains.kotlin.parsing.KotlinParsing.parseEnumEntry + */ + private fun convertInitializerList(initializerList: LighterASTNode): List { + val firValueArguments = mutableListOf() + initializerList.forEachChildren { + when (it.tokenType) { + SUPER_TYPE_CALL_ENTRY -> convertConstructorInvocation(it).apply { + firValueArguments += second + } + } + } + + return firValueArguments + } + /** * @see org.jetbrains.kotlin.parsing.KotlinParsing.parseClassBody * @see org.jetbrains.kotlin.parsing.KotlinParsing.parseEnumClassBody @@ -678,13 +692,13 @@ class DeclarationsConverter( COLON -> isReturnType = true TYPE_REFERENCE -> if (isReturnType) returnType = convertType(it) else receiverType = convertType(it) TYPE_CONSTRAINT_LIST -> typeConstraints += convertTypeConstraints(it) - PROPERTY_DELEGATE -> firDelegateExpression = expressionConverter.visitExpression(it) + PROPERTY_DELEGATE -> firDelegateExpression = expressionConverter.getAsFirExpression(it) VAR_KEYWORD -> isVar = true PROPERTY_ACCESSOR -> { val propertyAccessor = convertGetterOrSetter(it, returnType) if (propertyAccessor.isGetter) getter = propertyAccessor else setter = propertyAccessor } - else -> if (it.isExpression()) firExpression = expressionConverter.visitExpression(it) + else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it) } } @@ -746,7 +760,7 @@ class DeclarationsConverter( TYPE_REFERENCE -> returnType = convertType(it) VALUE_PARAMETER_LIST -> firValueParameters = convertSetterParameter(it, propertyTypeRef) BLOCK -> firBlock = visitBlock(it) - else -> if (it.isExpression()) firExpression = expressionConverter.visitExpression(it) + else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it) } } @@ -823,7 +837,7 @@ class DeclarationsConverter( TYPE_REFERENCE -> if (isReturnType) returnType = convertType(it) else receiverType = convertType(it) TYPE_CONSTRAINT_LIST -> typeConstraints += convertTypeConstraints(it) BLOCK -> firBlock = visitBlock(it) - else -> if (it.isExpression()) firExpression = expressionConverter.visitExpression(it) + else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it) } } @@ -941,11 +955,11 @@ class DeclarationsConverter( * ; */ private fun convertConstructorInvocation(constructorInvocation: LighterASTNode): Pair> { - lateinit var firTypeRef: FirTypeRef + var firTypeRef: FirTypeRef = implicitType val firValueArguments = mutableListOf() constructorInvocation.forEachChildren { when (it.tokenType) { - CONSTRUCTOR_CALLEE -> firTypeRef = convertType(it) + CONSTRUCTOR_CALLEE -> if (it.getAsString().isNotEmpty()) firTypeRef = convertType(it) //is empty in enum entry constructor VALUE_ARGUMENT_LIST -> firValueArguments += expressionConverter.convertValueArguments(it) } } @@ -965,7 +979,7 @@ class DeclarationsConverter( explicitDelegation.forEachChildren { when (it.tokenType) { TYPE_REFERENCE -> firTypeRef = convertType(it) - else -> if (it.isExpression()) firExpression = expressionConverter.visitExpression(it) + else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it) } } @@ -1216,7 +1230,7 @@ class DeclarationsConverter( VAR_KEYWORD -> isVar = true IDENTIFIER -> identifier = it.getAsString() TYPE_REFERENCE -> firType = convertType(it) - else -> if (it.isExpression()) firExpression = expressionConverter.visitExpression(it) + else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it) } } diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt index 04c50f21592..cb3877f66bc 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt @@ -25,13 +25,11 @@ import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirExplicitSuperReference import org.jetbrains.kotlin.fir.references.FirExplicitThisReference import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference +import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.types.FirTypeProjection import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.lexer.KtTokens.* -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.KtSuperExpression -import org.jetbrains.kotlin.psi.KtThisExpression import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType import org.jetbrains.kotlin.resolve.constants.evaluate.* import org.jetbrains.kotlin.types.expressions.OperatorConventions @@ -44,23 +42,28 @@ class ExpressionsConverter( private val declarationsConverter: DeclarationsConverter ) : BaseConverter(session, tree) { + inline fun getAsFirExpression(expression: LighterASTNode): R { + return convertExpression(expression) as R + } + /***** EXPRESSIONS *****/ - fun visitExpression(expression: LighterASTNode): FirExpression { + fun convertExpression(expression: LighterASTNode): FirElement { if (!stubMode) { - when (expression.tokenType) { - BINARY_EXPRESSION -> return convertBinaryExpression(expression) as FirExpression - PREFIX_EXPRESSION, POSTFIX_EXPRESSION -> return convertUnaryExpression(expression) as FirExpression - in qualifiedAccessTokens -> return convertQualifiedExpression(expression) - CALL_EXPRESSION -> return convertCallExpression(expression) - ARRAY_ACCESS_EXPRESSION -> return convertArrayAccessExpression(expression) - STRING_TEMPLATE -> return convertStringTemplate(expression) - is KtConstantExpressionElementType -> return convertConstantExpression(expression) - REFERENCE_EXPRESSION -> return convertSimpleNameExpression(expression) - PARENTHESIZED, PROPERTY_DELEGATE, INDICES -> return visitExpression(expression.getExpressionInParentheses()) - THIS_EXPRESSION -> return convertThisExpression(expression) - SUPER_EXPRESSION -> return convertSuperExpression(expression) + return when (expression.tokenType) { + BINARY_EXPRESSION -> convertBinaryExpression(expression) + PREFIX_EXPRESSION, POSTFIX_EXPRESSION -> convertUnaryExpression(expression) + ANNOTATED_EXPRESSION -> convertAnnotatedExpression(expression) + in qualifiedAccessTokens -> convertQualifiedExpression(expression) + CALL_EXPRESSION -> convertCallExpression(expression) + ARRAY_ACCESS_EXPRESSION -> convertArrayAccessExpression(expression) + STRING_TEMPLATE -> convertStringTemplate(expression) + is KtConstantExpressionElementType -> convertConstantExpression(expression) + REFERENCE_EXPRESSION -> convertSimpleNameExpression(expression) + PARENTHESIZED, PROPERTY_DELEGATE, INDICES -> convertExpression(expression.getExpressionInParentheses()) + THIS_EXPRESSION -> convertThisExpression(expression) + SUPER_EXPRESSION -> convertSuperExpression(expression) + else -> FirExpressionStub(session, null) } - return FirExpressionStub(session, null) //TODO("not fully implemented") } @@ -71,7 +74,7 @@ class ExpressionsConverter( * @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseBinaryExpression * @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitBinaryExpression */ - fun convertBinaryExpression(binaryExpression: LighterASTNode): FirStatement { + private fun convertBinaryExpression(binaryExpression: LighterASTNode): FirStatement { var isLeftArgument = true lateinit var operationTokenName: String lateinit var leftArgNode: LighterASTNode @@ -86,7 +89,7 @@ class ExpressionsConverter( if (isLeftArgument) { leftArgNode = it } else { - rightArgAsFir = visitExpression(it) + rightArgAsFir = getAsFirExpression(it) } } } @@ -95,11 +98,17 @@ class ExpressionsConverter( val operationToken = operationTokenName.getOperationSymbol() when (operationToken) { ELVIS -> - return visitExpression(leftArgNode).generateNotNullOrOther(session, rightArgAsFir, "elvis", null) + return getAsFirExpression(leftArgNode).generateNotNullOrOther( + session, rightArgAsFir, "elvis", null + ) ANDAND, OROR -> - return visitExpression(leftArgNode).generateLazyLogicalOperation(session, rightArgAsFir, operationToken == ANDAND, null) + return getAsFirExpression(leftArgNode).generateLazyLogicalOperation( + session, rightArgAsFir, operationToken == ANDAND, null + ) in OperatorConventions.IN_OPERATIONS -> - return rightArgAsFir.generateContainsOperation(session, visitExpression(leftArgNode), operationToken == NOT_IN, null, null) + return rightArgAsFir.generateContainsOperation( + session, getAsFirExpression(leftArgNode), operationToken == NOT_IN, null, null + ) } val conventionCallName = operationToken.toBinaryName() return if (conventionCallName != null || operationToken == IDENTIFIER) { @@ -108,7 +117,7 @@ class ExpressionsConverter( this@ExpressionsConverter.session, null, conventionCallName ?: operationTokenName.nameAsSafeName() ) - explicitReceiver = visitExpression(leftArgNode) + explicitReceiver = getAsFirExpression(leftArgNode) arguments += rightArgAsFir } } else { @@ -117,7 +126,7 @@ class ExpressionsConverter( return convertAssignment(leftArgNode, rightArgAsFir, firOperation) } else { FirOperatorCallImpl(session, null, firOperation).apply { - arguments += visitExpression(leftArgNode) + arguments += getAsFirExpression(leftArgNode) arguments += rightArgAsFir } } @@ -129,7 +138,7 @@ class ExpressionsConverter( * @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parsePrefixExpression * @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitUnaryExpression */ - fun convertUnaryExpression(unaryExpression: LighterASTNode): FirStatement { + private fun convertUnaryExpression(unaryExpression: LighterASTNode): FirExpression { lateinit var operationTokenName: String lateinit var argument: LighterASTNode unaryExpression.forEachChildren { @@ -141,7 +150,7 @@ class ExpressionsConverter( val operationToken = operationTokenName.getOperationSymbol() if (operationToken == EXCLEXCL) { - return bangBangToWhen(session, visitExpression(argument)) + return bangBangToWhen(session, getAsFirExpression(argument)) } val conventionCallName = operationToken.toUnaryName() @@ -155,16 +164,32 @@ class ExpressionsConverter( } FirFunctionCallImpl(session, null).apply { calleeReference = FirSimpleNamedReference(this@ExpressionsConverter.session, null, conventionCallName) - explicitReceiver = visitExpression(argument) + explicitReceiver = getAsFirExpression(argument) } } else { val firOperation = operationToken.toFirOperation() FirOperatorCallImpl(session, null, firOperation).apply { - arguments += visitExpression(argument) + arguments += getAsFirExpression(argument) } } } + private fun convertAnnotatedExpression(annotatedExpression: LighterASTNode): FirElement { + var firExpression: FirElement? = null + val firAnnotationList = mutableListOf() + annotatedExpression.forEachChildren { + when (it.tokenType) { + ANNOTATION -> firAnnotationList += declarationsConverter.convertAnnotation(it) + ANNOTATION_ENTRY -> firAnnotationList += declarationsConverter.convertAnnotationEntry(it) + else -> if (it.isExpression()) firExpression = getAsFirExpression(it) + } + } + + return (firExpression as? FirAbstractAnnotatedElement)?.apply { + annotations += firAnnotationList + } ?: FirErrorExpressionImpl(session, null, "Strange annotated expression: ${firExpression?.render()}") + } + /** * @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parsePostfixExpression * @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitQualifiedExpression @@ -181,7 +206,7 @@ class ExpressionsConverter( isSafe = true isSelector = true } - else -> if (isSelector) firSelector = visitExpression(it) else firReceiver = visitExpression(it) + else -> if (isSelector) firSelector = getAsFirExpression(it) else firReceiver = getAsFirExpression(it) } } @@ -211,7 +236,7 @@ class ExpressionsConverter( TYPE_ARGUMENT_LIST -> firTypeArguments += declarationsConverter.convertTypeArguments(it) VALUE_ARGUMENT_LIST -> firValueArguments += convertValueArguments(it) LAMBDA_ARGUMENT -> firValueArguments += convertAnnotatedLambda(it) - else -> additionalArgument = visitExpression(it) + else -> additionalArgument = getAsFirExpression(it) } } @@ -294,8 +319,8 @@ class ExpressionsConverter( private fun convertShortOrLongStringTemplate(shortOrLongString: LighterASTNode): FirExpression { lateinit var firExpression: FirExpression - shortOrLongString.forEachChildren { - firExpression = visitExpression(it) + shortOrLongString.forEachChildren(LONG_TEMPLATE_ENTRY_START, LONG_TEMPLATE_ENTRY_END) { + firExpression = getAsFirExpression(it) } return firExpression } @@ -355,24 +380,34 @@ class ExpressionsConverter( * @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseArrayAccess * @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitArrayAccessExpression */ - private fun convertArrayAccessExpression(arrayAccess: LighterASTNode): FirFunctionCall {//Pair> { - lateinit var expression: FirExpression - val indexes: MutableList = mutableListOf() + private fun convertArrayAccessExpression(arrayAccess: LighterASTNode): FirFunctionCall { + lateinit var firExpression: FirExpression + val indices: MutableList = mutableListOf() arrayAccess.forEachChildren { when (it.tokenType) { - INDICES -> indexes += visitExpression(it) - else -> if (it.isExpression()) expression = visitExpression(it) + INDICES -> indices += convertIndices(it) + else -> if (it.isExpression()) firExpression = getAsFirExpression(it) } } return FirFunctionCallImpl(session, null).apply { calleeReference = FirSimpleNamedReference(this@ExpressionsConverter.session, null, OperatorNameConventions.GET) - explicitReceiver = expression - for (indexExpression in indexes) { - arguments += indexExpression - } + explicitReceiver = firExpression + arguments += indices } } + /** + * @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseAsCollectionLiteralExpression + */ + private fun convertIndices(indices: LighterASTNode): List { + val firExpressionList: MutableList = mutableListOf() + indices.forEachChildren { + if (it.isExpression()) firExpressionList += getAsFirExpression(it) + } + + return firExpressionList + } + /** * @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseSimpleNameExpression * @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitSimpleNameExpression @@ -443,7 +478,7 @@ class ExpressionsConverter( MUL -> isSpread = true STRING_TEMPLATE -> firExpression = convertStringTemplate(it) is KtConstantExpressionElementType -> firExpression = convertConstantExpression(it) - else -> if (it.isExpression()) firExpression = visitExpression(it) + else -> if (it.isExpression()) firExpression = getAsFirExpression(it) } } return when { @@ -458,7 +493,7 @@ class ExpressionsConverter( return when (it.tokenType) { THIS_EXPRESSION -> convertThisExpression(leftArgNode).calleeReference REFERENCE_EXPRESSION -> FirSimpleNamedReference(session, null, it.getAsString().nameAsSafeName()) - in qualifiedAccessTokens -> (visitExpression(it) as FirQualifiedAccess).let { firQualifiedAccess -> + in qualifiedAccessTokens -> (getAsFirExpression(it) as FirQualifiedAccess).let { firQualifiedAccess -> container.explicitReceiver = firQualifiedAccess.explicitReceiver container.safe = firQualifiedAccess.safe return@let firQualifiedAccess.calleeReference diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/utils/ExpressionUtil.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/utils/ExpressionUtil.kt index e4840e3adf8..7f28d20c04d 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/utils/ExpressionUtil.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/utils/ExpressionUtil.kt @@ -43,7 +43,7 @@ fun ExpressionsConverter.convertAssignment( return convertAssignment(leftArgNode.getExpressionInParentheses(), rightArgAsFir, operation) } if (leftArgNode.tokenType == ARRAY_ACCESS_EXPRESSION) { - val arrayAccessFunctionCall = visitExpression(leftArgNode) as FirFunctionCall + val arrayAccessFunctionCall = getAsFirExpression(leftArgNode) as FirFunctionCall val firArrayExpression = arrayAccessFunctionCall.explicitReceiver!! val arraySet = if (operation != FirOperation.ASSIGN) { FirArraySetCallImpl(session, null, rightArgAsFir, operation).apply { @@ -74,7 +74,7 @@ fun ExpressionsConverter.convertAssignment( ) { return FirBlockImpl(session, null).apply { val name = Name.special("") - statements += generateTemporaryVariable(this@convertAssignment.session, null, name, visitExpression(leftArgNode)) + statements += generateTemporaryVariable(this@convertAssignment.session, null, name, getAsFirExpression(leftArgNode)) statements += FirVariableAssignmentImpl(this@convertAssignment.session, null, rightArgAsFir, operation).apply { lValue = FirSimpleNamedReference(this@convertAssignment.session, null, name) } @@ -96,12 +96,16 @@ fun ExpressionsConverter.generateIncrementOrDecrementBlock( } return FirBlockImpl(session, null).apply { val tempName = Name.special("") - val temporaryVariable = generateTemporaryVariable(this@generateIncrementOrDecrementBlock.session, null, tempName, visitExpression(argument)) + val temporaryVariable = generateTemporaryVariable( + this@generateIncrementOrDecrementBlock.session, null, tempName, getAsFirExpression(argument) + ) statements += temporaryVariable val resultName = Name.special("") val resultInitializer = FirFunctionCallImpl(this@generateIncrementOrDecrementBlock.session, null).apply { this.calleeReference = FirSimpleNamedReference(this@generateIncrementOrDecrementBlock.session, null, callName) - this.explicitReceiver = generateResolvedAccessExpression(this@generateIncrementOrDecrementBlock.session, null, temporaryVariable) + this.explicitReceiver = generateResolvedAccessExpression( + this@generateIncrementOrDecrementBlock.session, null, temporaryVariable + ) } val resultVar = generateTemporaryVariable(this@generateIncrementOrDecrementBlock.session, null, resultName, resultInitializer) val assignment = convertAssignment( @@ -128,7 +132,9 @@ fun ExpressionsConverter.generateIncrementOrDecrementBlock( statements += generateResolvedAccessExpression(this@generateIncrementOrDecrementBlock.session, null, resultVar) } else { appendAssignment() - statements += generateAccessExpression(this@generateIncrementOrDecrementBlock.session, null, argument.getAsString().nameAsSafeName()) + statements += generateAccessExpression( + this@generateIncrementOrDecrementBlock.session, null, argument.getAsString().nameAsSafeName() + ) } } else { appendAssignment() diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/FirPartialTransformer.kt b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/FirPartialTransformer.kt index c1ca6f55718..2f78cdd1e92 100644 --- a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/FirPartialTransformer.kt +++ b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/compare/FirPartialTransformer.kt @@ -62,7 +62,7 @@ class FirPartialTransformer( } override fun transformNamedFunction(namedFunction: FirNamedFunction, data: Nothing?): CompositeTransformResult { - return if (!visitNamedFunction || (namedFunction is FirAbstractCallableMember && namedFunction.visibility == Visibilities.LOCAL)) { + return if (!visitNamedFunction && namedFunction is FirAbstractCallableMember && namedFunction.visibility == Visibilities.LOCAL) { DummyFirDeclaration().compose() } else { (namedFunction.transformChildren(this, data) as FirNamedFunction).compose() @@ -73,7 +73,7 @@ class FirPartialTransformer( memberDeclaration: FirMemberDeclaration, data: Nothing? ): CompositeTransformResult { - return if (!visitMemberDeclaration || memberDeclaration.visibility == Visibilities.LOCAL) { + return if (!visitMemberDeclaration && memberDeclaration.visibility == Visibilities.LOCAL) { DummyFirDeclaration().compose() } else { (memberDeclaration.transformChildren(this, data) as FirMemberDeclaration).compose()