[FIR] Copy receiver of delegateProvider in fir building

There was a problem that receiver of `delegateProvider` and `expression` field
  of `FirWrappedDelegateExpression` was the same object, so after some changes in
  FirCallCompletionResultsWriterTransformer (where call was partially completed and then
  copied) there was a problem with resolve of `delegateProvider`, because reference of it's
  receiver had resolved reference, but type arguments were unsubstituted (see
  `testCommonCaseForInference`).

Maybe there is a better solution. E.g. we can transform type arguments in completion, so we don't need coping of function call at all
This commit is contained in:
Dmitriy Novozhilov
2019-12-10 11:59:07 +03:00
parent 51560f2f17
commit 00112d4227
4 changed files with 18 additions and 18 deletions
@@ -14,7 +14,10 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.builder.*
import org.jetbrains.kotlin.fir.builder.Context
import org.jetbrains.kotlin.fir.builder.generateAccessorsByDelegate
import org.jetbrains.kotlin.fir.builder.generateComponentFunctions
import org.jetbrains.kotlin.fir.builder.generateCopyFunction
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.*
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
@@ -819,6 +822,7 @@ class DeclarationsConverter(
val parentNode = property.getParent()
val isLocal = !(parentNode?.tokenType == KT_FILE || parentNode?.tokenType == CLASS_BODY)
return if (isLocal) {
val receiver = delegateExpression?.let { expressionConverter.getAsFirExpression<FirExpression>(it, "Incorrect delegate expression") }
FirPropertyImpl(
null,
session,
@@ -837,7 +841,7 @@ class DeclarationsConverter(
FirDeclarationStatusImpl(Visibilities.LOCAL, Modality.FINAL)
).apply {
annotations += modifiers.annotations
this.generateAccessorsByDelegate(this@DeclarationsConverter.session, member = false, stubMode = stubMode)
this.generateAccessorsByDelegate(this@DeclarationsConverter.session, member = false, stubMode, receiver)
}
} else {
val status = FirDeclarationStatusImpl(modifiers.getVisibility(), modifiers.getModality()).apply {
@@ -847,6 +851,9 @@ class DeclarationsConverter(
isConst = modifiers.isConst()
isLateInit = modifiers.hasLateinit()
}
val receiver = delegateExpression?.let {
expressionConverter.getAsFirExpression<FirExpression>(it, "Should have delegate")
}
FirPropertyImpl(
null,
session,
@@ -871,7 +878,7 @@ class DeclarationsConverter(
this.getter = getter ?: FirDefaultPropertyGetter(null, session, returnType, modifiers.getVisibility())
this.setter = if (isVar) setter ?: FirDefaultPropertySetter(null, session, returnType, modifiers.getVisibility()) else null
generateAccessorsByDelegate(
this@DeclarationsConverter.session, member = parentNode?.tokenType != KT_FILE, stubMode = stubMode
this@DeclarationsConverter.session, member = parentNode?.tokenType != KT_FILE, stubMode, receiver
)
}
}
@@ -313,7 +313,7 @@ fun generateTemporaryVariable(
session: FirSession, source: FirSourceElement?, specialName: String, initializer: FirExpression
): FirVariable<*> = generateTemporaryVariable(session, source, Name.special("<$specialName>"), initializer)
fun FirModifiableVariable<*>.generateAccessorsByDelegate(session: FirSession, member: Boolean, stubMode: Boolean) {
fun FirModifiableVariable<*>.generateAccessorsByDelegate(session: FirSession, member: Boolean, stubMode: Boolean, receiver: FirExpression?) {
val variable = this as FirVariable<*>
val delegateFieldSymbol = delegateFieldSymbol ?: return
val delegate = delegate as? FirWrappedDelegateExpressionImpl ?: return
@@ -333,7 +333,7 @@ fun FirModifiableVariable<*>.generateAccessorsByDelegate(session: FirSession, me
}
delegate.delegateProvider = if (stubMode) FirExpressionStub(null) else FirFunctionCallImpl(null).apply {
explicitReceiver = delegate.expression
explicitReceiver = receiver
calleeReference = FirSimpleNamedReference(null, PROVIDE_DELEGATE, null)
arguments += thisRef()
arguments += propertyRef()
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.*
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
@@ -775,6 +774,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
val delegateExpression by lazy { property.delegate?.expression }
val propertySource = property.toFirSourceElement()
val firProperty = if (property.isLocal) {
val receiver = delegateExpression?.toFirExpression("Incorrect delegate expression")
FirPropertyImpl(
propertySource,
session,
@@ -793,7 +793,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
true,
FirDeclarationStatusImpl(Visibilities.LOCAL, Modality.FINAL)
).apply {
generateAccessorsByDelegate(this@RawFirBuilder.session, member = false, stubMode = stubMode)
generateAccessorsByDelegate(this@RawFirBuilder.session, member = false, stubMode, receiver)
}
} else {
val status = FirDeclarationStatusImpl(property.visibility, property.modality).apply {
@@ -803,6 +803,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
isConst = property.hasModifier(CONST_KEYWORD)
isLateInit = property.hasModifier(LATEINIT_KEYWORD)
}
val receiver = delegateExpression?.toFirExpression("Should have delegate")
FirPropertyImpl(
propertySource,
session,
@@ -824,7 +825,7 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder
property.extractTypeParametersTo(this)
getter = property.getter.toFirPropertyAccessor(property, propertyType, isGetter = true)
setter = if (isVar) property.setter.toFirPropertyAccessor(property, propertyType, isGetter = false) else null
generateAccessorsByDelegate(this@RawFirBuilder.session, member = !property.isTopLevel, stubMode = stubMode)
generateAccessorsByDelegate(this@RawFirBuilder.session, member = !property.isTopLevel, stubMode, receiver)
}
}
property.extractAnnotationsTo(firProperty)
@@ -21,16 +21,13 @@ import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirWrappedDelegateExpressionImpl
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.isExtensionFunctionAnnotationCall
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.parsing.KotlinParserDefinition
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtPsiFactory
@@ -136,13 +133,10 @@ abstract class AbstractRawFirBuilderTestCase : KtParsingTestCase(
// NB: types are reused sometimes (e.g. in accessors)
if (!result.add(element)) {
throwTwiceVisitingError(element)
} else if (element !is FirWrappedDelegateExpression) {
element.acceptChildren(this)
} else {
element.delegateProvider.accept(this)
element.acceptChildren(this)
}
}
}
private class ConsistencyTransformer : FirTransformer<Unit>() {
@@ -151,10 +145,8 @@ abstract class AbstractRawFirBuilderTestCase : KtParsingTestCase(
override fun <E : FirElement> transformElement(element: E, data: Unit): CompositeTransformResult<E> {
if (!result.add(element)) {
throwTwiceVisitingError(element)
} else if (element !is FirWrappedDelegateExpressionImpl) {
element.transformChildren(this, Unit)
} else {
element.delegateProvider = element.delegateProvider.transformSingle(this, data)
element.transformChildren(this, Unit)
}
return CompositeTransformResult.single(element)
}