reading extension functions from binary classes
This commit is contained in:
@@ -110,6 +110,7 @@ public class FunctionCodegen {
|
|||||||
if(receiverParameter.getType().isNullable()) {
|
if(receiverParameter.getType().isNullable()) {
|
||||||
av.visit(StdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD, true);
|
av.visit(StdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD, true);
|
||||||
}
|
}
|
||||||
|
av.visit(StdlibNames.JET_VALUE_PARAMETER_RECEIVER_FIELD, true);
|
||||||
av.visitEnd();
|
av.visitEnd();
|
||||||
}
|
}
|
||||||
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
||||||
|
|||||||
+95
-25
@@ -9,6 +9,7 @@ import com.intellij.psi.*;
|
|||||||
import com.intellij.psi.search.DelegatingGlobalSearchScope;
|
import com.intellij.psi.search.DelegatingGlobalSearchScope;
|
||||||
import com.intellij.psi.search.GlobalSearchScope;
|
import com.intellij.psi.search.GlobalSearchScope;
|
||||||
import jet.typeinfo.TypeInfoVariance;
|
import jet.typeinfo.TypeInfoVariance;
|
||||||
|
import org.eclipse.jdt.internal.core.JavaModelManager;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
@@ -214,7 +215,11 @@ public class JavaDescriptorResolver {
|
|||||||
classDescriptor,
|
classDescriptor,
|
||||||
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
||||||
false);
|
false);
|
||||||
constructorDescriptor.initialize(typeParameters, resolveParameterDescriptors(constructorDescriptor, constructor.getParameterList().getParameters()), Modality.FINAL,
|
ValueParameterDescriptors valueParameterDescriptors = resolveParameterDescriptors(constructorDescriptor, constructor.getParameterList().getParameters());
|
||||||
|
if (valueParameterDescriptors.receiverType != null) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
constructorDescriptor.initialize(typeParameters, valueParameterDescriptors.descriptors, Modality.FINAL,
|
||||||
resolveVisibilityFromPsiModifiers(constructor));
|
resolveVisibilityFromPsiModifiers(constructor));
|
||||||
constructorDescriptor.setReturnType(classDescriptor.getDefaultType());
|
constructorDescriptor.setReturnType(classDescriptor.getDefaultType());
|
||||||
classDescriptor.addConstructor(constructorDescriptor);
|
classDescriptor.addConstructor(constructorDescriptor);
|
||||||
@@ -522,21 +527,71 @@ public class JavaDescriptorResolver {
|
|||||||
semanticServices.getTrace().record(BindingContext.NAMESPACE, psiClass, namespaceDescriptor);
|
semanticServices.getTrace().record(BindingContext.NAMESPACE, psiClass, namespaceDescriptor);
|
||||||
return namespaceDescriptor;
|
return namespaceDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ValueParameterDescriptors {
|
||||||
|
private final JetType receiverType;
|
||||||
|
private final List<ValueParameterDescriptor> descriptors;
|
||||||
|
|
||||||
public List<ValueParameterDescriptor> resolveParameterDescriptors(DeclarationDescriptor containingDeclaration, PsiParameter[] parameters) {
|
private ValueParameterDescriptors(@Nullable JetType receiverType, List<ValueParameterDescriptor> descriptors) {
|
||||||
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
|
this.receiverType = receiverType;
|
||||||
for (int i = 0, parametersLength = parameters.length; i < parametersLength; i++) {
|
this.descriptors = descriptors;
|
||||||
PsiParameter parameter = parameters[i];
|
|
||||||
ValueParameterDescriptor valueParameterDescriptor = resolveParameterDescriptor(containingDeclaration, i, parameter);
|
|
||||||
if (valueParameterDescriptor != null) {
|
|
||||||
result.add(valueParameterDescriptor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
public ValueParameterDescriptors resolveParameterDescriptors(DeclarationDescriptor containingDeclaration, PsiParameter[] parameters) {
|
||||||
private ValueParameterDescriptor resolveParameterDescriptor(DeclarationDescriptor containingDeclaration, int i, PsiParameter parameter) {
|
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
|
||||||
|
JetType receiverType = null;
|
||||||
|
for (int i = 0, parametersLength = parameters.length; i < parametersLength; i++) {
|
||||||
|
PsiParameter parameter = parameters[i];
|
||||||
|
JvmMethodParameterMeaning meaning = resolveParameterDescriptor(containingDeclaration, i, parameter);
|
||||||
|
if (meaning.kind == JvmMethodParameterKind.TYPE_INFO) {
|
||||||
|
// TODO
|
||||||
|
} else if (meaning.kind == JvmMethodParameterKind.REGULAR) {
|
||||||
|
result.add(meaning.valueParameterDescriptor);
|
||||||
|
} else if (meaning.kind == JvmMethodParameterKind.RECEIVER) {
|
||||||
|
if (receiverType != null) {
|
||||||
|
throw new IllegalStateException("more then one receiver");
|
||||||
|
}
|
||||||
|
receiverType = meaning.receiverType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ValueParameterDescriptors(receiverType, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum JvmMethodParameterKind {
|
||||||
|
REGULAR,
|
||||||
|
RECEIVER,
|
||||||
|
TYPE_INFO,
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class JvmMethodParameterMeaning {
|
||||||
|
private final JvmMethodParameterKind kind;
|
||||||
|
private final JetType receiverType;
|
||||||
|
private final ValueParameterDescriptor valueParameterDescriptor;
|
||||||
|
private final Object typeInfo;
|
||||||
|
|
||||||
|
private JvmMethodParameterMeaning(JvmMethodParameterKind kind, JetType receiverType, ValueParameterDescriptor valueParameterDescriptor, Object typeInfo) {
|
||||||
|
this.kind = kind;
|
||||||
|
this.receiverType = receiverType;
|
||||||
|
this.valueParameterDescriptor = valueParameterDescriptor;
|
||||||
|
this.typeInfo = typeInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JvmMethodParameterMeaning receiver(@NotNull JetType receiverType) {
|
||||||
|
return new JvmMethodParameterMeaning(JvmMethodParameterKind.RECEIVER, receiverType, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JvmMethodParameterMeaning regular(@NotNull ValueParameterDescriptor valueParameterDescriptor) {
|
||||||
|
return new JvmMethodParameterMeaning(JvmMethodParameterKind.REGULAR, null, valueParameterDescriptor, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JvmMethodParameterMeaning typeInfo(@NotNull Object typeInfo) {
|
||||||
|
return new JvmMethodParameterMeaning(JvmMethodParameterKind.TYPE_INFO, null, null, typeInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private JvmMethodParameterMeaning resolveParameterDescriptor(DeclarationDescriptor containingDeclaration, int i, PsiParameter parameter) {
|
||||||
PsiType psiType = parameter.getType();
|
PsiType psiType = parameter.getType();
|
||||||
|
|
||||||
JetType varargElementType;
|
JetType varargElementType;
|
||||||
@@ -552,6 +607,8 @@ public class JavaDescriptorResolver {
|
|||||||
boolean nullable = true;
|
boolean nullable = true;
|
||||||
String typeFromAnnotation = null;
|
String typeFromAnnotation = null;
|
||||||
|
|
||||||
|
boolean receiver = false;
|
||||||
|
|
||||||
// TODO: must be very slow, make it lazy?
|
// TODO: must be very slow, make it lazy?
|
||||||
String name = parameter.getName() != null ? parameter.getName() : "p" + i;
|
String name = parameter.getName() != null ? parameter.getName() : "p" + i;
|
||||||
for (PsiAnnotation annotation : parameter.getModifierList().getAnnotations()) {
|
for (PsiAnnotation annotation : parameter.getModifierList().getAnnotations()) {
|
||||||
@@ -575,8 +632,16 @@ public class JavaDescriptorResolver {
|
|||||||
if (signatureExpression != null) {
|
if (signatureExpression != null) {
|
||||||
typeFromAnnotation = (String) signatureExpression.getValue();
|
typeFromAnnotation = (String) signatureExpression.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PsiLiteralExpression receiverExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_VALUE_PARAMETER_RECEIVER_FIELD);
|
||||||
|
if (receiverExpression != null) {
|
||||||
|
receiver = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} else if (annotation.getQualifiedName().equals(StdlibNames.JET_TYPE_PARAMETER.getFqName())) {
|
} else if (annotation.getQualifiedName().equals(StdlibNames.JET_TYPE_PARAMETER.getFqName())) {
|
||||||
return null;
|
return JvmMethodParameterMeaning.typeInfo(new Object());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -586,16 +651,20 @@ public class JavaDescriptorResolver {
|
|||||||
} else {
|
} else {
|
||||||
outType = semanticServices.getTypeTransformer().transformToType(psiType);
|
outType = semanticServices.getTypeTransformer().transformToType(psiType);
|
||||||
}
|
}
|
||||||
return new ValueParameterDescriptorImpl(
|
if (receiver) {
|
||||||
containingDeclaration,
|
return JvmMethodParameterMeaning.receiver(outType);
|
||||||
i,
|
} else {
|
||||||
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
return JvmMethodParameterMeaning.regular(new ValueParameterDescriptorImpl(
|
||||||
name,
|
containingDeclaration,
|
||||||
null, // TODO : review
|
i,
|
||||||
changeNullable ? TypeUtils.makeNullableAsSpecified(outType, nullable) : outType,
|
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
||||||
false,
|
name,
|
||||||
varargElementType
|
null, // TODO : review
|
||||||
);
|
changeNullable ? TypeUtils.makeNullableAsSpecified(outType, nullable) : outType,
|
||||||
|
false,
|
||||||
|
varargElementType
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public VariableDescriptor resolveFieldToVariableDescriptor(DeclarationDescriptor containingDeclaration, PsiField field) {
|
public VariableDescriptor resolveFieldToVariableDescriptor(DeclarationDescriptor containingDeclaration, PsiField field) {
|
||||||
@@ -687,11 +756,12 @@ public class JavaDescriptorResolver {
|
|||||||
);
|
);
|
||||||
methodDescriptorCache.put(method, functionDescriptorImpl);
|
methodDescriptorCache.put(method, functionDescriptorImpl);
|
||||||
List<TypeParameterDescriptor> typeParameters = resolveMethodTypeParameters(method, functionDescriptorImpl);
|
List<TypeParameterDescriptor> typeParameters = resolveMethodTypeParameters(method, functionDescriptorImpl);
|
||||||
|
ValueParameterDescriptors valueParameterDescriptors = resolveParameterDescriptors(functionDescriptorImpl, parameters);
|
||||||
functionDescriptorImpl.initialize(
|
functionDescriptorImpl.initialize(
|
||||||
null,
|
valueParameterDescriptors.receiverType,
|
||||||
DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor),
|
DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor),
|
||||||
typeParameters,
|
typeParameters,
|
||||||
resolveParameterDescriptors(functionDescriptorImpl, parameters),
|
valueParameterDescriptors.descriptors,
|
||||||
makeReturnType(returnType, method),
|
makeReturnType(returnType, method),
|
||||||
Modality.convertFromFlags(method.hasModifierProperty(PsiModifier.ABSTRACT), !method.hasModifierProperty(PsiModifier.FINAL)),
|
Modality.convertFromFlags(method.hasModifierProperty(PsiModifier.ABSTRACT), !method.hasModifierProperty(PsiModifier.FINAL)),
|
||||||
resolveVisibilityFromPsiModifiers(method)
|
resolveVisibilityFromPsiModifiers(method)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ public class StdlibNames {
|
|||||||
public static final String JET_VALUE_PARAMETER_HAS_DEFAULT_VALUE_FIELD = "hasDefaultValue";
|
public static final String JET_VALUE_PARAMETER_HAS_DEFAULT_VALUE_FIELD = "hasDefaultValue";
|
||||||
public static final String JET_VALUE_PARAMETER_NULLABLE_FIELD = "nullable";
|
public static final String JET_VALUE_PARAMETER_NULLABLE_FIELD = "nullable";
|
||||||
public static final String JET_VALUE_PARAMETER_TYPE_FIELD = "type";
|
public static final String JET_VALUE_PARAMETER_TYPE_FIELD = "type";
|
||||||
|
public static final String JET_VALUE_PARAMETER_RECEIVER_FIELD = "receiver";
|
||||||
|
|
||||||
|
|
||||||
public static final JvmClassName JET_TYPE_PARAMETER = new JvmClassName("jet.typeinfo.JetTypeParameter");
|
public static final JvmClassName JET_TYPE_PARAMETER = new JvmClassName("jet.typeinfo.JetTypeParameter");
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace test
|
||||||
|
|
||||||
|
fun Int.shuffle() = 1
|
||||||
@@ -23,6 +23,7 @@ import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
|||||||
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
|
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
|
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||||
import org.jetbrains.jet.lang.types.Variance;
|
import org.jetbrains.jet.lang.types.Variance;
|
||||||
@@ -226,6 +227,12 @@ public class ReadClassDataTest extends UsefulTestCase {
|
|||||||
serializeCommaSeparated(fun.getTypeParameters(), sb);
|
serializeCommaSeparated(fun.getTypeParameters(), sb);
|
||||||
sb.append(">");
|
sb.append(">");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fun.getReceiverParameter().exists()) {
|
||||||
|
serialize(fun.getReceiverParameter(), sb);
|
||||||
|
sb.append(".");
|
||||||
|
}
|
||||||
|
|
||||||
sb.append(fun.getName());
|
sb.append(fun.getName());
|
||||||
sb.append("(");
|
sb.append("(");
|
||||||
serializeCommaSeparated(fun.getValueParameters(), sb);
|
serializeCommaSeparated(fun.getValueParameters(), sb);
|
||||||
@@ -233,6 +240,10 @@ public class ReadClassDataTest extends UsefulTestCase {
|
|||||||
serialize(fun.getReturnType(), sb);
|
serialize(fun.getReturnType(), sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void serialize(ExtensionReceiver extensionReceiver, StringBuilder sb) {
|
||||||
|
serialize(extensionReceiver.getType(), sb);
|
||||||
|
}
|
||||||
|
|
||||||
private void serialize(PropertyDescriptor prop, StringBuilder sb) {
|
private void serialize(PropertyDescriptor prop, StringBuilder sb) {
|
||||||
if (prop.isVar()) {
|
if (prop.isVar()) {
|
||||||
sb.append("var ");
|
sb.append("var ");
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ public @interface JetValueParameter {
|
|||||||
*/
|
*/
|
||||||
boolean hasDefaultValue () default false;
|
boolean hasDefaultValue () default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return if this parameter is receiver
|
||||||
|
*/
|
||||||
|
boolean receiver() default false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return type unless Java type is correct Kotlin type.
|
* @return type unless Java type is correct Kotlin type.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user