Skip to content

Commit

Permalink
[cls] save parameter name for functional types in stub
Browse files Browse the repository at this point in the history
to make it available for deserialized Fir
  • Loading branch information
akozlova authored and teamcity committed Apr 27, 2023
1 parent d59d66e commit a41f7dc
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package test

class ParameterName {
inline fun <A, B> foo(crossinline block: (input: A, state: B) -> Unit) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
PsiJetFileStubImpl[package=test]
KotlinStub$PACKAGE_DIRECTIVE
KotlinStub$REFERENCE_EXPRESSION[referencedName=test]
KotlinStub$IMPORT_LIST
KotlinStub$CLASS[classId=test/ParameterName, fqName=test.ParameterName, isEnumEntry=false, isInterface=false, isLocal=false, isTopLevel=true, name=ParameterName, superNames=[]]
KotlinStub$MODIFIER_LIST[public final]
KotlinStub$PRIMARY_CONSTRUCTOR[fqName=null, hasBody=false, isDelegatedCallToThis=false, isExtension=false, isTopLevel=false, name=ParameterName]
KotlinStub$MODIFIER_LIST[public]
KotlinStub$VALUE_PARAMETER_LIST
KotlinStub$CLASS_BODY
KotlinStub$FUN[fqName=test.ParameterName.foo, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=true, isExtension=false, isTopLevel=false, mayHaveContract=false, name=foo]
KotlinStub$MODIFIER_LIST[public final inline]
KotlinStub$TYPE_PARAMETER_LIST
KotlinStub$TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=A]
KotlinStub$TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=B]
KotlinStub$VALUE_PARAMETER_LIST
KotlinStub$VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=block]
KotlinStub$MODIFIER_LIST[crossinline]
KotlinStub$TYPE_REFERENCE
KotlinStub$FUNCTION_TYPE
KotlinStub$VALUE_PARAMETER_LIST
KotlinStub$VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=null] paramNameByAnnotation: input
KotlinStub$TYPE_REFERENCE
KotlinStub$USER_TYPE
KotlinStub$REFERENCE_EXPRESSION[referencedName=A]
KotlinStub$VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=null] paramNameByAnnotation: state
KotlinStub$TYPE_REFERENCE
KotlinStub$USER_TYPE
KotlinStub$REFERENCE_EXPRESSION[referencedName=B]
KotlinStub$TYPE_REFERENCE
KotlinStub$USER_TYPE
KotlinStub$USER_TYPE
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
KotlinStub$REFERENCE_EXPRESSION[referencedName=Unit]
KotlinStub$TYPE_REFERENCE
KotlinStub$USER_TYPE
KotlinStub$USER_TYPE
KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin]
KotlinStub$REFERENCE_EXPRESSION[referencedName=Unit]
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ abstract class AbstractAdditionalStubInfoTest : AbstractDecompiledClassTest() {
.append(arguments.entries.joinToString(", ", "(", ")") { "${it.key.asString()} = ${it.value}" })
}
}
is KotlinParameterStubImpl -> {
stub.functionTypeParameterName?.let { builder.append(" paramNameByAnnotation: ").append(it) }
}
}
for (child in stub.childrenStubs) {
builder.append("\n").append(" ".repeat(level))
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.intellij.psi.stubs.StubElement
import com.intellij.util.io.StringRef
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.isBuiltinFunctionClass
import org.jetbrains.kotlin.constant.StringValue
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.metadata.ProtoBuf
Expand All @@ -21,7 +22,6 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.protobuf.MessageLite
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.stubs.ConstantValueKind
import org.jetbrains.kotlin.psi.stubs.KotlinUserTypeStub
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
import org.jetbrains.kotlin.psi.stubs.impl.*
Expand All @@ -37,7 +37,8 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
fun createTypeReferenceStub(
parent: StubElement<out PsiElement>,
type: Type,
additionalAnnotations: () -> List<AnnotationWithTarget> = { emptyList() }
additionalAnnotations: () -> List<AnnotationWithTarget> = { emptyList() },
loadTypeAnnotations: (Type) -> List<AnnotationWithArgs> = { c.components.annotationLoader.loadTypeAnnotations(it, c.nameResolver) }
) {
val abbreviatedType = type.abbreviatedType(c.typeTable)
if (abbreviatedType != null) {
Expand All @@ -46,7 +47,8 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {

val typeReference = KotlinPlaceHolderStubImpl<KtTypeReference>(parent, KtStubElementTypes.TYPE_REFERENCE)

val annotations = c.components.annotationLoader.loadTypeAnnotations(type, c.nameResolver).filterNot {
val allAnnotationsInType = loadTypeAnnotations(type)
val annotations = allAnnotationsInType.filterNot {
val isTopLevelClass = !it.classId.isNestedClass
isTopLevelClass && it.classId.asSingleFqName() in ANNOTATIONS_NOT_LOADED_FOR_TYPES
}
Expand Down Expand Up @@ -271,8 +273,8 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
var suspendParameterType: Type? = null

for ((index, argument) in typeArgumentsWithoutReceiverAndReturnType.withIndex()) {
val parameterType = argument.type(c.typeTable)!!
if (isSuspend && index == typeArgumentsWithoutReceiverAndReturnType.size - 1) {
val parameterType = argument.type(c.typeTable)!!
if (parameterType.hasClassName() && parameterType.argumentCount == 1) {
val classId = c.nameResolver.getClassId(parameterType.className)
val fqName = classId.asSingleFqName()
Expand All @@ -286,11 +288,27 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
continue
}
}
val annotations = c.components.annotationLoader.loadTypeAnnotations(parameterType, c.nameResolver)

fun getFunctionTypeParameterName(annotations: List<AnnotationWithArgs>): String? {
for (annotationWithArgs in annotations) {
if (annotationWithArgs.classId.asSingleFqName() == StandardNames.FqNames.parameterName) {
return (annotationWithArgs.args.values.firstOrNull() as? StringValue)?.value
}
}
return null
}

val parameter = KotlinParameterStubImpl(
parameterList, fqName = null, name = null, isMutable = false, hasValOrVar = false, hasDefaultValue = false
parameterList,
fqName = null,
name = null,
isMutable = false,
hasValOrVar = false,
hasDefaultValue = false,
functionTypeParameterName = getFunctionTypeParameterName(annotations)
)

createTypeReferenceStub(parameter, argument.type(c.typeTable)!!)
createTypeReferenceStub(parameter, parameterType, loadTypeAnnotations = { annotations })
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ import org.jetbrains.kotlin.fir.declarations.builder.FirTypeParameterBuilder
import org.jetbrains.kotlin.fir.declarations.utils.addDefaultBoundIfNecessary
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotation
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationArgumentMapping
import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression
import org.jetbrains.kotlin.fir.symbols.*
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.*
Expand All @@ -29,11 +29,13 @@ import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.hasSuspendModifier
import org.jetbrains.kotlin.psi.psiUtil.unwrapNullability
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
import org.jetbrains.kotlin.psi.stubs.impl.*
import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.types.Variance

class StubBasedFirTypeDeserializer(
Expand Down Expand Up @@ -99,11 +101,24 @@ class StubBasedFirTypeDeserializer(
}
}

private fun attributesFromAnnotations(typeReference: KtTypeReference): ConeAttributes =
annotationDeserializer.loadAnnotations(typeReference).computeTypeAttributes(moduleData.session, shouldExpandTypeAliases = false)

fun type(typeReference: KtTypeReference): ConeKotlinType {
return type(typeReference, attributesFromAnnotations(typeReference))
val annotations = annotationDeserializer.loadAnnotations(typeReference).toMutableList()
val parent = typeReference.stub?.parentStub
if (parent is KotlinParameterStubImpl) {
(parent as? KotlinParameterStubImpl)?.functionTypeParameterName?.let { paramName ->
annotations += buildAnnotation {
annotationTypeRef = buildResolvedTypeRef {
type = StandardNames.FqNames.parameterNameClassId.toLookupTag()
.constructClassType(emptyArray(), isNullable = false)
}
this.argumentMapping = buildAnnotationArgumentMapping {
mapping[Name.identifier("name")] =
buildConstExpression(null, ConstantValueKind.String, paramName, setType = true)
}
}
}
}
return type(typeReference, annotations.computeTypeAttributes(moduleData.session, shouldExpandTypeAliases = false))
}

fun type(type: KotlinTypeBean): ConeKotlinType? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ object KotlinStubVersions {
// Though only kotlin declarations (no code in the bodies) are stubbed, please do increase this version
// if you are not 100% sure it can be avoided.
// Increasing this version will lead to reindexing of all kotlin source files on the first IDE startup with the new version.
const val SOURCE_STUB_VERSION = 152
const val SOURCE_STUB_VERSION = 153

// Binary stub version should be increased if stub format (org.jetbrains.kotlin.psi.stubs.impl) is changed
// or changes are made to the core stub building code (org.jetbrains.kotlin.idea.decompiler.stubBuilder).
// Increasing this version will lead to reindexing of all binary files that are potentially kotlin binaries (including all class files).
private const val BINARY_STUB_VERSION = 88
private const val BINARY_STUB_VERSION = 89

// Classfile stub version should be increased if changes are made to classfile stub building subsystem (org.jetbrains.kotlin.idea.decompiler.classFile)
// Increasing this version will lead to reindexing of all classfiles.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public KotlinParameterStub createStub(@NotNull KtParameter psi, StubElement pare
StringRef fqNameRef = StringRef.fromString(fqName != null ? fqName.asString() : null);
return new KotlinParameterStubImpl(
(StubElement<?>) parentStub, fqNameRef, StringRef.fromString(psi.getName()),
psi.isMutable(), psi.hasValOrVar(), psi.hasDefaultValue()
psi.isMutable(), psi.hasValOrVar(), psi.hasDefaultValue(), null
);
}

Expand All @@ -54,6 +54,7 @@ public void serialize(@NotNull KotlinParameterStub stub, @NotNull StubOutputStre
dataStream.writeBoolean(stub.hasDefaultValue());
FqName name = stub.getFqName();
dataStream.writeName(name != null ? name.asString() : null);
dataStream.writeName(stub instanceof KotlinParameterStubImpl ? ((KotlinParameterStubImpl) stub).getFunctionTypeParameterName() : null);
}

@NotNull
Expand All @@ -65,7 +66,8 @@ public KotlinParameterStub deserialize(@NotNull StubInputStream dataStream, Stub
boolean hasDefaultValue = dataStream.readBoolean();
StringRef fqName = dataStream.readName();

return new KotlinParameterStubImpl((StubElement<?>) parentStub, fqName, name, isMutable, hasValOrValNode, hasDefaultValue);
return new KotlinParameterStubImpl((StubElement<?>) parentStub, fqName, name, isMutable, hasValOrValNode, hasDefaultValue,
dataStream.readNameString());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ class KotlinParameterStubImpl(
private val name: StringRef?,
private val isMutable: Boolean,
private val hasValOrVar: Boolean,
private val hasDefaultValue: Boolean
private val hasDefaultValue: Boolean,
val functionTypeParameterName: String? = null
) : KotlinStubBaseImpl<KtParameter>(parent, KtStubElementTypes.VALUE_PARAMETER), KotlinParameterStub {

override fun getName(): String? {
return StringRef.toString(name)
}
Expand Down

0 comments on commit a41f7dc

Please sign in to comment.