Fix for debugger to support inlined lambdas

This commit is contained in:
Mikhael Bogdanov
2014-03-19 18:23:02 +04:00
parent 93367ffd3b
commit 86a02b54fa
2 changed files with 99 additions and 30 deletions
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.resolve.extension;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
@@ -130,18 +131,20 @@ public class InlineAnalyzerExtension implements FunctionAnalyzerExtension.Analyz
}
}
private static boolean checkInlinableParameter(
public static boolean checkInlinableParameter(
@NotNull CallableDescriptor parameter,
@NotNull JetElement expression,
@NotNull FunctionDescriptor functionDescriptor,
@NotNull BindingTrace trace
@NotNull CallableDescriptor functionDescriptor,
@Nullable BindingTrace trace
) {
KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
JetType type = parameter.getReturnType();
if (type != null && builtIns.isExactFunctionOrExtensionFunctionType(type)) {
if (!InlineUtil.hasNoinlineAnnotation(parameter)) {
if (type.isNullable()) {
trace.report(Errors.NULLABLE_INLINE_PARAMETER.on(expression, expression, functionDescriptor));
if (trace != null) {
trace.report(Errors.NULLABLE_INLINE_PARAMETER.on(expression, expression, functionDescriptor));
}
}
else {
return true;
@@ -41,19 +41,22 @@ import org.jetbrains.jet.codegen.PackageCodegen;
import org.jetbrains.jet.codegen.binding.CodegenBinding;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
import org.jetbrains.jet.lang.resolve.extension.InlineAnalyzerExtension;
import org.jetbrains.jet.lang.resolve.java.JetFilesProvider;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.types.lang.InlineStrategy;
import org.jetbrains.jet.lang.types.lang.InlineUtil;
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache;
import org.jetbrains.jet.plugin.util.DebuggerUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.WeakHashMap;
import java.util.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.asmTypeForAnonymousClass;
@@ -134,34 +137,44 @@ public class JetPositionManager implements PositionManager {
JetFile file = (JetFile) sourcePosition.getFile();
JetTypeMapper typeMapper = prepareTypeMapper(file);
PsiElement element = PsiTreeUtil.getParentOfType(sourcePosition.getElementAt(), JetClassOrObject.class, JetFunctionLiteral.class, JetNamedFunction.class);
if (element instanceof JetClassOrObject) {
result.set(getJvmInternalNameForImpl(typeMapper, (JetClassOrObject) element));
}
else if (element instanceof JetFunctionLiteral) {
Type asmType = asmTypeForAnonymousClass(typeMapper.getBindingContext(), ((JetFunctionLiteral) element));
result.set(asmType.getInternalName());
}
else if (element instanceof JetNamedFunction) {
PsiElement parent = PsiTreeUtil.getParentOfType(element, JetClassOrObject.class, JetFunctionLiteralExpression.class, JetNamedFunction.class);
if (parent instanceof JetClassOrObject) {
result.set(getJvmInternalNameForImpl(typeMapper, (JetClassOrObject) parent));
}
else if (parent instanceof JetFunctionLiteralExpression || parent instanceof JetNamedFunction) {
Type asmType = asmTypeForAnonymousClass(typeMapper.getBindingContext(), (JetElement) element);
result.set(asmType.getInternalName());
}
}
if (result.isNull()) {
result.set(PackageCodegen.getPackagePartInternalName(file));
}
result.set(getClassNameForElement(sourcePosition.getElementAt(), typeMapper, file));
}
});
return result.get();
}
@SuppressWarnings("unchecked")
private static String getClassNameForElement(@Nullable PsiElement notPositionedElement, @NotNull JetTypeMapper typeMapper, @NotNull JetFile file) {
PsiElement element = PsiTreeUtil.getParentOfType(notPositionedElement, JetClassOrObject.class, JetFunctionLiteral.class, JetNamedFunction.class);
if (element instanceof JetClassOrObject) {
return getJvmInternalNameForImpl(typeMapper, (JetClassOrObject) element);
}
else if (element instanceof JetFunctionLiteral) {
if (isInlinedLambda((JetFunctionLiteral) element, typeMapper.getBindingContext())) {
return getClassNameForElement(element.getParent(), typeMapper, file);
} else {
Type asmType = asmTypeForAnonymousClass(typeMapper.getBindingContext(), ((JetFunctionLiteral) element));
return asmType.getInternalName();
}
}
else if (element instanceof JetNamedFunction) {
PsiElement parent = PsiTreeUtil.getParentOfType(element, JetClassOrObject.class, JetFunctionLiteralExpression.class, JetNamedFunction.class);
if (parent instanceof JetClassOrObject) {
return getJvmInternalNameForImpl(typeMapper, (JetClassOrObject) parent);
}
else if (parent instanceof JetFunctionLiteralExpression || parent instanceof JetNamedFunction) {
Type asmType = asmTypeForAnonymousClass(typeMapper.getBindingContext(), (JetElement) element);
return asmType.getInternalName();
}
}
return PackageCodegen.getPackagePartInternalName(file);
}
@Nullable
private static String getJvmInternalNameForImpl(JetTypeMapper typeMapper, JetClassOrObject jetClass) {
ClassDescriptor classDescriptor = typeMapper.getBindingContext().get(BindingContext.CLASS, jetClass);
@@ -244,4 +257,57 @@ public class JetPositionManager implements PositionManager {
}, false);
myTypeMappers.put(fqName, value);
}
public static boolean isInlinedLambda(@NotNull JetFunctionLiteral functionLiteral, @NotNull BindingContext context) {
PsiElement functionLiteralExpression = functionLiteral.getParent();
if (functionLiteralExpression == null) return false;
PsiElement parent = functionLiteralExpression.getParent();
PsiElement valueArgument = functionLiteralExpression;
while (parent instanceof JetParenthesizedExpression ||
parent instanceof JetBinaryExpressionWithTypeRHS ||
parent instanceof JetPrefixExpression && JetPsiUtil.isLabeledExpression((JetPrefixExpression) parent)) {
valueArgument = parent;
parent = parent.getParent();
}
while (parent instanceof ValueArgument ||
parent instanceof JetValueArgumentList) {
parent = parent.getParent();
}
if ((parent == null || !(parent instanceof JetBinaryExpression)) && !(parent instanceof JetCallExpression)) return false;
ResolvedCall<?> call = null;
if (parent instanceof JetCallExpression) {
call = context.get(BindingContext.RESOLVED_CALL, ((JetCallExpression) parent).getCalleeExpression());
}
if (parent instanceof JetBinaryExpression) {
call = context.get(BindingContext.RESOLVED_CALL, ((JetBinaryExpression) parent).getOperationReference());
}
if (call == null) return false;
InlineStrategy inlineType = InlineUtil.getInlineType(call.getResultingDescriptor().getAnnotations());
if (!inlineType.isInline()) return false;
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : call.getValueArguments().entrySet()) {
ValueParameterDescriptor valueParameterDescriptor = entry.getKey();
ResolvedValueArgument resolvedValueArgument = entry.getValue();
for (ValueArgument next : resolvedValueArgument.getArguments()) {
JetExpression expression = next.getArgumentExpression();
if (valueArgument == expression) {
return InlineAnalyzerExtension.checkInlinableParameter(
valueParameterDescriptor, (JetElement) resolvedValueArgument,
call.getResultingDescriptor(), null
);
}
}
}
return false;
}
}