Support single-underscore named variables in JVM backend
There are mainly two kind of changes: - skipping 'componentX' calls for destructuring entries named _ - fixing local variable table for them - skip entries for destructuring entries named _ - use $noName_<i> format for lambda parameters named _ #KT-3824 Fixed #KT-2783 Fixed
This commit is contained in:
@@ -44,7 +44,7 @@ class ClosureGenerationStrategy(
|
||||
for (parameterDescriptor in codegen.context.functionDescriptor.valueParameters) {
|
||||
if (parameterDescriptor !is ValueParameterDescriptorImpl.WithDestructuringDeclaration) continue
|
||||
|
||||
for (entry in parameterDescriptor.destructuringVariables) {
|
||||
for (entry in parameterDescriptor.destructuringVariables.filterOutDescriptorsWithSpecialNames()) {
|
||||
codegen.myFrameMap.enter(entry, codegen.typeMapper.mapType(entry.type))
|
||||
}
|
||||
|
||||
|
||||
@@ -775,9 +775,19 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
private void generateDestructuringDeclaration(@NotNull KtDestructuringDeclaration destructuringDeclaration) {
|
||||
final Label destructuringStartLabel = new Label();
|
||||
for (KtDestructuringDeclarationEntry variableDeclaration : destructuringDeclaration.getEntries()) {
|
||||
final VariableDescriptor componentDescriptor = bindingContext.get(VARIABLE, variableDeclaration);
|
||||
|
||||
List<VariableDescriptor> componentDescriptors =
|
||||
CollectionsKt.map(
|
||||
destructuringDeclaration.getEntries(),
|
||||
new Function1<KtDestructuringDeclarationEntry, VariableDescriptor>() {
|
||||
@Override
|
||||
public VariableDescriptor invoke(KtDestructuringDeclarationEntry entry) {
|
||||
return getVariableDescriptorNotNull(entry);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
for (final VariableDescriptor componentDescriptor : CodegenUtilKt.filterOutDescriptorsWithSpecialNames(componentDescriptors)) {
|
||||
@SuppressWarnings("ConstantConditions") final Type componentAsmType = asmType(componentDescriptor.getReturnType());
|
||||
final int componentVarIndex = myFrameMap.enter(componentDescriptor, componentAsmType);
|
||||
scheduleLeaveVariable(new Runnable() {
|
||||
@@ -1957,8 +1967,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
private void putLocalVariableIntoFrameMap(@NotNull KtVariableDeclaration statement) {
|
||||
VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, statement);
|
||||
assert variableDescriptor != null : "Couldn't find variable declaration in binding context " + statement.getText();
|
||||
VariableDescriptor variableDescriptor = getVariableDescriptorNotNull(statement);
|
||||
// Do not modify local variables table for variables like _ in val (_, y) = pair
|
||||
// They always will have special name
|
||||
if (variableDescriptor.getName().isSpecial()) return;
|
||||
|
||||
Type type = getVariableType(variableDescriptor);
|
||||
int index = myFrameMap.enter(variableDescriptor, type);
|
||||
@@ -2004,6 +2016,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
) {
|
||||
final VariableDescriptor variableDescriptor = getVariableDescriptorNotNull(statement);
|
||||
|
||||
// Do not modify local variables table for variables like _ in val (_, y) = pair
|
||||
// They always will have special name
|
||||
if (variableDescriptor.getName().isSpecial()) return;
|
||||
|
||||
final Type type = getVariableType(variableDescriptor);
|
||||
|
||||
final Label scopeStart = new Label();
|
||||
@@ -3902,6 +3918,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(COMPONENT_RESOLVED_CALL, variableDeclaration);
|
||||
assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText();
|
||||
Call call = makeFakeCall(receiver);
|
||||
|
||||
VariableDescriptor variableDescriptor = getVariableDescriptorNotNull(variableDeclaration);
|
||||
|
||||
// Do not call `componentX` for destructuring entry called _
|
||||
if (variableDescriptor.getName().isSpecial()) continue;
|
||||
|
||||
initializeLocalVariable(variableDeclaration, invokeFunction(call, resolvedCall, receiverStackValue));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,9 +46,11 @@ import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.psi.KtElement;
|
||||
import org.jetbrains.kotlin.psi.KtFunction;
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction;
|
||||
import org.jetbrains.kotlin.psi.KtParameter;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue;
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||
import org.jetbrains.kotlin.resolve.constants.KClassValue;
|
||||
@@ -563,7 +565,7 @@ public class FunctionCodegen {
|
||||
|
||||
parameterName =
|
||||
destructuringVariables == null
|
||||
? parameter.getName().asString()
|
||||
? computeParameterName(i, parameter)
|
||||
: "$" + joinParameterNames(destructuringVariables);
|
||||
}
|
||||
else {
|
||||
@@ -583,7 +585,7 @@ public class FunctionCodegen {
|
||||
List<VariableDescriptor> destructuringVariables = ValueParameterDescriptorImpl.getDestructuringVariablesOrNull(parameter);
|
||||
if (destructuringVariables == null) continue;
|
||||
|
||||
for (VariableDescriptor entry : destructuringVariables) {
|
||||
for (VariableDescriptor entry : CodegenUtilKt.filterOutDescriptorsWithSpecialNames(destructuringVariables)) {
|
||||
Type type = typeMapper.mapType(entry.getType());
|
||||
mv.visitLocalVariable(entry.getName().asString(), type.getDescriptor(), null, methodBegin, methodEnd, shift);
|
||||
shift += type.getSize();
|
||||
@@ -591,10 +593,21 @@ public class FunctionCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private static String computeParameterName(int i, ValueParameterDescriptor parameter) {
|
||||
PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(parameter);
|
||||
if (element instanceof KtParameter && UnderscoreUtilKt.isSingleUnderscore((KtParameter) element)) {
|
||||
return "$noName_" + i;
|
||||
}
|
||||
|
||||
return parameter.getName().asString();
|
||||
}
|
||||
|
||||
private static String joinParameterNames(@NotNull List<VariableDescriptor> variables) {
|
||||
return org.jetbrains.kotlin.utils.StringsKt.join(CollectionsKt.map(variables, new Function1<VariableDescriptor, String>() {
|
||||
@Override
|
||||
public String invoke(VariableDescriptor descriptor) {
|
||||
// stub for anonymous destructuring declaration entry
|
||||
if (descriptor.getName().isSpecial()) return "$_$";
|
||||
return descriptor.getName().asString();
|
||||
}
|
||||
}), "_");
|
||||
|
||||
@@ -255,3 +255,5 @@ private fun CallableDescriptor.isJvmStaticIn(predicate: (DeclarationDescriptor)
|
||||
}
|
||||
else -> predicate(containingDeclaration) && hasJvmStaticAnnotation()
|
||||
}
|
||||
|
||||
fun Collection<VariableDescriptor>.filterOutDescriptorsWithSpecialNames() = filterNot { it.name.isSpecial }
|
||||
|
||||
Reference in New Issue
Block a user