[Stubs] Fix stub inconsistency on unnamed setter parameters

If an unused setter parameter was replaced with an underscore ('_'),
it had a special name in the stub ('<anonymous parameter 0>'). The text
version of the stub inserted it as is, leading to an extra
'PsiErrorElement'.

^KTIJ-28194 Fixed
This commit is contained in:
Yan Zhulanow
2023-12-14 15:27:26 +09:00
committed by Space Team
parent 552ee1ee38
commit c8af3381d6
14 changed files with 104 additions and 12 deletions
@@ -311,4 +311,10 @@ public class DecompiledKnmStubConsistencyFe10TestGenerated extends AbstractDecom
public void testTypes() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/Types/");
}
@Test
@TestMetadata("UnderscoreParameterName")
public void testUnderscoreParameterName() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/UnderscoreParameterName/");
}
}
@@ -311,4 +311,10 @@ public class DecompiledKnmStubConsistencyK2TestGenerated extends AbstractDecompi
public void testTypes() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/Types/");
}
@Test
@TestMetadata("UnderscoreParameterName")
public void testUnderscoreParameterName() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/UnderscoreParameterName/");
}
}
@@ -0,0 +1,8 @@
// FIR_IDENTICAL
package test
class UnderscoreParameterName {
var foo: String?
get() = null
set(_) {}
}
@@ -0,0 +1,30 @@
PsiJetFileStubImpl[package=test]
PACKAGE_DIRECTIVE
REFERENCE_EXPRESSION[referencedName=test]
IMPORT_LIST
CLASS[classId=test/UnderscoreParameterName, fqName=test.UnderscoreParameterName, isEnumEntry=false, isInterface=false, isLocal=false, isTopLevel=true, name=UnderscoreParameterName, superNames=[]]
MODIFIER_LIST[public final]
PRIMARY_CONSTRUCTOR[fqName=null, hasBody=false, isDelegatedCallToThis=false, isExtension=false, isTopLevel=false, name=UnderscoreParameterName]
MODIFIER_LIST[public]
VALUE_PARAMETER_LIST
CLASS_BODY
PROPERTY[fqName=test.UnderscoreParameterName.foo, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=true, name=foo]
MODIFIER_LIST[public final]
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=String]
PROPERTY_ACCESSOR[hasBlockBody=true, hasBody=false, isGetter=true]
MODIFIER_LIST[public final]
PROPERTY_ACCESSOR[hasBlockBody=true, hasBody=true, isGetter=false]
MODIFIER_LIST[public final]
VALUE_PARAMETER_LIST
VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=_]
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=String]
@@ -311,4 +311,10 @@ public class ClsStubBuilderK2CompilerTestGenerated extends AbstractClsStubBuilde
public void testTypes() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/Types/");
}
@Test
@TestMetadata("UnderscoreParameterName")
public void testUnderscoreParameterName() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/UnderscoreParameterName/");
}
}
@@ -311,4 +311,10 @@ public class ClsStubBuilderTestGenerated extends AbstractClsStubBuilderTest {
public void testTypes() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/Types/");
}
@Test
@TestMetadata("UnderscoreParameterName")
public void testUnderscoreParameterName() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/UnderscoreParameterName/");
}
}
@@ -7,10 +7,12 @@ package org.jetbrains.kotlin.analysis.decompiler.psi.text
import org.jetbrains.kotlin.analysis.decompiler.stub.COMPILED_DEFAULT_INITIALIZER
import org.jetbrains.kotlin.analysis.decompiler.stub.COMPILED_DEFAULT_PARAMETER_VALUE
import org.jetbrains.kotlin.analysis.decompiler.stub.computeParameterName
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.contracts.description.ContractProviderKey
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.psi.psiUtil.quoteIfNeeded
import org.jetbrains.kotlin.renderer.DescriptorRenderer
@@ -128,11 +130,8 @@ fun buildDecompiledText(
builder.append(descriptorRenderer.renderAnnotation(annotation))
builder.append(" ")
}
val paramName = when (val name = parameterDescriptor.name) {
SpecialNames.IMPLICIT_SET_PARAMETER -> StandardNames.DEFAULT_VALUE_PARAMETER
else -> name
}
builder.append(paramName.asString()).append(": ")
val parameterName = computeParameterName(parameterDescriptor.name)
builder.append(parameterName.asString()).append(": ")
.append(descriptorRenderer.renderType(parameterDescriptor.type))
builder.append(")")
builder.append(" {").append(DECOMPILED_CODE_COMMENT).append(" }")
@@ -311,4 +311,10 @@ public class ByDecompiledPsiStubBuilderK2CompilerTestGenerated extends AbstractB
public void testTypes() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/Types/");
}
@Test
@TestMetadata("UnderscoreParameterName")
public void testUnderscoreParameterName() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/UnderscoreParameterName/");
}
}
@@ -311,4 +311,10 @@ public class ByDecompiledPsiStubBuilderTestGenerated extends AbstractByDecompile
public void testTypes() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/Types/");
}
@Test
@TestMetadata("UnderscoreParameterName")
public void testUnderscoreParameterName() throws Exception {
runTest("analysis/decompiled/decompiler-to-file-stubs/testData/clsFileStubBuilder/UnderscoreParameterName/");
}
}
@@ -330,14 +330,11 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
) {
val parameterListStub = KotlinPlaceHolderStubImpl<KtParameterList>(parent, KtStubElementTypes.VALUE_PARAMETER_LIST)
for ((index, valueParameterProto) in parameters.withIndex()) {
val paramName = when (val name = c.nameResolver.getName(valueParameterProto.name)) {
SpecialNames.IMPLICIT_SET_PARAMETER -> StandardNames.DEFAULT_VALUE_PARAMETER
else -> name
}
val parameterName = computeParameterName(c.nameResolver.getName(valueParameterProto.name))
val hasDefaultValue = Flags.DECLARES_DEFAULT_VALUE.get(valueParameterProto.flags)
val parameterStub = KotlinParameterStubImpl(
parameterListStub,
name = paramName.ref(),
name = parameterName.ref(),
fqName = null,
hasDefaultValue = hasDefaultValue,
hasValOrVar = false,
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
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.KotlinUserTypeStub
@@ -249,3 +250,11 @@ val MessageLite.annotatedCallableKind: AnnotatedCallableKind
fun Name.ref() = StringRef.fromString(this.asString())!!
fun FqName.ref() = StringRef.fromString(this.asString())!!
fun computeParameterName(name: Name): Name {
return when {
name == SpecialNames.IMPLICIT_SET_PARAMETER -> StandardNames.DEFAULT_VALUE_PARAMETER
SpecialNames.isAnonymousParameterName(name) -> Name.identifier("_")
else -> name
}
}
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.diagnostics.Errors;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.name.SpecialNames;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
import org.jetbrains.kotlin.resolve.calls.components.InferenceSession;
@@ -366,7 +367,7 @@ public class DescriptorResolver {
// of containing class where, it can not find a descriptor with special name.
// Thus, to preserve behavior, we don't use a special name for val/var.
parameterName = !valueParameter.hasValOrVar() && UnderscoreUtilKt.isSingleUnderscore(valueParameter)
? Name.special("<anonymous parameter " + index + ">")
? SpecialNames.anonymousParameterName(index)
: KtPsiUtil.safeName(valueParameter.getName());
}
else {
@@ -17,7 +17,7 @@ object KotlinStubVersions {
// 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 = 95
private const val BINARY_STUB_VERSION = 96
// 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.
@@ -88,6 +88,18 @@ object SpecialNames {
return Name.special("<index_$idx>")
}
private const val ANONYMOUS_PARAMETER_NAME_PREFIX = "anonymous parameter"
@JvmStatic
fun anonymousParameterName(index: Int): Name {
return Name.special("<$ANONYMOUS_PARAMETER_NAME_PREFIX $index>")
}
@JvmStatic
fun isAnonymousParameterName(name: Name): Boolean {
return name.isSpecial && name.asStringStripSpecialMarkers().startsWith(ANONYMOUS_PARAMETER_NAME_PREFIX)
}
@JvmStatic
fun safeIdentifier(name: Name?): Name {
return if (name != null && !name.isSpecial) name else SAFE_IDENTIFIER_FOR_NO_NAME