[FIR IDE] LC fix annotations with special sites and nullability

This commit is contained in:
Igor Yakovlev
2020-12-11 17:42:37 +03:00
parent 2e7866ca86
commit 46071c1925
12 changed files with 173 additions and 70 deletions
@@ -12,7 +12,7 @@ public final class Foo /* Foo*/ {
public Foo();// .ctor() public Foo();// .ctor()
public final /* vararg */ void nullableVararg(@org.jetbrains.annotations.Nullable() java.lang.Object...);// nullableVararg(java.lang.Object[]) public final /* vararg */ void nullableVararg(@org.jetbrains.annotations.NotNull() java.lang.Object...);// nullableVararg(java.lang.Object[])
public final int bar4();// bar4() public final int bar4();// bar4()
@@ -8,9 +8,11 @@ package org.jetbrains.kotlin.idea.frontend.api.symbols.markers
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.idea.frontend.api.types.KtType
data class ReceiverTypeAndAnnotations(val type: KtType, val annotations: List<KtAnnotationCall>)
interface KtPossibleExtensionSymbol { interface KtPossibleExtensionSymbol {
val receiverTypeAndAnnotations: ReceiverTypeAndAnnotations?
val isExtension: Boolean val isExtension: Boolean
val receiverType: KtType?
} }
val KtCallableSymbol.isExtension: Boolean val KtCallableSymbol.isExtension: Boolean
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.asJava.parameters.FirLightSetterParameterForSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.* import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.util.ifTrue import org.jetbrains.kotlin.idea.util.ifTrue
import org.jetbrains.kotlin.load.java.JvmAbi.getterName import org.jetbrains.kotlin.load.java.JvmAbi.getterName
@@ -173,8 +174,9 @@ internal class FirLightAccessorMethodForSymbol(
if (propertyParameter != null) { if (propertyParameter != null) {
builder.addParameter( builder.addParameter(
FirLightParameterForSymbol( FirLightSetterParameterForSymbol(
parameterSymbol = propertyParameter, parameterSymbol = propertyParameter,
containingPropertySymbol = containingPropertySymbol,
containingMethod = this@FirLightAccessorMethodForSymbol containingMethod = this@FirLightAccessorMethodForSymbol
) )
) )
@@ -0,0 +1,59 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.asJava
import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.idea.util.ifTrue
import org.jetbrains.kotlin.psi.KtParameter
internal abstract class FirLightParameterBaseForSymbol(
private val parameterSymbol: KtParameterSymbol,
private val containingMethod: FirLightMethod
) : FirLightParameter(containingMethod) {
private val _name: String = parameterSymbol.name.asString()
override fun getName(): String = _name
override fun hasModifierProperty(name: String): Boolean =
modifierList.hasModifierProperty(name)
override val kotlinOrigin: KtParameter? = parameterSymbol.psi as? KtParameter
abstract override fun getModifierList(): PsiModifierList
private val _identifier: PsiIdentifier by lazyPub {
FirLightIdentifier(this, parameterSymbol)
}
protected val nullabilityType: NullabilityType get() {
val nullabilityApplicable = !containingMethod.containingClass.let { it.isAnnotationType || it.isEnum } &&
!containingMethod.hasModifierProperty(PsiModifier.PRIVATE)
return if (nullabilityApplicable) parameterSymbol.type.getTypeNullability(parameterSymbol, FirResolvePhase.TYPES)
else NullabilityType.Unknown
}
override fun getNameIdentifier(): PsiIdentifier = _identifier
private val _type by lazyPub {
val convertedType = parameterSymbol.asPsiType(this, FirResolvePhase.TYPES)
if (convertedType is PsiArrayType && parameterSymbol.isVararg) {
PsiEllipsisType(convertedType.componentType, convertedType.annotationProvider)
} else convertedType
}
override fun getType(): PsiType = _type
abstract override fun equals(other: Any?): Boolean
abstract override fun hashCode(): Int
}
@@ -11,19 +11,17 @@ import com.intellij.psi.PsiModifierList
import com.intellij.psi.PsiType import com.intellij.psi.PsiType
import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionLikeSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotatedSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.ReceiverTypeAndAnnotations
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtNamedSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtNamedSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtPossibleExtensionSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtPossibleExtensionSymbol
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtParameter
internal class FirLightParameterForReceiver private constructor( internal class FirLightParameterForReceiver private constructor(
private val annotatedSymbol: KtAnnotatedSymbol, private val receiverTypeAndAnnotations: ReceiverTypeAndAnnotations,
type: KtType, private val context: KtSymbol,
methodName: String, methodName: String,
method: FirLightMethod method: FirLightMethod
) : FirLightParameter(method) { ) : FirLightParameter(method) {
@@ -35,15 +33,14 @@ internal class FirLightParameterForReceiver private constructor(
): FirLightParameterForReceiver? { ): FirLightParameterForReceiver? {
if (callableSymbol !is KtNamedSymbol) return null if (callableSymbol !is KtNamedSymbol) return null
if (callableSymbol !is KtAnnotatedSymbol) return null
if (callableSymbol !is KtPossibleExtensionSymbol) return null if (callableSymbol !is KtPossibleExtensionSymbol) return null
if (!callableSymbol.isExtension) return null if (!callableSymbol.isExtension) return null
val receiverType = callableSymbol.receiverType ?: return null val extensionTypeAndAnnotations = callableSymbol.receiverTypeAndAnnotations ?: return null
return FirLightParameterForReceiver( return FirLightParameterForReceiver(
annotatedSymbol = callableSymbol, receiverTypeAndAnnotations = extensionTypeAndAnnotations,
type = receiverType, context = callableSymbol,
methodName = callableSymbol.name.asString(), methodName = callableSymbol.name.asString(),
method = method method = method
) )
@@ -64,11 +61,9 @@ internal class FirLightParameterForReceiver private constructor(
override val kotlinOrigin: KtParameter? = null override val kotlinOrigin: KtParameter? = null
private val _annotations: List<PsiAnnotation> by lazyPub { private val _annotations: List<PsiAnnotation> by lazyPub {
annotatedSymbol.computeAnnotations( receiverTypeAndAnnotations.annotations.map {
parent = this, FirLightAnnotationForAnnotationCall(it, this)
nullability = type.getTypeNullability(annotatedSymbol, FirResolvePhase.TYPES), }
annotationUseSiteTarget = AnnotationUseSiteTarget.RECEIVER,
)
} }
override fun getModifierList(): PsiModifierList = _modifierList override fun getModifierList(): PsiModifierList = _modifierList
@@ -77,7 +72,7 @@ internal class FirLightParameterForReceiver private constructor(
} }
private val _type: PsiType by lazyPub { private val _type: PsiType by lazyPub {
type.asPsiType(annotatedSymbol, method, FirResolvePhase.TYPES) receiverTypeAndAnnotations.type.asPsiType(context, method, FirResolvePhase.TYPES)
} }
override fun getType(): PsiType = _type override fun getType(): PsiType = _type
@@ -85,8 +80,7 @@ internal class FirLightParameterForReceiver private constructor(
override fun equals(other: Any?): Boolean = override fun equals(other: Any?): Boolean =
this === other || this === other ||
(other is FirLightParameterForReceiver && (other is FirLightParameterForReceiver &&
kotlinOrigin == other.kotlinOrigin && receiverTypeAndAnnotations == other.receiverTypeAndAnnotations)
annotatedSymbol == other.annotatedSymbol)
override fun hashCode(): Int = kotlinOrigin.hashCode() override fun hashCode(): Int = kotlinOrigin.hashCode()
} }
@@ -5,46 +5,30 @@
package org.jetbrains.kotlin.idea.asJava package org.jetbrains.kotlin.idea.asJava
import com.intellij.psi.* import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiModifierList
import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionLikeSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtParameterSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.idea.util.ifTrue import org.jetbrains.kotlin.idea.util.ifTrue
import org.jetbrains.kotlin.psi.KtParameter
internal class FirLightParameterForSymbol( internal class FirLightParameterForSymbol(
private val parameterSymbol: KtParameterSymbol, private val parameterSymbol: KtParameterSymbol,
containingMethod: FirLightMethod containingMethod: FirLightMethod
) : FirLightParameter(containingMethod) { ) : FirLightParameterBaseForSymbol(parameterSymbol, containingMethod) {
private val _name: String = parameterSymbol.name.asString()
override fun getName(): String = _name
private val _isVarArgs: Boolean = parameterSymbol.isVararg
override fun isVarArgs() = _isVarArgs
override fun hasModifierProperty(name: String): Boolean =
modifierList.hasModifierProperty(name)
override val kotlinOrigin: KtParameter? = parameterSymbol.psi as? KtParameter
private val _annotations: List<PsiAnnotation> by lazyPub { private val _annotations: List<PsiAnnotation> by lazyPub {
val annotationSite = (containingMethod.isConstructor && parameterSymbol.symbolKind == KtSymbolKind.MEMBER).ifTrue {
val annotationSite = (parameterSymbol is KtConstructorParameterSymbol).ifTrue {
AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER
} }
val nullabilityApplicable = !containingMethod.containingClass.let { it.isAnnotationType || it.isEnum } && val nullability = if (parameterSymbol.isVararg) NullabilityType.NotNull else super.nullabilityType
!containingMethod.hasModifierProperty(PsiModifier.PRIVATE)
val nullabilityType = if (nullabilityApplicable)
parameterSymbol.type.getTypeNullability(parameterSymbol, FirResolvePhase.TYPES)
else NullabilityType.Unknown
parameterSymbol.computeAnnotations( parameterSymbol.computeAnnotations(
parent = this, parent = this,
nullability = nullabilityType, nullability = nullability,
annotationUseSiteTarget = annotationSite, annotationUseSiteTarget = annotationSite,
includeAnnotationsWithoutSite = true includeAnnotationsWithoutSite = true
) )
@@ -55,21 +39,7 @@ internal class FirLightParameterForSymbol(
FirLightClassModifierList(this, emptySet(), _annotations) FirLightClassModifierList(this, emptySet(), _annotations)
} }
private val _identifier: PsiIdentifier by lazyPub { override fun isVarArgs() = parameterSymbol.isVararg
FirLightIdentifier(this, parameterSymbol)
}
override fun getNameIdentifier(): PsiIdentifier = _identifier
private val _type by lazyPub {
val convertedType = parameterSymbol.asPsiType(this, FirResolvePhase.TYPES)
if (convertedType is PsiArrayType && parameterSymbol.isVararg) {
PsiEllipsisType(convertedType.componentType, convertedType.annotationProvider)
} else convertedType
}
override fun getType(): PsiType = _type
override fun equals(other: Any?): Boolean = override fun equals(other: Any?): Boolean =
this === other || this === other ||
@@ -0,0 +1,51 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.asJava.parameters
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiModifierList
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.idea.asJava.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
internal class FirLightSetterParameterForSymbol(
private val containingPropertySymbol: KtPropertySymbol,
private val parameterSymbol: KtParameterSymbol,
containingMethod: FirLightMethod
) : FirLightParameterBaseForSymbol(parameterSymbol, containingMethod) {
private val _annotations: List<PsiAnnotation> by lazyPub {
val annotationsFomSetter = parameterSymbol.computeAnnotations(
parent = this,
nullability = NullabilityType.Unknown,
annotationUseSiteTarget = null,
)
val annotationsFromProperty = containingPropertySymbol.computeAnnotations(
parent = this,
nullability = nullabilityType,
annotationUseSiteTarget = AnnotationUseSiteTarget.SETTER_PARAMETER,
includeAnnotationsWithoutSite = false
)
annotationsFomSetter + annotationsFromProperty
}
override fun getModifierList(): PsiModifierList = _modifierList
private val _modifierList: PsiModifierList by lazyPub {
FirLightClassModifierList(this, emptySet(), _annotations)
}
override fun isVarArgs() = false
override fun equals(other: Any?): Boolean =
this === other ||
(other is FirLightSetterParameterForSymbol && parameterSymbol == other.parameterSymbol)
override fun hashCode(): Int = kotlinOrigin.hashCode()
}
@@ -18,10 +18,7 @@ import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.createSignatu
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.convertAnnotation import org.jetbrains.kotlin.idea.frontend.api.fir.utils.convertAnnotation
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotationCall import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtCommonSymbolModality
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolVisibility
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.CanNotCreateSymbolPointerForLocalLibraryDeclarationException import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.CanNotCreateSymbolPointerForLocalLibraryDeclarationException
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer
@@ -57,7 +54,17 @@ internal class KtFirFunctionSymbol(
override val isSuspend: Boolean get() = firRef.withFir { it.isSuspend } override val isSuspend: Boolean get() = firRef.withFir { it.isSuspend }
override val isOverride: Boolean get() = firRef.withFir { it.isOverride } override val isOverride: Boolean get() = firRef.withFir { it.isOverride }
override val receiverType: KtType? by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir -> fir.receiverTypeRef?.let(builder::buildKtType) }
override val receiverTypeAndAnnotations: ReceiverTypeAndAnnotations? by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir ->
fir.receiverTypeRef?.let { typeRef ->
val type = builder.buildKtType(typeRef)
val annotations = typeRef.annotations.mapNotNull {
convertAnnotation(it, fir.session)
}
ReceiverTypeAndAnnotations(type, annotations)
}
}
override val isOperator: Boolean get() = firRef.withFir { it.isOperator } override val isOperator: Boolean get() = firRef.withFir { it.isOperator }
override val isExternal: Boolean get() = firRef.withFir { it.isExternal } override val isExternal: Boolean get() = firRef.withFir { it.isExternal }
override val isInline: Boolean get() = firRef.withFir { it.isInline } override val isInline: Boolean get() = firRef.withFir { it.isInline }
@@ -47,7 +47,17 @@ internal class KtFirKotlinPropertySymbol(
override val isVal: Boolean get() = firRef.withFir { it.isVal } override val isVal: Boolean get() = firRef.withFir { it.isVal }
override val name: Name get() = firRef.withFir { it.name } override val name: Name get() = firRef.withFir { it.name }
override val type: KtType by firRef.withFirAndCache(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) { fir -> builder.buildKtType(fir.returnTypeRef) } override val type: KtType by firRef.withFirAndCache(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) { fir -> builder.buildKtType(fir.returnTypeRef) }
override val receiverType: KtType? by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir -> fir.receiverTypeRef?.let(builder::buildKtType) }
override val receiverTypeAndAnnotations: ReceiverTypeAndAnnotations? by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir ->
fir.receiverTypeRef?.let { typeRef ->
val type = builder.buildKtType(typeRef)
val annotations = typeRef.annotations.mapNotNull {
convertAnnotation(it, fir.session)
}
ReceiverTypeAndAnnotations(type, annotations)
}
}
override val isExtension: Boolean get() = firRef.withFir { it.receiverTypeRef != null } override val isExtension: Boolean get() = firRef.withFir { it.receiverTypeRef != null }
override val initializer: KtConstantValue? by firRef.withFirAndCache(FirResolvePhase.BODY_RESOLVE) { fir -> fir.initializer?.convertConstantExpression() } override val initializer: KtConstantValue? by firRef.withFirAndCache(FirResolvePhase.BODY_RESOLVE) { fir -> fir.initializer?.convertConstantExpression() }
override val symbolKind: KtSymbolKind override val symbolKind: KtSymbolKind
@@ -42,7 +42,15 @@ internal class KtFirSyntheticJavaPropertySymbol(
override val isVal: Boolean get() = firRef.withFir { it.isVal } override val isVal: Boolean get() = firRef.withFir { it.isVal }
override val name: Name get() = firRef.withFir { it.name } override val name: Name get() = firRef.withFir { it.name }
override val type: KtType by firRef.withFirAndCache(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) { fir -> builder.buildKtType(fir.returnTypeRef) } override val type: KtType by firRef.withFirAndCache(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) { fir -> builder.buildKtType(fir.returnTypeRef) }
override val receiverType: KtType? by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir -> fir.receiverTypeRef?.let(builder::buildKtType) } override val receiverTypeAndAnnotations: ReceiverTypeAndAnnotations? by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir ->
fir.receiverTypeRef?.let { typeRef ->
val type = builder.buildKtType(typeRef)
val annotations = typeRef.annotations.mapNotNull {
convertAnnotation(it, fir.session)
}
ReceiverTypeAndAnnotations(type, annotations)
}
}
override val isExtension: Boolean get() = firRef.withFir { it.receiverTypeRef != null } override val isExtension: Boolean get() = firRef.withFir { it.receiverTypeRef != null }
override val initializer: KtConstantValue? by firRef.withFirAndCache(FirResolvePhase.BODY_RESOLVE) { fir -> fir.initializer?.convertConstantExpression() } override val initializer: KtConstantValue? by firRef.withFirAndCache(FirResolvePhase.BODY_RESOLVE) { fir -> fir.initializer?.convertConstantExpression() }
@@ -64,7 +64,7 @@ private fun ConeClassLikeType.expandTypeAliasIfNeeded(session: FirSession): Cone
?: return this ?: return this
} }
private fun convertAnnotation( internal fun convertAnnotation(
annotationCall: FirAnnotationCall, annotationCall: FirAnnotationCall,
session: FirSession session: FirSession
): KtFirAnnotationCall? { ): KtFirAnnotationCall? {
@@ -94,8 +94,8 @@ private fun KtCall.stringRepresentation(): String {
is KtFunctionLikeSymbol -> buildString { is KtFunctionLikeSymbol -> buildString {
append(if (this@stringValue is KtFunctionSymbol) callableIdIfNonLocal ?: name else "<constructor>") append(if (this@stringValue is KtFunctionSymbol) callableIdIfNonLocal ?: name else "<constructor>")
append("(") append("(")
(this@stringValue as? KtFunctionSymbol)?.receiverType?.let { receiver -> (this@stringValue as? KtFunctionSymbol)?.receiverTypeAndAnnotations?.let { receiver ->
append("<receiver>: ${receiver.render()}") append("<receiver>: ${receiver.type.render()}")
if (valueParameters.isNotEmpty()) append(", ") if (valueParameters.isNotEmpty()) append(", ")
} }
valueParameters.joinTo(this) { parameter -> valueParameters.joinTo(this) { parameter ->