Merge branch 'master' of ssh://git.labs.intellij.net/jet

This commit is contained in:
svtk
2011-09-21 18:05:55 +04:00
59 changed files with 1006 additions and 629 deletions
@@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.InstructionAdapter;
@@ -72,7 +73,7 @@ public class ClassContext {
thisIdx++; thisIdx++;
} }
final boolean hasReceiver = descriptor.getReceiverType() != null; final boolean hasReceiver = descriptor.getReceiver().exists();
if (hasReceiver) { if (hasReceiver) {
thisIdx++; thisIdx++;
} }
@@ -102,12 +103,12 @@ public class ClassContext {
return frameMap; return frameMap;
} }
private JetType receiverType() { private ReceiverDescriptor receiver() {
return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiverType() : null; return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiver() : ReceiverDescriptor.NO_RECEIVER;
} }
private boolean hasReceiver() { private boolean hasReceiver() {
return receiverType() != null; return receiver().exists();
} }
public ClassContext getParentContext() { public ClassContext getParentContext() {
@@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.JetFunctionLiteral; import org.jetbrains.jet.lang.psi.JetFunctionLiteral;
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression; import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
@@ -41,7 +42,7 @@ public class ClosureCodegen {
} }
public static Method erasedInvokeSignature(FunctionDescriptor fd) { public static Method erasedInvokeSignature(FunctionDescriptor fd) {
boolean isExtensionFunction = fd.getReceiverType() != null; boolean isExtensionFunction = fd.getReceiver().exists();
int paramCount = fd.getValueParameters().size(); int paramCount = fd.getValueParameters().size();
if (isExtensionFunction) { if (isExtensionFunction) {
paramCount++; paramCount++;
@@ -150,11 +151,11 @@ public class ClosureCodegen {
iv.load(0, Type.getObjectType(className)); iv.load(0, Type.getObjectType(className));
final JetType receiverType = funDescriptor.getReceiverType(); final ReceiverDescriptor receiver = funDescriptor.getReceiver();
int count = 1; int count = 1;
if (receiverType != null) { if (receiver.exists()) {
StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv); StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv);
StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(state.getTypeMapper().mapType(receiverType), iv); StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(state.getTypeMapper().mapType(receiver.getType()), iv);
count++; count++;
} }
@@ -228,7 +229,7 @@ public class ClosureCodegen {
public static String getInternalClassName(FunctionDescriptor descriptor) { public static String getInternalClassName(FunctionDescriptor descriptor) {
final int paramCount = descriptor.getValueParameters().size(); final int paramCount = descriptor.getValueParameters().size();
if (descriptor.getReceiverType() != null) { if (descriptor.getReceiver().exists()) {
return "jet/ExtensionFunction" + paramCount; return "jet/ExtensionFunction" + paramCount;
} }
else { else {
@@ -249,7 +250,7 @@ public class ClosureCodegen {
Method descriptor = erasedInvokeSignature(fd); Method descriptor = erasedInvokeSignature(fd);
String owner = getInternalClassName(fd); String owner = getInternalClassName(fd);
final CallableMethod result = new CallableMethod(owner, descriptor, Opcodes.INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes())); final CallableMethod result = new CallableMethod(owner, descriptor, Opcodes.INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
if (fd.getReceiverType() != null) { if (fd.getReceiver().exists()) {
result.setNeedsReceiver(null); result.setNeedsReceiver(null);
} }
result.requestGenerateCallee(Type.getObjectType(getInternalClassName(fd))); result.requestGenerateCallee(Type.getObjectType(getInternalClassName(fd)));
@@ -82,17 +82,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
typeParameterExpressions.put(typeParameter, expression); typeParameterExpressions.put(typeParameter, expression);
} }
static void loadTypeInfo(JetTypeMapper typeMapper, ClassDescriptor descriptor, InstructionAdapter v) {
String owner = typeMapper.jvmName(descriptor, OwnerKind.IMPLEMENTATION);
if (descriptor.getTypeConstructor().getParameters().size() > 0) {
v.load(0, JetTypeMapper.TYPE_OBJECT);
v.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
}
else {
v.getstatic(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
}
}
public StackValue genQualified(StackValue receiver, JetElement selector) { public StackValue genQualified(StackValue receiver, JetElement selector) {
markLineNumber(selector); markLineNumber(selector);
return selector.visit(this, receiver); return selector.visit(this, receiver);
@@ -2033,9 +2022,26 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration(); DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
if (containingDeclaration == contextType() && contextType() instanceof ClassDescriptor) { if (containingDeclaration == contextType() && contextType() instanceof ClassDescriptor) {
loadTypeInfo(typeMapper, (ClassDescriptor) contextType(), v); ClassDescriptor descriptor = (ClassDescriptor) contextType();
JetType defaultType = descriptor.getDefaultType();
Type ownerType = typeMapper.mapType(defaultType);
ownerType = JetTypeMapper.boxType(ownerType);
if(!typeMapper.isInterface(descriptor)) {
if (descriptor.getTypeConstructor().getParameters().size() > 0) {
v.load(0, JetTypeMapper.TYPE_OBJECT);
v.getfield(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
}
else {
v.getstatic(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
}
}
else {
v.load(0, JetTypeMapper.TYPE_OBJECT);
v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
}
v.aconst(ownerType);
v.iconst(typeParameterDescriptor.getIndex()); v.iconst(typeParameterDescriptor.getIndex());
v.invokevirtual("jet/typeinfo/TypeInfo", "getArgumentType", "(I)Ljet/typeinfo/TypeInfo;"); v.invokevirtual("jet/typeinfo/TypeInfo", "getArgumentType", "(Ljava/lang/Class;I)Ljet/typeinfo/TypeInfo;");
return; return;
} }
throw new UnsupportedOperationException("don't know what this type parameter resolves to"); throw new UnsupportedOperationException("don't know what this type parameter resolves to");
@@ -141,7 +141,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override @Override
protected void generateSyntheticParts() { protected void generateSyntheticParts() {
generateFieldForTypeInfo();
generateFieldForObjectInstance(); generateFieldForObjectInstance();
generateFieldForClassObject(); generateFieldForClassObject();
@@ -156,25 +155,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
//genGetSuperTypesTypeInfo(); //genGetSuperTypesTypeInfo();
} }
private void generateFieldForTypeInfo() {
if(myClass instanceof JetClass && ((JetClass)myClass).isTrait())
return;
final boolean typeInfoIsStatic = descriptor.getTypeConstructor().getParameters().size() == 0;
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | (typeInfoIsStatic ? Opcodes.ACC_STATIC : 0), "$typeInfo",
"Ljet/typeinfo/TypeInfo;", null, null);
if (typeInfoIsStatic) {
staticInitializerChunks.add(new CodeChunk() {
@Override
public void generate(InstructionAdapter v) {
JetTypeMapper typeMapper = state.getTypeMapper();
ClassCodegen.newTypeInfo(v, false, typeMapper.jvmType(descriptor, OwnerKind.IMPLEMENTATION));
v.putstatic(typeMapper.jvmName(descriptor, kind), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
}
});
}
}
private void generateFieldForObjectInstance() { private void generateFieldForObjectInstance() {
if (isNonLiteralObject()) { if (isNonLiteralObject()) {
Type type = JetTypeMapper.jetImplementationType(descriptor); Type type = JetTypeMapper.jetImplementationType(descriptor);
@@ -397,6 +377,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
} }
else if(psiElement instanceof PsiClass) { else if(psiElement instanceof PsiClass) {
// todo
PsiClass psiClass = (PsiClass) psiElement; PsiClass psiClass = (PsiClass) psiElement;
} }
} }
@@ -550,7 +531,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.astore(JetTypeMapper.TYPE_OBJECT); iv.astore(JetTypeMapper.TYPE_OBJECT);
} }
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;"); iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
iv.putfield(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$typeInfo", "Ljet/typeinfo/TypeInfo;"); iv.invokevirtual(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V");
} }
protected void generateInitializers(ExpressionCodegen codegen, InstructionAdapter iv) { protected void generateInitializers(ExpressionCodegen codegen, InstructionAdapter iv) {
@@ -648,21 +629,79 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if(myClass instanceof JetClass && ((JetClass)myClass).isTrait()) if(myClass instanceof JetClass && ((JetClass)myClass).isTrait())
return; return;
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC, JetType defaultType = descriptor.getDefaultType();
"getTypeInfo", if(isParametrizedClass(defaultType)) {
"()Ljet/typeinfo/TypeInfo;", if(!hasDerivedTypeInfoField(defaultType, true)) {
null /* TODO */, v.visitField(Opcodes.ACC_PRIVATE, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
null);
mv.visitCode(); MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
InstructionAdapter v = new InstructionAdapter(mv); mv.visitCode();
ExpressionCodegen.loadTypeInfo(state.getTypeMapper(), descriptor, v); InstructionAdapter iv = new InstructionAdapter(mv);
v.areturn(JetTypeMapper.TYPE_TYPEINFO); String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
mv.visitMaxs(0, 0); iv.load(0, JetTypeMapper.TYPE_OBJECT);
mv.visitEnd(); iv.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
iv.areturn(JetTypeMapper.TYPE_TYPEINFO);
mv.visitMaxs(0, 0);
mv.visitEnd();
mv = v.visitMethod(Opcodes.ACC_PROTECTED|Opcodes.ACC_FINAL, "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V", null, null);
mv.visitCode();
iv = new InstructionAdapter(mv);
owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.load(1, JetTypeMapper.TYPE_OBJECT);
iv.putfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
else {
if(descriptor.getTypeConstructor().getParameters().isEmpty()) {
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
staticInitializerChunks.add(new CodeChunk() {
@Override
public void generate(InstructionAdapter v) {
JetTypeMapper typeMapper = state.getTypeMapper();
ClassCodegen.newTypeInfo(v, false, typeMapper.jvmType(descriptor, OwnerKind.IMPLEMENTATION));
v.putstatic(typeMapper.jvmName(descriptor, kind), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
}
});
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv);
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
v.getstatic(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
v.areturn(JetTypeMapper.TYPE_TYPEINFO);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
}
}
else {
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
staticInitializerChunks.add(new CodeChunk() {
@Override
public void generate(InstructionAdapter v) {
JetTypeMapper typeMapper = state.getTypeMapper();
ClassCodegen.newTypeInfo(v, false, typeMapper.jvmType(descriptor, OwnerKind.IMPLEMENTATION));
v.putstatic(typeMapper.jvmName(descriptor, kind), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
}
});
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv);
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
v.getstatic(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
v.areturn(JetTypeMapper.TYPE_TYPEINFO);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
} }
private void generateClassObject(JetClassObject declaration) { private void generateClassObject(JetClassObject declaration) {
state.forClass().generate(context, declaration.getObjectDeclaration()); state.forClass().generate(context, declaration.getObjectDeclaration());
} }
private void genGetSuperTypesTypeInfo() { private void genGetSuperTypesTypeInfo() {
@@ -710,4 +749,31 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
return sb.toString(); return sb.toString();
} }
public static boolean isParametrizedClass(JetType type) {
if(type.getConstructor().getParameters().size() > 0)
return true;
for (JetType jetType : type.getConstructor().getSupertypes()) {
if(isParametrizedClass(jetType))
return true;
}
return false;
}
public boolean hasDerivedTypeInfoField(JetType type, boolean exceptOwn) {
if(!exceptOwn) {
if(!state.getTypeMapper().isInterface((ClassDescriptor) type.getConstructor().getDeclarationDescriptor()))
if(isParametrizedClass(type))
return true;
}
for (JetType jetType : type.getConstructor().getSupertypes()) {
if(hasDerivedTypeInfoField(jetType, false))
return true;
}
return false;
}
} }
@@ -9,6 +9,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.resolve.DescriptorRenderer; import org.jetbrains.jet.resolve.DescriptorRenderer;
@@ -514,11 +515,11 @@ public class JetTypeMapper {
} }
public Method mapSignature(String name, FunctionDescriptor f) { public Method mapSignature(String name, FunctionDescriptor f) {
final JetType receiverType = f.getReceiverType(); final ReceiverDescriptor receiver = f.getReceiver();
final List<ValueParameterDescriptor> parameters = f.getValueParameters(); final List<ValueParameterDescriptor> parameters = f.getValueParameters();
List<Type> parameterTypes = new ArrayList<Type>(); List<Type> parameterTypes = new ArrayList<Type>();
if (receiverType != null) { if (receiver.exists()) {
parameterTypes.add(mapType(receiverType)); parameterTypes.add(mapType(receiver.getType()));
} }
for (ValueParameterDescriptor parameter : parameters) { for (ValueParameterDescriptor parameter : parameters) {
parameterTypes.add(mapType(parameter.getOutType())); parameterTypes.add(mapType(parameter.getOutType()));
@@ -5,6 +5,7 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
@@ -42,7 +43,7 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
} }
} }
} }
return null; return JetStandardClasses.getAnyType();
} }
@Override @Override
@@ -60,9 +61,4 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
private String jvmName() { private String jvmName() {
return state.getTypeMapper().jvmName(descriptor, OwnerKind.TRAIT_IMPL); return state.getTypeMapper().jvmName(descriptor, OwnerKind.TRAIT_IMPL);
} }
@Override
protected void genNamedFunction(JetNamedFunction declaration, FunctionCodegen functionCodegen) {
super.genNamedFunction(declaration, functionCodegen); //To change body of overridden methods use File | Settings | File Templates.
}
} }
@@ -5,6 +5,8 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import java.util.Collections; import java.util.Collections;
@@ -23,6 +25,7 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
private Modality modality; private Modality modality;
private JetType superclassType; private JetType superclassType;
private final ClassKind kind; private final ClassKind kind;
private ClassReceiver implicitReceiver;
public JavaClassDescriptor(DeclarationDescriptor containingDeclaration, @NotNull ClassKind kind) { public JavaClassDescriptor(DeclarationDescriptor containingDeclaration, @NotNull ClassKind kind) {
@@ -155,4 +158,13 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
public String toString() { public String toString() {
return "java class " + typeConstructor; return "java class " + typeConstructor;
} }
@NotNull
@Override
public ReceiverDescriptor getImplicitReceiver() {
if (implicitReceiver == null) {
implicitReceiver = new ClassReceiver(this);
}
return implicitReceiver;
}
} }
+1 -1
View File
@@ -96,7 +96,7 @@ trait Range<in T : Comparable<T>> {
fun contains(item : T) : Boolean fun contains(item : T) : Boolean
} }
class IntRange<T : Comparable<T>> : Range<T>, Iterable<T> { class IntRange<T : Comparable<T>>(val start : Int, val end : Int) : Range<T>, Iterable<T> {
} }
@@ -1,7 +1,8 @@
package org.jetbrains.jet.lang.descriptors; package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.resolve.scopes.receivers.ImplicitReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor; import org.jetbrains.jet.lang.types.TypeSubstitutor;
@@ -12,8 +13,8 @@ import java.util.Set;
* @author abreslav * @author abreslav
*/ */
public interface CallableDescriptor extends DeclarationDescriptor { public interface CallableDescriptor extends DeclarationDescriptor {
@Nullable @NotNull
JetType getReceiverType(); ReceiverDescriptor getReceiver();
@NotNull @NotNull
List<TypeParameterDescriptor> getTypeParameters(); List<TypeParameterDescriptor> getTypeParameters();
@@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.descriptors;
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.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
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.TypeSubstitutor; import org.jetbrains.jet.lang.types.TypeSubstitutor;
@@ -53,4 +54,7 @@ public interface ClassDescriptor extends ClassifierDescriptor {
@NotNull @NotNull
Modality getModality(); Modality getModality();
@NotNull
ReceiverDescriptor getImplicitReceiver();
} }
@@ -5,6 +5,8 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import java.util.Collection; import java.util.Collection;
@@ -21,6 +23,7 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
private FunctionGroup constructors; private FunctionGroup constructors;
private ConstructorDescriptor primaryConstructor; private ConstructorDescriptor primaryConstructor;
private JetType superclassType; private JetType superclassType;
private ReceiverDescriptor implicitReceiver;
public ClassDescriptorImpl( public ClassDescriptorImpl(
@NotNull DeclarationDescriptor containingDeclaration, @NotNull DeclarationDescriptor containingDeclaration,
@@ -151,4 +154,13 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
public Modality getModality() { public Modality getModality() {
return Modality.FINAL; return Modality.FINAL;
} }
@NotNull
@Override
public ReceiverDescriptor getImplicitReceiver() {
if (implicitReceiver == null) {
implicitReceiver = new ClassReceiver(this);
}
return implicitReceiver;
}
} }
@@ -5,6 +5,8 @@ import com.google.common.collect.Sets;
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.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.DescriptorSubstitutor; import org.jetbrains.jet.lang.types.DescriptorSubstitutor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor; import org.jetbrains.jet.lang.types.TypeSubstitutor;
@@ -13,6 +15,8 @@ import org.jetbrains.jet.lang.types.Variance;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
/** /**
* @author abreslav * @author abreslav
*/ */
@@ -21,7 +25,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
private List<TypeParameterDescriptor> typeParameters; private List<TypeParameterDescriptor> typeParameters;
private List<ValueParameterDescriptor> unsubstitutedValueParameters; private List<ValueParameterDescriptor> unsubstitutedValueParameters;
private JetType unsubstitutedReturnType; private JetType unsubstitutedReturnType;
private JetType receiverType; private ReceiverDescriptor receiver;
private Modality modality; private Modality modality;
private final Set<FunctionDescriptor> overriddenFunctions = Sets.newLinkedHashSet(); private final Set<FunctionDescriptor> overriddenFunctions = Sets.newLinkedHashSet();
@@ -49,11 +53,11 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters, @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
@Nullable JetType unsubstitutedReturnType, @Nullable JetType unsubstitutedReturnType,
@Nullable Modality modality) { @Nullable Modality modality) {
this.receiverType = receiverType;
this.typeParameters = typeParameters; this.typeParameters = typeParameters;
this.unsubstitutedValueParameters = unsubstitutedValueParameters; this.unsubstitutedValueParameters = unsubstitutedValueParameters;
this.unsubstitutedReturnType = unsubstitutedReturnType; this.unsubstitutedReturnType = unsubstitutedReturnType;
this.modality = modality; this.modality = modality;
this.receiver = receiverType == null ? NO_RECEIVER : new ExtensionReceiver(this, receiverType);
return this; return this;
} }
@@ -61,9 +65,10 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
this.unsubstitutedReturnType = unsubstitutedReturnType; this.unsubstitutedReturnType = unsubstitutedReturnType;
} }
@NotNull
@Override @Override
public JetType getReceiverType() { public ReceiverDescriptor getReceiver() {
return receiverType; return receiver;
} }
@NotNull @NotNull
@@ -116,10 +121,9 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
List<TypeParameterDescriptor> substitutedTypeParameters = Lists.newArrayList(); List<TypeParameterDescriptor> substitutedTypeParameters = Lists.newArrayList();
TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(getTypeParameters(), originalSubstitutor, substitutedDescriptor, substitutedTypeParameters); TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(getTypeParameters(), originalSubstitutor, substitutedDescriptor, substitutedTypeParameters);
JetType receiverType = getReceiverType();
JetType substitutedReceiverType = null; JetType substitutedReceiverType = null;
if (receiverType != null) { if (receiver != NO_RECEIVER) {
substitutedReceiverType = substitutor.substitute(receiverType, Variance.IN_VARIANCE); substitutedReceiverType = substitutor.substitute(getReceiver().getType(), Variance.IN_VARIANCE);
if (substitutedReceiverType == null) { if (substitutedReceiverType == null) {
return null; return null;
} }
@@ -5,11 +5,12 @@ import com.google.common.collect.HashBiMap;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
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.resolve.*; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.TraceBasedRedeclarationHandler;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionCallableReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import java.util.*; import java.util.*;
@@ -97,9 +98,9 @@ public class FunctionDescriptorUtil {
@NotNull @NotNull
public static JetScope getFunctionInnerScope(@NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) { public static JetScope getFunctionInnerScope(@NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) {
WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, new TraceBasedRedeclarationHandler(trace)).setDebugName("Function inner scope"); WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, new TraceBasedRedeclarationHandler(trace)).setDebugName("Function inner scope");
JetType receiverType = descriptor.getReceiverType(); ReceiverDescriptor receiver = descriptor.getReceiver();
if (receiverType != null) { if (receiver.exists()) {
parameterScope.setImplicitReceiver(new ExtensionCallableReceiver(descriptor)); parameterScope.setImplicitReceiver(receiver);
} }
for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) { for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
parameterScope.addTypeParameterDescriptor(typeParameter); parameterScope.addTypeParameterDescriptor(typeParameter);
@@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import java.util.Collection; import java.util.Collection;
@@ -94,6 +95,12 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
throw new UnsupportedOperationException(); // TODO throw new UnsupportedOperationException(); // TODO
} }
@NotNull
@Override
public ReceiverDescriptor getImplicitReceiver() {
throw new UnsupportedOperationException(); // TODO
}
@NotNull @NotNull
@Override @Override
public FunctionGroup getConstructors() { public FunctionGroup getConstructors() {
@@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.resolve.DescriptorRenderer; import org.jetbrains.jet.resolve.DescriptorRenderer;
@@ -38,6 +39,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
private JetType defaultType; private JetType defaultType;
private final ClassKind kind; private final ClassKind kind;
private JetType superclassType; private JetType superclassType;
private ClassReceiver implicitReceiver;
// public MutableClassDescriptor(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) { // public MutableClassDescriptor(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) {
// this(trace, containingDeclaration, outerScope, ClassKind.CLASS); // this(trace, containingDeclaration, outerScope, ClassKind.CLASS);
@@ -293,4 +295,13 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
public Collection<JetType> getSupertypes() { public Collection<JetType> getSupertypes() {
return supertypes; return supertypes;
} }
@NotNull
@Override
public ReceiverDescriptor getImplicitReceiver() {
if (implicitReceiver == null) {
implicitReceiver = new ClassReceiver(this);
}
return implicitReceiver;
}
} }
@@ -15,6 +15,7 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm
private final boolean hasBody; private final boolean hasBody;
private final boolean isDefault; private final boolean isDefault;
private final Modality modality; private final Modality modality;
private final PropertyDescriptor correspondingProperty;
protected PropertyAccessorDescriptor( protected PropertyAccessorDescriptor(
@NotNull Modality modality, @NotNull Modality modality,
@@ -24,6 +25,7 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm
boolean hasBody, boolean hasBody,
boolean isDefault) { boolean isDefault) {
super(correspondingProperty.getContainingDeclaration(), annotations, name); super(correspondingProperty.getContainingDeclaration(), annotations, name);
this.correspondingProperty = correspondingProperty;
this.modality = modality; this.modality = modality;
this.hasBody = hasBody; this.hasBody = hasBody;
this.isDefault = isDefault; this.isDefault = isDefault;
@@ -60,4 +62,9 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm
public Modality getModality() { public Modality getModality() {
return modality; return modality;
} }
@NotNull
public PropertyDescriptor getCorrespondingProperty() {
return correspondingProperty;
}
} }
@@ -4,6 +4,8 @@ import com.google.common.collect.Lists;
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.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor; import org.jetbrains.jet.lang.types.TypeSubstitutor;
import org.jetbrains.jet.lang.types.Variance; import org.jetbrains.jet.lang.types.Variance;
@@ -17,7 +19,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member
private final Modality modality; private final Modality modality;
private final boolean isVar; private final boolean isVar;
private final JetType receiverType; private final ReceiverDescriptor receiver;
private final List<TypeParameterDescriptor> typeParemeters = Lists.newArrayListWithCapacity(0); private final List<TypeParameterDescriptor> typeParemeters = Lists.newArrayListWithCapacity(0);
private final PropertyDescriptor original; private final PropertyDescriptor original;
private PropertyGetterDescriptor getter; private PropertyGetterDescriptor getter;
@@ -38,7 +40,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member
// assert outType != null; // assert outType != null;
this.isVar = isVar; this.isVar = isVar;
this.modality = modality; this.modality = modality;
this.receiverType = receiverType; this.receiver = receiverType == null ? ReceiverDescriptor.NO_RECEIVER : new ExtensionReceiver(this, receiverType);
this.original = original == null ? this : original.getOriginal(); this.original = original == null ? this : original.getOriginal();
} }
@@ -83,9 +85,9 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member
return typeParemeters; return typeParemeters;
} }
@Nullable @NotNull
public JetType getReceiverType() { public ReceiverDescriptor getReceiver() {
return receiverType; return receiver;
} }
@NotNull @NotNull
@@ -125,10 +127,9 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member
if (inType == null && outType == null) { if (inType == null && outType == null) {
return null; // TODO : tell the user that the property was projected out return null; // TODO : tell the user that the property was projected out
} }
JetType receiverType = getReceiverType();
return new PropertyDescriptor( return new PropertyDescriptor(
this, this,
receiverType == null ? null : substitutor.substitute(receiverType, Variance.IN_VARIANCE), receiver.exists() ? substitutor.substitute(receiver.getType(), Variance.IN_VARIANCE) : null,
inType, inType,
outType outType
); );
@@ -4,6 +4,7 @@ import com.google.common.collect.Sets;
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.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import java.util.Collections; import java.util.Collections;
@@ -32,9 +33,10 @@ public class PropertyGetterDescriptor extends PropertyAccessorDescriptor {
overriddenGetters.add(overriddenGetter); overriddenGetters.add(overriddenGetter);
} }
@NotNull
@Override @Override
public JetType getReceiverType() { public ReceiverDescriptor getReceiver() {
return null; // TODO return getCorrespondingProperty().getReceiver();
} }
@NotNull @NotNull
@@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
@@ -41,9 +42,10 @@ public class PropertySetterDescriptor extends PropertyAccessorDescriptor {
overriddenSetters.add(overriddenSetter); overriddenSetters.add(overriddenSetter);
} }
@NotNull
@Override @Override
public JetType getReceiverType() { public ReceiverDescriptor getReceiver() {
return null; // TODO return getCorrespondingProperty().getReceiver();
} }
@NotNull @NotNull
@@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.descriptors;
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.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import java.util.Collections; import java.util.Collections;
@@ -71,9 +72,10 @@ public abstract class VariableDescriptorImpl extends DeclarationDescriptorImpl i
return Collections.emptyList(); return Collections.emptyList();
} }
@NotNull
@Override @Override
public JetType getReceiverType() { public ReceiverDescriptor getReceiver() {
return null; return ReceiverDescriptor.NO_RECEIVER;
} }
@NotNull @NotNull
@@ -106,9 +106,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
COLON_AS(COLON, AS_KEYWORD, AS_SAFE) { COLON_AS(COLON, AS_KEYWORD, AS_SAFE) {
@Override @Override
public JetNodeType parseRightHandSide(IElementType operation, JetExpressionParsing parser) { public JetNodeType parseRightHandSide(IElementType operation, JetExpressionParsing parser) {
parser.myBuilder.disableJoiningComplexTokens();
parser.myJetParsing.parseTypeRef(); parser.myJetParsing.parseTypeRef();
parser.myBuilder.enableJoiningComplexTokens();
return BINARY_WITH_TYPE; return BINARY_WITH_TYPE;
} }
@@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetModifierList; import org.jetbrains.jet.lang.psi.JetModifierList;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeInferrer; import org.jetbrains.jet.lang.types.JetTypeInferrer;
@@ -46,7 +47,7 @@ public class AnnotationResolver {
} }
public void resolveAnnotationStub(@NotNull JetScope scope, @NotNull JetAnnotationEntry entryElement, @NotNull AnnotationDescriptor descriptor) { public void resolveAnnotationStub(@NotNull JetScope scope, @NotNull JetAnnotationEntry entryElement, @NotNull AnnotationDescriptor descriptor) {
JetType jetType = typeInferrer.getCallResolver().resolveCall(trace, scope, null, entryElement, NO_EXPECTED_TYPE); JetType jetType = typeInferrer.getCallResolver().resolveCall(trace, scope, ReceiverDescriptor.NO_RECEIVER, entryElement, NO_EXPECTED_TYPE);
descriptor.setAnnotationType(jetType == null ? ErrorUtils.createErrorType("Unresolved annotation type") : jetType); descriptor.setAnnotationType(jetType == null ? ErrorUtils.createErrorType("Unresolved annotation type") : jetType);
} }
@@ -8,6 +8,7 @@ import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.util.slicedmap.*; import org.jetbrains.jet.util.slicedmap.*;
@@ -17,6 +18,8 @@ import java.util.Collection;
* @author abreslav * @author abreslav
*/ */
public interface BindingContext { public interface BindingContext {
WritableSlice<JetElement, ReceiverDescriptor> RECEIVER = Slices.createSimpleSlice("RECEIVER");
WritableSlice<JetAnnotationEntry, AnnotationDescriptor> ANNOTATION = Slices.createSimpleSlice("ANNOTATION"); WritableSlice<JetAnnotationEntry, AnnotationDescriptor> ANNOTATION = Slices.createSimpleSlice("ANNOTATION");
WritableSlice<JetExpression, CompileTimeConstant<?>> COMPILE_TIME_VALUE = Slices.createSimpleSlice("COMPILE_TIME_VALUE"); WritableSlice<JetExpression, CompileTimeConstant<?>> COMPILE_TIME_VALUE = Slices.createSimpleSlice("COMPILE_TIME_VALUE");
WritableSlice<JetTypeReference, JetType> TYPE = Slices.createSimpleSlice("TYPE"); WritableSlice<JetTypeReference, JetType> TYPE = Slices.createSimpleSlice("TYPE");
@@ -13,7 +13,7 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionCallableReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.util.slicedmap.WritableSlice; import org.jetbrains.jet.util.slicedmap.WritableSlice;
@@ -275,7 +275,7 @@ public class BodyResolver {
JetTypeReference typeReference = call.getTypeReference(); JetTypeReference typeReference = call.getTypeReference();
if (typeReference != null) { if (typeReference != null) {
if (descriptor.getUnsubstitutedPrimaryConstructor() != null) { if (descriptor.getUnsubstitutedPrimaryConstructor() != null) {
JetType supertype = typeInferrer.getCallResolver().resolveCall(context.getTrace(), scopeForConstructor, null, call, NO_EXPECTED_TYPE); JetType supertype = typeInferrer.getCallResolver().resolveCall(context.getTrace(), scopeForConstructor, ReceiverDescriptor.NO_RECEIVER, call, NO_EXPECTED_TYPE);
if (supertype != null) { if (supertype != null) {
recordSupertype(typeReference, supertype); recordSupertype(typeReference, supertype);
ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype); ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
@@ -460,7 +460,7 @@ public class BodyResolver {
typeInferrerForInitializers.getCallResolver().resolveCall(context.getTrace(), typeInferrerForInitializers.getCallResolver().resolveCall(context.getTrace(),
functionInnerScope, functionInnerScope,
null, call, NO_EXPECTED_TYPE); ReceiverDescriptor.NO_RECEIVER, call, NO_EXPECTED_TYPE);
// call.getThisReference(), // call.getThisReference(),
// classDescriptor, // classDescriptor,
// classDescriptor.getDefaultType(), // classDescriptor.getDefaultType(),
@@ -575,9 +575,9 @@ public class BodyResolver {
for (TypeParameterDescriptor typeParameterDescriptor : propertyDescriptor.getTypeParameters()) { for (TypeParameterDescriptor typeParameterDescriptor : propertyDescriptor.getTypeParameters()) {
result.addTypeParameterDescriptor(typeParameterDescriptor); result.addTypeParameterDescriptor(typeParameterDescriptor);
} }
JetType receiverType = propertyDescriptor.getReceiverType(); ReceiverDescriptor receiver = propertyDescriptor.getReceiver();
if (receiverType != null) { if (receiver.exists()) {
result.setImplicitReceiver(new ExtensionCallableReceiver(propertyDescriptor)); result.setImplicitReceiver(receiver);
} }
return result; return result;
} }
@@ -799,15 +799,15 @@ public class BodyResolver {
boolean inTrait = classDescriptor.getKind() == ClassKind.TRAIT; boolean inTrait = classDescriptor.getKind() == ClassKind.TRAIT;
boolean inEnum = classDescriptor.getKind() == ClassKind.ENUM_CLASS; boolean inEnum = classDescriptor.getKind() == ClassKind.ENUM_CLASS;
boolean inAbstractClass = classDescriptor.getModality() == Modality.ABSTRACT; boolean inAbstractClass = classDescriptor.getModality() == Modality.ABSTRACT;
PsiElement classElement = context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor);
assert classElement instanceof JetModifierListOwner;
if (hasAbstractModifier && !inAbstractClass && !inTrait && !inEnum) { if (hasAbstractModifier && !inAbstractClass && !inTrait && !inEnum) {
PsiElement classElement = context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor);
assert classElement instanceof JetModifierListOwner;
context.getTrace().report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(functionOrPropertyAccessor, abstractNode, functionDescriptor.getName(), classDescriptor, (JetModifierListOwner) classElement)); context.getTrace().report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(functionOrPropertyAccessor, abstractNode, functionDescriptor.getName(), classDescriptor, (JetModifierListOwner) classElement));
} }
if (hasAbstractModifier && inTrait && !isPropertyAccessor) { if (hasAbstractModifier && inTrait && !isPropertyAccessor) {
context.getTrace().report(REDUNDANT_ABSTRACT.on(functionOrPropertyAccessor, abstractNode)); context.getTrace().report(REDUNDANT_ABSTRACT.on(functionOrPropertyAccessor, abstractNode));
} }
if (function.getBodyExpression() != null && hasAbstractModifier) { //TODO if (function.getBodyExpression() != null && hasAbstractModifier) {
context.getTrace().report(ABSTRACT_FUNCTION_WITH_BODY.on(functionOrPropertyAccessor, abstractNode, functionDescriptor)); context.getTrace().report(ABSTRACT_FUNCTION_WITH_BODY.on(functionOrPropertyAccessor, abstractNode, functionDescriptor));
} }
if (function.getBodyExpression() == null && !hasAbstractModifier && !inTrait && nameIdentifier != null && !isPropertyAccessor) { if (function.getBodyExpression() == null && !hasAbstractModifier && !inTrait && nameIdentifier != null && !isPropertyAccessor) {
@@ -21,7 +21,7 @@ public class DescriptorUtils {
@Override @Override
public Boolean visitFunctionDescriptor(FunctionDescriptor descriptor, Void data) { public Boolean visitFunctionDescriptor(FunctionDescriptor descriptor, Void data) {
return descriptor.getReceiverType() != null; return descriptor.getReceiver().exists();
} }
@Override @Override
@@ -31,7 +31,7 @@ public class DescriptorUtils {
@Override @Override
public Boolean visitPropertyDescriptor(PropertyDescriptor descriptor, Void data) { public Boolean visitPropertyDescriptor(PropertyDescriptor descriptor, Void data) {
return descriptor.getReceiverType() != null; return descriptor.getReceiver().exists();
} }
}, null); }, null);
} }
@@ -13,6 +13,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.inference.ConstraintSystem; import org.jetbrains.jet.lang.types.inference.ConstraintSystem;
@@ -20,7 +21,9 @@ import java.util.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET; import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET;
import static org.jetbrains.jet.lang.resolve.BindingContext.RECEIVER;
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE; import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
/** /**
@@ -42,11 +45,11 @@ public class CallResolver {
public VariableDescriptor resolveSimpleProperty( public VariableDescriptor resolveSimpleProperty(
@NotNull BindingTrace trace, @NotNull BindingTrace trace,
@NotNull JetScope scope, @NotNull JetScope scope,
@Nullable JetType receiverType, @NotNull ReceiverDescriptor receiver,
@NotNull final JetSimpleNameExpression nameExpression, @NotNull final JetSimpleNameExpression nameExpression,
@NotNull JetType expectedType) { @NotNull JetType expectedType) {
Call call = CallMaker.makePropertyCall(nameExpression); Call call = CallMaker.makePropertyCall(nameExpression);
List<ResolutionTask<VariableDescriptor>> prioritizedTasks = PROPERTY_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiverType, call, nameExpression.getReferencedName()); List<ResolutionTask<VariableDescriptor>> prioritizedTasks = PROPERTY_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiver, call, nameExpression.getReferencedName());
return resolveCallToDescriptor(trace, scope, call, nameExpression.getNode(), expectedType, prioritizedTasks, nameExpression); return resolveCallToDescriptor(trace, scope, call, nameExpression.getNode(), expectedType, prioritizedTasks, nameExpression);
} }
@@ -55,11 +58,11 @@ public class CallResolver {
public JetType resolveCall( public JetType resolveCall(
@NotNull BindingTrace trace, @NotNull BindingTrace trace,
@NotNull JetScope scope, @NotNull JetScope scope,
@Nullable JetType receiverType, @NotNull ReceiverDescriptor receiver,
@NotNull JetCallElement call, @NotNull JetCallElement call,
@NotNull JetType expectedType @NotNull JetType expectedType
) { ) {
FunctionDescriptor functionDescriptor = resolveSimpleCallToFunctionDescriptor(trace, scope, receiverType, call, expectedType); FunctionDescriptor functionDescriptor = resolveSimpleCallToFunctionDescriptor(trace, scope, receiver, call, expectedType);
return functionDescriptor == null ? null : functionDescriptor.getReturnType(); return functionDescriptor == null ? null : functionDescriptor.getReturnType();
} }
@@ -70,11 +73,11 @@ public class CallResolver {
@NotNull final Call call, @NotNull final Call call,
@NotNull final JetReferenceExpression functionReference, @NotNull final JetReferenceExpression functionReference,
@NotNull String name, @NotNull String name,
@Nullable JetType receiverType, @NotNull ReceiverDescriptor receiver,
@NotNull JetType expectedType) { @NotNull JetType expectedType) {
// TODO : autocasts // TODO : autocasts
// TODO : nullability // TODO : nullability
List<ResolutionTask<FunctionDescriptor>> tasks = FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiverType, call, name); List<ResolutionTask<FunctionDescriptor>> tasks = FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiver, call, name);
return resolveCallToDescriptor(trace, scope, call, functionReference.getNode(), expectedType, tasks, functionReference); return resolveCallToDescriptor(trace, scope, call, functionReference.getNode(), expectedType, tasks, functionReference);
} }
@@ -82,7 +85,7 @@ public class CallResolver {
public FunctionDescriptor resolveSimpleCallToFunctionDescriptor( public FunctionDescriptor resolveSimpleCallToFunctionDescriptor(
@NotNull BindingTrace trace, @NotNull BindingTrace trace,
@NotNull JetScope scope, @NotNull JetScope scope,
@Nullable JetType receiverType, @NotNull ReceiverDescriptor receiver,
@NotNull final JetCallElement call, @NotNull final JetCallElement call,
@NotNull JetType expectedType @NotNull JetType expectedType
) { ) {
@@ -97,7 +100,7 @@ public class CallResolver {
String name = expression.getReferencedName(); String name = expression.getReferencedName();
if (name == null) return checkArgumentTypesAndFail(trace, scope, call); if (name == null) return checkArgumentTypesAndFail(trace, scope, call);
prioritizedTasks = FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiverType, call, name); prioritizedTasks = FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiver, call, name);
ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() { ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() {
@Override @Override
public <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) { public <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
@@ -120,7 +123,7 @@ public class CallResolver {
JetValueArgumentList valueArgumentList = call.getValueArgumentList(); JetValueArgumentList valueArgumentList = call.getValueArgumentList();
ASTNode reportAbsenceOn = valueArgumentList == null ? call.getNode() : valueArgumentList.getNode(); ASTNode reportAbsenceOn = valueArgumentList == null ? call.getNode() : valueArgumentList.getNode();
if (calleeExpression instanceof JetConstructorCalleeExpression) { if (calleeExpression instanceof JetConstructorCalleeExpression) {
assert receiverType == null; assert receiver == NO_RECEIVER;
prioritizedTasks = Lists.newArrayList(); prioritizedTasks = Lists.newArrayList();
@@ -141,7 +144,7 @@ public class CallResolver {
trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
return checkArgumentTypesAndFail(trace, scope, call); return checkArgumentTypesAndFail(trace, scope, call);
} }
prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(constructors, null, call)); prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(constructors, NO_RECEIVER, call));
} }
else { else {
// trace.getErrorHandler().genericError(calleeExpression.getNode(), "Not a class"); // trace.getErrorHandler().genericError(calleeExpression.getNode(), "Not a class");
@@ -162,7 +165,7 @@ public class CallResolver {
trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
return checkArgumentTypesAndFail(trace, scope, call); return checkArgumentTypesAndFail(trace, scope, call);
} }
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(constructors, null, call)); prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(constructors, NO_RECEIVER, call));
} }
else { else {
throw new UnsupportedOperationException("Type argument inference not implemented for " + call.getText()); throw new UnsupportedOperationException("Type argument inference not implemented for " + call.getText());
@@ -190,45 +193,11 @@ public class CallResolver {
OverloadResolutionResult<D> resultForFirstNonemptyCandidateSet = null; OverloadResolutionResult<D> resultForFirstNonemptyCandidateSet = null;
TracingStrategy tracing = new TracingStrategy() { TracingStrategy tracing = new TracingStrategy() {
@Override @Override
public void bindReference(@NotNull BindingTrace trace, @NotNull CallableDescriptor descriptor) { public void bindReference(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiver, @NotNull CallableDescriptor descriptor) {
trace.record(REFERENCE_TARGET, reference, descriptor); trace.record(REFERENCE_TARGET, reference, descriptor);
trace.record(RECEIVER, reference, receiver);
} }
// public void reportOverallResolutionError(@NotNull BindingTrace trace, @NotNull String message) {
// trace.getErrorHandler().genericError(callNode, message);
// }
//
// public void reportWrongTypeArguments(@NotNull BindingTrace trace, @NotNull String message) {
// JetTypeArgumentList typeArgumentList = call.getTypeArgumentList();
// if (typeArgumentList != null) {
// trace.getErrorHandler().genericError(typeArgumentList.getNode(), message);
// }
// else {
// reportOverallResolutionError(trace, message);
// }
// }
//
// public void reportWrongValueArguments(@NotNull BindingTrace trace, @NotNull String message) {
// ASTNode node;
//
// JetValueArgumentList valueArgumentList = call.getValueArgumentList();
// if (valueArgumentList != null) {
// node = valueArgumentList.getNode();
// }
// else if (!call.getFunctionLiteralArguments().isEmpty()) {
// node = call.getFunctionLiteralArguments().get(0).getNode();
// }
// else {
// node = callNode;
// }
//
// trace.getErrorHandler().genericError(node, message);
// }
//
// public void reportErrorOnReference(BindingTrace trace, String message) {
// trace.getErrorHandler().genericError(reference.getNode(), message);
// }
@Override @Override
public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<D> candidates) { public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<D> candidates) {
trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, candidates); trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, candidates);
@@ -257,8 +226,8 @@ public class CallResolver {
} }
@Override @Override
public void missingReceiver(@NotNull BindingTrace trace, @NotNull JetType candidateReceiverType) { public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver) {
trace.report(MISSING_RECEIVER.on(reference, candidateReceiverType)); trace.report(MISSING_RECEIVER.on(reference, expectedReceiver.getType()));
} }
@Override @Override
@@ -340,7 +309,7 @@ public class CallResolver {
traces.put(candidate, temporaryTrace); traces.put(candidate, temporaryTrace);
JetTypeInferrer.Services temporaryServices = typeInferrer.getServices(temporaryTrace); JetTypeInferrer.Services temporaryServices = typeInferrer.getServices(temporaryTrace);
tracing.bindReference(temporaryTrace, candidate); tracing.bindReference(temporaryTrace, task.getReceiver(), candidate);
if (ErrorUtils.isError(candidate)) { if (ErrorUtils.isError(candidate)) {
successfulCandidates.put(candidate, candidate); successfulCandidates.put(candidate, candidate);
@@ -394,10 +363,10 @@ public class CallResolver {
checkReceiverAbsence(task, tracing, candidate, temporaryTrace); checkReceiverAbsence(task, tracing, candidate, temporaryTrace);
// Error is already reported if something is missing // Error is already reported if something is missing
JetType receiverType = task.getReceiverType(); ReceiverDescriptor receiver = task.getReceiver();
JetType candidateReceiverType = candidate.getReceiverType(); ReceiverDescriptor candidateReceiver = candidate.getReceiver();
if (receiverType != null && candidateReceiverType != null) { if (receiver != NO_RECEIVER && candidateReceiver != NO_RECEIVER) {
constraintSystem.addSubtypingConstraint(receiverType, candidateReceiverType); constraintSystem.addSubtypingConstraint(receiver.getType(), candidateReceiver.getType());
} }
if (expectedType != NO_EXPECTED_TYPE) { if (expectedType != NO_EXPECTED_TYPE) {
@@ -508,28 +477,28 @@ public class CallResolver {
private <D extends CallableDescriptor> boolean checkReceiver(ResolutionTask<D> task, TracingStrategy tracing, D candidate, TemporaryBindingTrace temporaryTrace) { private <D extends CallableDescriptor> boolean checkReceiver(ResolutionTask<D> task, TracingStrategy tracing, D candidate, TemporaryBindingTrace temporaryTrace) {
if (!checkReceiverAbsence(task, tracing, candidate, temporaryTrace)) return false; if (!checkReceiverAbsence(task, tracing, candidate, temporaryTrace)) return false;
JetType receiverType = task.getReceiverType(); ReceiverDescriptor receiver = task.getReceiver();
JetType candidateReceiverType = candidate.getReceiverType(); ReceiverDescriptor candidateReceiver = candidate.getReceiver();
if (receiverType != null if (receiver != NO_RECEIVER
&& candidateReceiverType != null && candidateReceiver != NO_RECEIVER
&& !semanticServices.getTypeChecker().isSubtypeOf(receiverType, candidateReceiverType)) { && !semanticServices.getTypeChecker().isSubtypeOf(receiver.getType(), candidateReceiver.getType())) {
tracing.missingReceiver(temporaryTrace, candidateReceiverType); tracing.missingReceiver(temporaryTrace, candidateReceiver);
return false; return false;
} }
return true; return true;
} }
private <D extends CallableDescriptor> boolean checkReceiverAbsence(ResolutionTask<D> task, TracingStrategy tracing, D candidate, TemporaryBindingTrace temporaryTrace) { private <D extends CallableDescriptor> boolean checkReceiverAbsence(ResolutionTask<D> task, TracingStrategy tracing, D candidate, TemporaryBindingTrace temporaryTrace) {
JetType receiverType = task.getReceiverType(); ReceiverDescriptor receiver = task.getReceiver();
JetType candidateReceiverType = candidate.getReceiverType(); ReceiverDescriptor candidateReceiver = candidate.getReceiver();
if (receiverType != null) { if (receiver != NO_RECEIVER) {
if (candidateReceiverType == null) { if (candidateReceiver == NO_RECEIVER) {
tracing.noReceiverAllowed(temporaryTrace); tracing.noReceiverAllowed(temporaryTrace);
return false; return false;
} }
} }
else if (candidateReceiverType != null) { else if (candidateReceiver != NO_RECEIVER) {
tracing.missingReceiver(temporaryTrace, candidateReceiverType); tracing.missingReceiver(temporaryTrace, candidateReceiver);
return false; return false;
} }
return true; return true;
@@ -658,8 +627,8 @@ public class CallResolver {
} }
@NotNull @NotNull
public OverloadResolutionResult<FunctionDescriptor> resolveExactSignature(@NotNull JetScope scope, @Nullable JetType receiverType, @NotNull String name, @NotNull List<JetType> parameterTypes) { public OverloadResolutionResult<FunctionDescriptor> resolveExactSignature(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, @NotNull String name, @NotNull List<JetType> parameterTypes) {
List<FunctionDescriptor> result = findCandidatesByExactSignature(scope, receiverType, name, parameterTypes); List<FunctionDescriptor> result = findCandidatesByExactSignature(scope, receiver, name, parameterTypes);
BindingTraceContext trace = new BindingTraceContext(); BindingTraceContext trace = new BindingTraceContext();
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(trace); TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(trace);
@@ -672,25 +641,25 @@ public class CallResolver {
return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, candidates, Collections.<FunctionDescriptor>emptySet(), Collections.<FunctionDescriptor>emptySet(), traces); return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, candidates, Collections.<FunctionDescriptor>emptySet(), Collections.<FunctionDescriptor>emptySet(), traces);
} }
private List<FunctionDescriptor> findCandidatesByExactSignature(JetScope scope, JetType receiverType, String name, List<JetType> parameterTypes) { private List<FunctionDescriptor> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver, String name, List<JetType> parameterTypes) {
List<FunctionDescriptor> result = Lists.newArrayList(); List<FunctionDescriptor> result = Lists.newArrayList();
if (receiverType != null) { if (receiver != NO_RECEIVER) {
Set<FunctionDescriptor> extensionFunctionDescriptors = scope.getFunctionGroup(name).getFunctionDescriptors(); Set<FunctionDescriptor> extensionFunctionDescriptors = scope.getFunctionGroup(name).getFunctionDescriptors();
List<FunctionDescriptor> nonlocal = Lists.newArrayList(); List<FunctionDescriptor> nonlocal = Lists.newArrayList();
List<FunctionDescriptor> local = Lists.newArrayList(); List<FunctionDescriptor> local = Lists.newArrayList();
TaskPrioritizer.splitLexicallyLocalDescriptors(extensionFunctionDescriptors, scope.getContainingDeclaration(), local, nonlocal); TaskPrioritizer.splitLexicallyLocalDescriptors(extensionFunctionDescriptors, scope.getContainingDeclaration(), local, nonlocal);
if (findExtensionFunctions(local, receiverType, parameterTypes, result)) { if (findExtensionFunctions(local, receiver, parameterTypes, result)) {
return result; return result;
} }
Set<FunctionDescriptor> functionDescriptors = receiverType.getMemberScope().getFunctionGroup(name).getFunctionDescriptors(); Set<FunctionDescriptor> functionDescriptors = receiver.getType().getMemberScope().getFunctionGroup(name).getFunctionDescriptors();
if (lookupExactSignature(functionDescriptors, parameterTypes, result)) { if (lookupExactSignature(functionDescriptors, parameterTypes, result)) {
return result; return result;
} }
findExtensionFunctions(nonlocal, receiverType, parameterTypes, result); findExtensionFunctions(nonlocal, receiver, parameterTypes, result);
return result; return result;
} }
else { else {
@@ -702,7 +671,7 @@ public class CallResolver {
private boolean lookupExactSignature(Set<FunctionDescriptor> candidates, List<JetType> parameterTypes, List<FunctionDescriptor> result) { private boolean lookupExactSignature(Set<FunctionDescriptor> candidates, List<JetType> parameterTypes, List<FunctionDescriptor> result) {
boolean found = false; boolean found = false;
for (FunctionDescriptor functionDescriptor : candidates) { for (FunctionDescriptor functionDescriptor : candidates) {
if (functionDescriptor.getReceiverType() != null) continue; if (functionDescriptor.getReceiver() != NO_RECEIVER) continue;
if (!functionDescriptor.getTypeParameters().isEmpty()) continue; if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
if (!checkValueParameters(functionDescriptor, parameterTypes)) continue; if (!checkValueParameters(functionDescriptor, parameterTypes)) continue;
result.add(functionDescriptor); result.add(functionDescriptor);
@@ -711,13 +680,13 @@ public class CallResolver {
return found; return found;
} }
private boolean findExtensionFunctions(Collection<FunctionDescriptor> candidates, JetType receiverType, List<JetType> parameterTypes, List<FunctionDescriptor> result) { private boolean findExtensionFunctions(Collection<FunctionDescriptor> candidates, ReceiverDescriptor receiver, List<JetType> parameterTypes, List<FunctionDescriptor> result) {
boolean found = false; boolean found = false;
for (FunctionDescriptor functionDescriptor : candidates) { for (FunctionDescriptor functionDescriptor : candidates) {
JetType functionReceiverType = functionDescriptor.getReceiverType(); ReceiverDescriptor functionReceiver = functionDescriptor.getReceiver();
if (functionReceiverType == null) continue; if (functionReceiver == NO_RECEIVER) continue;
if (!functionDescriptor.getTypeParameters().isEmpty()) continue; if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
if (!semanticServices.getTypeChecker().isSubtypeOf(receiverType, functionReceiverType)) continue; if (!semanticServices.getTypeChecker().isSubtypeOf(receiver.getType(), functionReceiver.getType())) continue;
if (!checkValueParameters(functionDescriptor, parameterTypes))continue; if (!checkValueParameters(functionDescriptor, parameterTypes))continue;
result.add(functionDescriptor); result.add(functionDescriptor);
found = true; found = true;
@@ -744,7 +713,7 @@ public class CallResolver {
Set<FunctionDescriptor> functions = Sets.newLinkedHashSet(scope.getFunctionGroup(name).getFunctionDescriptors()); Set<FunctionDescriptor> functions = Sets.newLinkedHashSet(scope.getFunctionGroup(name).getFunctionDescriptors());
for (Iterator<FunctionDescriptor> iterator = functions.iterator(); iterator.hasNext(); ) { for (Iterator<FunctionDescriptor> iterator = functions.iterator(); iterator.hasNext(); ) {
FunctionDescriptor functionDescriptor = iterator.next(); FunctionDescriptor functionDescriptor = iterator.next();
if (functionDescriptor.getReceiverType() != null) { if (functionDescriptor.getReceiver() != NO_RECEIVER) {
iterator.remove(); iterator.remove();
} }
} }
@@ -756,10 +725,11 @@ public class CallResolver {
@NotNull @NotNull
@Override @Override
protected Collection<FunctionDescriptor> getMembersByName(@NotNull JetType receiverType, String name) { protected Collection<FunctionDescriptor> getMembersByName(@NotNull ReceiverDescriptor receiver, String name) {
Set<FunctionDescriptor> members = Sets.newHashSet(receiverType.getMemberScope().getFunctionGroup(name).getFunctionDescriptors()); JetScope receiverScope = receiver.getType().getMemberScope();
addConstructors(receiverType.getMemberScope(), name, members); Set<FunctionDescriptor> members = Sets.newHashSet(receiverScope.getFunctionGroup(name).getFunctionDescriptors());
addVariableAsFunction(receiverType.getMemberScope(), name, members, false); addConstructors(receiverScope, name, members);
addVariableAsFunction(receiverScope, name, members, false);
return members; return members;
} }
@@ -769,7 +739,7 @@ public class CallResolver {
Set<FunctionDescriptor> extensionFunctions = Sets.newHashSet(scope.getFunctionGroup(name).getFunctionDescriptors()); Set<FunctionDescriptor> extensionFunctions = Sets.newHashSet(scope.getFunctionGroup(name).getFunctionDescriptors());
for (Iterator<FunctionDescriptor> iterator = extensionFunctions.iterator(); iterator.hasNext(); ) { for (Iterator<FunctionDescriptor> iterator = extensionFunctions.iterator(); iterator.hasNext(); ) {
FunctionDescriptor descriptor = iterator.next(); FunctionDescriptor descriptor = iterator.next();
if (descriptor.getReceiverType() == null) { if (descriptor.getReceiver() == NO_RECEIVER) {
iterator.remove(); iterator.remove();
} }
} }
@@ -779,8 +749,8 @@ public class CallResolver {
@NotNull @NotNull
@Override @Override
protected ResolutionTask<FunctionDescriptor> createTask(JetType receiverType, Call call, Collection<FunctionDescriptor> candidates) { protected ResolutionTask<FunctionDescriptor> createTask(@NotNull ReceiverDescriptor receiver, Call call, Collection<FunctionDescriptor> candidates) {
return new ResolutionTask<FunctionDescriptor>(candidates, receiverType, call); return new ResolutionTask<FunctionDescriptor>(candidates, receiver, call);
} }
private void addConstructors(JetScope scope, String name, Collection<FunctionDescriptor> functions) { private void addConstructors(JetScope scope, String name, Collection<FunctionDescriptor> functions) {
@@ -793,11 +763,11 @@ public class CallResolver {
private void addVariableAsFunction(JetScope scope, String name, Set<FunctionDescriptor> functions, boolean receiverNeeded) { private void addVariableAsFunction(JetScope scope, String name, Set<FunctionDescriptor> functions, boolean receiverNeeded) {
VariableDescriptor variable = scope.getVariable(name); VariableDescriptor variable = scope.getVariable(name);
if (variable != null && variable.getReceiverType() == null) { if (variable != null && variable.getReceiver() == NO_RECEIVER) {
JetType outType = variable.getOutType(); JetType outType = variable.getOutType();
if (outType != null && JetStandardClasses.isFunctionType(outType)) { if (outType != null && JetStandardClasses.isFunctionType(outType)) {
VariableAsFunctionDescriptor functionDescriptor = VariableAsFunctionDescriptor.create(variable); VariableAsFunctionDescriptor functionDescriptor = VariableAsFunctionDescriptor.create(variable);
if ((functionDescriptor.getReceiverType() != null) == receiverNeeded) { if ((functionDescriptor.getReceiver() != NO_RECEIVER) == receiverNeeded) {
functions.add(functionDescriptor); functions.add(functionDescriptor);
} }
} }
@@ -811,7 +781,7 @@ public class CallResolver {
@Override @Override
protected Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String name) { protected Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String name) {
VariableDescriptor variable = scope.getVariable(name); VariableDescriptor variable = scope.getVariable(name);
if (variable != null && variable.getReceiverType() == null) { if (variable != null && variable.getReceiver() == NO_RECEIVER) {
return Collections.singleton(variable); return Collections.singleton(variable);
} }
return Collections.emptyList(); return Collections.emptyList();
@@ -819,8 +789,8 @@ public class CallResolver {
@NotNull @NotNull
@Override @Override
protected Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiverType, String name) { protected Collection<VariableDescriptor> getMembersByName(@NotNull ReceiverDescriptor receiver, String name) {
VariableDescriptor variable = receiverType.getMemberScope().getVariable(name); VariableDescriptor variable = receiver.getType().getMemberScope().getVariable(name);
if (variable != null) { if (variable != null) {
return Collections.singleton(variable); return Collections.singleton(variable);
} }
@@ -831,7 +801,7 @@ public class CallResolver {
@Override @Override
protected Collection<VariableDescriptor> getExtensionsByName(JetScope scope, String name) { protected Collection<VariableDescriptor> getExtensionsByName(JetScope scope, String name) {
VariableDescriptor variable = scope.getVariable(name); VariableDescriptor variable = scope.getVariable(name);
if (variable != null && variable.getReceiverType() != null) { if (variable != null && variable.getReceiver() != NO_RECEIVER) {
return Collections.singleton(variable); return Collections.singleton(variable);
} }
return Collections.emptyList(); return Collections.emptyList();
@@ -839,8 +809,8 @@ public class CallResolver {
@NotNull @NotNull
@Override @Override
protected ResolutionTask<VariableDescriptor> createTask(JetType receiverType, Call call, Collection<VariableDescriptor> candidates) { protected ResolutionTask<VariableDescriptor> createTask(@NotNull ReceiverDescriptor receiver, Call call, Collection<VariableDescriptor> candidates) {
return new ResolutionTask<VariableDescriptor>(candidates, receiverType, call); return new ResolutionTask<VariableDescriptor>(candidates, receiver, call);
} }
}; };
@@ -9,6 +9,7 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetStandardLibrary; import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
@@ -59,10 +60,10 @@ import java.util.Set;
if (overrides(f, g)) return true; if (overrides(f, g)) return true;
if (overrides(g, f)) return false; if (overrides(g, f)) return false;
JetType receiverTypeOfF = f.getReceiverType(); ReceiverDescriptor receiverOfF = f.getReceiver();
JetType receiverTypeOfG = g.getReceiverType(); ReceiverDescriptor receiverOfG = g.getReceiver();
if (receiverTypeOfF != null && receiverTypeOfG != null) { if (f.getReceiver().exists() && g.getReceiver().exists()) {
if (!typeMoreSpecific(receiverTypeOfF, receiverTypeOfG)) return false; if (!typeMoreSpecific(receiverOfF.getType(), receiverOfG.getType())) return false;
} }
List<ValueParameterDescriptor> fParams = f.getValueParameters(); List<ValueParameterDescriptor> fParams = f.getValueParameters();
@@ -8,9 +8,9 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetTypeProjection; import org.jetbrains.jet.lang.psi.JetTypeProjection;
import org.jetbrains.jet.lang.psi.ValueArgument; import org.jetbrains.jet.lang.psi.ValueArgument;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@@ -19,7 +19,7 @@ import java.util.List;
*/ */
/*package*/ class ResolutionTask<Descriptor extends CallableDescriptor> { /*package*/ class ResolutionTask<Descriptor extends CallableDescriptor> {
private final Collection<Descriptor> candidates; private final Collection<Descriptor> candidates;
private final JetType receiverType; private final ReceiverDescriptor receiver;
private final List<JetTypeProjection> typeArguments; private final List<JetTypeProjection> typeArguments;
private final List<? extends ValueArgument> valueArguments; private final List<? extends ValueArgument> valueArguments;
private final List<JetExpression> functionLiteralArguments; private final List<JetExpression> functionLiteralArguments;
@@ -27,12 +27,12 @@ import java.util.List;
public ResolutionTask( public ResolutionTask(
@NotNull Collection<Descriptor> candidates, @NotNull Collection<Descriptor> candidates,
@Nullable JetType receiverType, @NotNull ReceiverDescriptor receiver,
@NotNull List<JetTypeProjection> typeArguments, @NotNull List<JetTypeProjection> typeArguments,
@NotNull List<? extends ValueArgument> valueArguments, @NotNull List<? extends ValueArgument> valueArguments,
@NotNull List<JetExpression> functionLiteralArguments) { @NotNull List<JetExpression> functionLiteralArguments) {
this.candidates = candidates; this.candidates = candidates;
this.receiverType = receiverType; this.receiver = receiver;
this.typeArguments = typeArguments; this.typeArguments = typeArguments;
this.valueArguments = valueArguments; this.valueArguments = valueArguments;
this.functionLiteralArguments = functionLiteralArguments; this.functionLiteralArguments = functionLiteralArguments;
@@ -40,10 +40,10 @@ import java.util.List;
public ResolutionTask( public ResolutionTask(
@NotNull Collection<Descriptor> candidates, @NotNull Collection<Descriptor> candidates,
@Nullable JetType receiverType, @NotNull ReceiverDescriptor receiver,
@NotNull Call call @NotNull Call call
) { ) {
this(candidates, receiverType, call.getTypeArguments(), call.getValueArguments(), call.getFunctionLiteralArguments()); this(candidates, receiver, call.getTypeArguments(), call.getValueArguments(), call.getFunctionLiteralArguments());
} }
@NotNull @NotNull
@@ -51,9 +51,9 @@ import java.util.List;
return candidates; return candidates;
} }
@Nullable @NotNull
public JetType getReceiverType() { public ReceiverDescriptor getReceiver() {
return receiverType; return receiver;
} }
@NotNull @NotNull
@@ -2,7 +2,6 @@ package org.jetbrains.jet.lang.resolve.calls;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
@@ -10,7 +9,6 @@ import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.Call; import org.jetbrains.jet.lang.psi.Call;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@@ -64,33 +62,33 @@ import java.util.List;
return false; return false;
} }
public List<ResolutionTask<D>> computePrioritizedTasks(@NotNull JetScope scope, @Nullable JetType receiverType, @NotNull Call call, @NotNull String name) { public List<ResolutionTask<D>> computePrioritizedTasks(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, @NotNull Call call, @NotNull String name) {
List<ResolutionTask<D>> result = Lists.newArrayList(); List<ResolutionTask<D>> result = Lists.newArrayList();
doComputeTasks(scope, receiverType, call, name, result); doComputeTasks(scope, receiver, call, name, result);
return result; return result;
} }
private void doComputeTasks(JetScope scope, JetType receiverType, Call call, String name, List<ResolutionTask<D>> result) { private void doComputeTasks(JetScope scope, ReceiverDescriptor receiver, Call call, String name, List<ResolutionTask<D>> result) {
List<ReceiverDescriptor> receivers = Lists.newArrayList(); List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList();
scope.getImplicitReceiversHierarchy(receivers); scope.getImplicitReceiversHierarchy(implicitReceivers);
if (receiverType != null) { if (receiver != ReceiverDescriptor.NO_RECEIVER) {
Collection<D> extensionFunctions = getExtensionsByName(scope, name); Collection<D> extensionFunctions = getExtensionsByName(scope, name);
List<D> nonlocals = Lists.newArrayList(); List<D> nonlocals = Lists.newArrayList();
List<D> locals = Lists.newArrayList(); List<D> locals = Lists.newArrayList();
//noinspection unchecked,RedundantTypeArguments //noinspection unchecked,RedundantTypeArguments
TaskPrioritizer.<D>splitLexicallyLocalDescriptors(extensionFunctions, scope.getContainingDeclaration(), locals, nonlocals); TaskPrioritizer.<D>splitLexicallyLocalDescriptors(extensionFunctions, scope.getContainingDeclaration(), locals, nonlocals);
Collection<D> members = getMembersByName(receiverType, name); Collection<D> members = getMembersByName(receiver, name);
addTask(result, receiverType, call, locals); addTask(result, receiver, call, locals);
addTask(result, null, call, members); addTask(result, ReceiverDescriptor.NO_RECEIVER, call, members);
for (ReceiverDescriptor receiver : receivers) { for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
Collection<D> memberExtensions = getExtensionsByName(receiver.getReceiverType().getMemberScope(), name); Collection<D> memberExtensions = getExtensionsByName(implicitReceiver.getType().getMemberScope(), name);
addTask(result, receiverType, call, memberExtensions); addTask(result, receiver, call, memberExtensions);
} }
addTask(result, receiverType, call, nonlocals); addTask(result, receiver, call, nonlocals);
} }
else { else {
Collection<D> functions = getNonExtensionsByName(scope, name); Collection<D> functions = getNonExtensionsByName(scope, name);
@@ -100,13 +98,13 @@ import java.util.List;
//noinspection unchecked,RedundantTypeArguments //noinspection unchecked,RedundantTypeArguments
TaskPrioritizer.<D>splitLexicallyLocalDescriptors(functions, scope.getContainingDeclaration(), locals, nonlocals); TaskPrioritizer.<D>splitLexicallyLocalDescriptors(functions, scope.getContainingDeclaration(), locals, nonlocals);
addTask(result, receiverType, call, locals); addTask(result, receiver, call, locals);
for (ReceiverDescriptor receiver : receivers) { for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
doComputeTasks(scope, receiver.getReceiverType(), call, name, result); doComputeTasks(scope, implicitReceiver, call, name, result);
} }
addTask(result, receiverType, call, nonlocals); addTask(result, receiver, call, nonlocals);
} }
} }
@@ -114,17 +112,17 @@ import java.util.List;
protected abstract Collection<D> getNonExtensionsByName(JetScope scope, String name); protected abstract Collection<D> getNonExtensionsByName(JetScope scope, String name);
@NotNull @NotNull
protected abstract Collection<D> getMembersByName(@NotNull JetType receiverType, String name); protected abstract Collection<D> getMembersByName(@NotNull ReceiverDescriptor receiver, String name);
@NotNull @NotNull
protected abstract Collection<D> getExtensionsByName(JetScope scope, String name); protected abstract Collection<D> getExtensionsByName(JetScope scope, String name);
private void addTask(@NotNull List<ResolutionTask<D>> result, @Nullable JetType receiverType, @NotNull Call call, @NotNull Collection<D> candidates) { private void addTask(@NotNull List<ResolutionTask<D>> result, @NotNull ReceiverDescriptor receiver, @NotNull Call call, @NotNull Collection<D> candidates) {
if (candidates.isEmpty()) return; if (candidates.isEmpty()) return;
result.add(createTask(receiverType, call, candidates)); result.add(createTask(receiver, call, candidates));
} }
@NotNull @NotNull
protected abstract ResolutionTask<D> createTask(JetType receiverType, Call call, Collection<D> candidates); protected abstract ResolutionTask<D> createTask(ReceiverDescriptor receiver, Call call, Collection<D> candidates);
} }
@@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import java.util.Collection; import java.util.Collection;
import java.util.Set; import java.util.Set;
@@ -15,7 +15,7 @@ import java.util.Set;
/*package*/ interface TracingStrategy { /*package*/ interface TracingStrategy {
TracingStrategy EMPTY = new TracingStrategy() { TracingStrategy EMPTY = new TracingStrategy() {
@Override @Override
public void bindReference(@NotNull BindingTrace trace, @NotNull CallableDescriptor descriptor) {} public void bindReference(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiver, @NotNull CallableDescriptor descriptor) {}
@Override @Override
public void unresolvedReference(@NotNull BindingTrace trace) {} public void unresolvedReference(@NotNull BindingTrace trace) {}
@@ -24,7 +24,7 @@ import java.util.Set;
public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<D> candidates) {} public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<D> candidates) {}
@Override @Override
public void missingReceiver(@NotNull BindingTrace trace, @NotNull JetType candidateReceiverType) {} public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver) {}
@Override @Override
public void noReceiverAllowed(@NotNull BindingTrace trace) {} public void noReceiverAllowed(@NotNull BindingTrace trace) {}
@@ -48,13 +48,13 @@ import java.util.Set;
public void typeInferenceFailed(@NotNull BindingTrace trace) {} public void typeInferenceFailed(@NotNull BindingTrace trace) {}
}; };
void bindReference(@NotNull BindingTrace trace, @NotNull CallableDescriptor descriptor); void bindReference(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiver, @NotNull CallableDescriptor descriptor);
void unresolvedReference(@NotNull BindingTrace trace); void unresolvedReference(@NotNull BindingTrace trace);
<D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<D> candidates); <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<D> candidates);
void missingReceiver(@NotNull BindingTrace trace, @NotNull JetType candidateReceiverType); void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver);
void noReceiverAllowed(@NotNull BindingTrace trace); void noReceiverAllowed(@NotNull BindingTrace trace);
@@ -3,7 +3,7 @@ package org.jetbrains.jet.lang.resolve.scopes;
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.*;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ImplicitReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
/** /**
* @author abreslav * @author abreslav
@@ -30,5 +30,5 @@ public interface WritableScope extends JetScope {
void importScope(@NotNull JetScope imported); void importScope(@NotNull JetScope imported);
void setImplicitReceiver(@NotNull ImplicitReceiverDescriptor implicitReceiver); void setImplicitReceiver(@NotNull ReceiverDescriptor implicitReceiver);
} }
@@ -7,7 +7,6 @@ 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.*;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ImplicitReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import java.util.*; import java.util.*;
@@ -36,7 +35,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
private Map<String, List<DeclarationDescriptor>> labelsToDescriptors; private Map<String, List<DeclarationDescriptor>> labelsToDescriptors;
@Nullable @Nullable
private ImplicitReceiverDescriptor implicitReceiver; private ReceiverDescriptor implicitReceiver;
public WritableScopeImpl(@NotNull JetScope scope, @NotNull DeclarationDescriptor owner, @NotNull RedeclarationHandler redeclarationHandler) { public WritableScopeImpl(@NotNull JetScope scope, @NotNull DeclarationDescriptor owner, @NotNull RedeclarationHandler redeclarationHandler) {
super(scope, redeclarationHandler); super(scope, redeclarationHandler);
@@ -275,7 +274,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
} }
@Override @Override
public void setImplicitReceiver(@NotNull ImplicitReceiverDescriptor implicitReceiver) { public void setImplicitReceiver(@NotNull ReceiverDescriptor implicitReceiver) {
if (this.implicitReceiver != null) { if (this.implicitReceiver != null) {
throw new UnsupportedOperationException("Receiver redeclared"); throw new UnsupportedOperationException("Receiver redeclared");
} }
@@ -284,7 +283,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
@Override @Override
public void getImplicitReceiversHierarchy(@NotNull List<ReceiverDescriptor> result) { public void getImplicitReceiversHierarchy(@NotNull List<ReceiverDescriptor> result) {
if (implicitReceiver != null && implicitReceiver != ReceiverDescriptor.NO_RECEIVER) { if (implicitReceiver != null && implicitReceiver.exists()) {
result.add(implicitReceiver); result.add(implicitReceiver);
} }
super.getImplicitReceiversHierarchy(result); super.getImplicitReceiversHierarchy(result);
@@ -4,7 +4,6 @@ import com.google.common.collect.Lists;
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.*;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ImplicitReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import java.util.Collection; import java.util.Collection;
@@ -147,7 +146,7 @@ public class WriteThroughScope extends WritableScopeWithImports {
} }
@Override @Override
public void setImplicitReceiver(@NotNull ImplicitReceiverDescriptor implicitReceiver) { public void setImplicitReceiver(@NotNull ReceiverDescriptor implicitReceiver) {
writableWorker.setImplicitReceiver(implicitReceiver); writableWorker.setImplicitReceiver(implicitReceiver);
} }
@@ -0,0 +1,26 @@
package org.jetbrains.jet.lang.resolve.scopes.receivers;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author abreslav
*/
public abstract class AbstractReceiverDescriptor implements ReceiverDescriptor {
protected final JetType receiverType;
public AbstractReceiverDescriptor(@NotNull JetType receiverType) {
this.receiverType = receiverType;
}
@Override
@NotNull
public JetType getType() {
return receiverType;
}
@Override
public boolean exists() {
return true;
}
}
@@ -1,5 +1,6 @@
package org.jetbrains.jet.lang.resolve.scopes.receivers; package org.jetbrains.jet.lang.resolve.scopes.receivers;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
/** /**
@@ -10,4 +11,9 @@ public class ClassReceiver extends ImplicitReceiverDescriptor {
public ClassReceiver(ClassDescriptor classDescriptor) { public ClassReceiver(ClassDescriptor classDescriptor) {
super(classDescriptor, classDescriptor.getDefaultType()); super(classDescriptor, classDescriptor.getDefaultType());
} }
@Override
public <R, D> R accept(@NotNull ReceiverDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitClassReceiver(this, data);
}
} }
@@ -1,22 +0,0 @@
package org.jetbrains.jet.lang.resolve.scopes.receivers;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author abreslav
*/
public class ExplicitReceiver implements ReceiverDescriptor {
private final JetType type;
public ExplicitReceiver(@NotNull JetType type) {
this.type = type;
}
@NotNull
@Override
public JetType getReceiverType() {
return type;
}
}
@@ -0,0 +1,28 @@
package org.jetbrains.jet.lang.resolve.scopes.receivers;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author abreslav
*/
public class ExpressionReceiver extends AbstractReceiverDescriptor implements ReceiverDescriptor {
private final JetExpression expression;
public ExpressionReceiver(@NotNull JetExpression expression, @NotNull JetType type) {
super(type);
this.expression = expression;
}
@NotNull
public JetExpression getExpression() {
return expression;
}
@Override
public <R, D> R accept(@NotNull ReceiverDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitExpressionReceiver(this, data);
}
}
@@ -1,13 +0,0 @@
package org.jetbrains.jet.lang.resolve.scopes.receivers;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
/**
* @author abreslav
*/
public class ExtensionCallableReceiver extends ImplicitReceiverDescriptor {
public ExtensionCallableReceiver(CallableDescriptor callableDescriptor) {
super(callableDescriptor, callableDescriptor.getReceiverType());
}
}
@@ -0,0 +1,20 @@
package org.jetbrains.jet.lang.resolve.scopes.receivers;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author abreslav
*/
public class ExtensionReceiver extends ImplicitReceiverDescriptor {
public ExtensionReceiver(@NotNull CallableDescriptor callableDescriptor, @NotNull JetType receiverType) {
super(callableDescriptor, receiverType);
}
@Override
public <R, D> R accept(@NotNull ReceiverDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitExtensionReceiver(this, data);
}
}
@@ -9,21 +9,14 @@ import org.jetbrains.jet.lang.types.JetType;
* *
* @author abreslav * @author abreslav
*/ */
public abstract class ImplicitReceiverDescriptor implements ReceiverDescriptor { public abstract class ImplicitReceiverDescriptor extends AbstractReceiverDescriptor {
private final JetType receiverType;
private final DeclarationDescriptor declarationDescriptor; private final DeclarationDescriptor declarationDescriptor;
protected ImplicitReceiverDescriptor(DeclarationDescriptor declarationDescriptor, JetType receiverType) { protected ImplicitReceiverDescriptor(@NotNull DeclarationDescriptor declarationDescriptor, @NotNull JetType receiverType) {
this.receiverType = receiverType; super(receiverType);
this.declarationDescriptor = declarationDescriptor; this.declarationDescriptor = declarationDescriptor;
} }
@Override
@NotNull
public JetType getReceiverType() {
return receiverType;
}
@NotNull @NotNull
public DeclarationDescriptor getDeclarationDescriptor() { public DeclarationDescriptor getDeclarationDescriptor() {
return declarationDescriptor; return declarationDescriptor;
@@ -1,7 +1,6 @@
package org.jetbrains.jet.lang.resolve.scopes.receivers; package org.jetbrains.jet.lang.resolve.scopes.receivers;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
/** /**
@@ -12,8 +11,18 @@ public interface ReceiverDescriptor {
ReceiverDescriptor NO_RECEIVER = new ReceiverDescriptor() { ReceiverDescriptor NO_RECEIVER = new ReceiverDescriptor() {
@NotNull @NotNull
@Override @Override
public JetType getReceiverType() { public JetType getType() {
return JetStandardClasses.getNothingType(); throw new UnsupportedOperationException("NO_RECEIVER.getType()");
}
@Override
public boolean exists() {
return false;
}
@Override
public <R, D> R accept(@NotNull ReceiverDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitNoReceiver(this, data);
} }
@Override @Override
@@ -23,5 +32,9 @@ public interface ReceiverDescriptor {
}; };
@NotNull @NotNull
JetType getReceiverType(); JetType getType();
boolean exists();
<R, D> R accept(@NotNull ReceiverDescriptorVisitor<R, D> visitor, D data);
} }
@@ -0,0 +1,26 @@
package org.jetbrains.jet.lang.resolve.scopes.receivers;
/**
* @author abreslav
*/
public class ReceiverDescriptorVisitor<R, D> {
public R visitNoReceiver(ReceiverDescriptor noReceiver, D data) {
return null;
}
public R visitTransientReceiver(TransientReceiver receiver, D data) {
return null;
}
public R visitExtensionReceiver(ExtensionReceiver receiver, D data) {
return null;
}
public R visitExpressionReceiver(ExpressionReceiver receiver, D data) {
return null;
}
public R visitClassReceiver(ClassReceiver classReceiver, D data) {
return null;
}
}
@@ -0,0 +1,21 @@
package org.jetbrains.jet.lang.resolve.scopes.receivers;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.JetType;
/**
* This represents the receiver of hasNext and next() in for-loops
* Cannot be an expression receiver because there is no expression for the iterator() call
*
* @author abreslav
*/
public class TransientReceiver extends AbstractReceiverDescriptor {
public TransientReceiver(@NotNull JetType type) {
super(type);
}
@Override
public <R, D> R accept(@NotNull ReceiverDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitTransientReceiver(this, data);
}
}
@@ -26,6 +26,9 @@ import org.jetbrains.jet.lang.resolve.constants.StringValue;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.util.slicedmap.WritableSlice; import org.jetbrains.jet.util.slicedmap.WritableSlice;
@@ -196,7 +199,7 @@ public class JetTypeInferrer {
} }
@NotNull @NotNull
public JetType safeGetType(@NotNull final JetScope scope, @NotNull JetExpression expression, @NotNull JetType expectedType) { public JetType safeGetType(@NotNull JetScope scope, @NotNull JetExpression expression, @NotNull JetType expectedType) {
JetType type = getType(scope, expression, expectedType); JetType type = getType(scope, expression, expectedType);
if (type != null) { if (type != null) {
return type; return type;
@@ -221,9 +224,9 @@ public class JetTypeInferrer {
private void checkNullSafety(@Nullable JetType receiverType, @NotNull ASTNode operationTokenNode, @Nullable FunctionDescriptor callee, @NotNull JetElement element) { private void checkNullSafety(@Nullable JetType receiverType, @NotNull ASTNode operationTokenNode, @Nullable FunctionDescriptor callee, @NotNull JetElement element) {
if (receiverType != null && callee != null) { if (receiverType != null && callee != null) {
boolean namespaceType = receiverType instanceof NamespaceType; boolean namespaceType = receiverType instanceof NamespaceType;
JetType calleeReceiverType = callee.getReceiverType();
boolean nullableReceiver = !namespaceType && receiverType.isNullable(); boolean nullableReceiver = !namespaceType && receiverType.isNullable();
boolean calleeForbidsNullableReceiver = calleeReceiverType == null || !calleeReceiverType.isNullable(); ReceiverDescriptor calleeReceiver = callee.getReceiver();
boolean calleeForbidsNullableReceiver = !calleeReceiver.exists() || !calleeReceiver.getType().isNullable();
IElementType operationSign = operationTokenNode.getElementType(); IElementType operationSign = operationTokenNode.getElementType();
if (nullableReceiver && calleeForbidsNullableReceiver && operationSign == JetTokens.DOT) { if (nullableReceiver && calleeForbidsNullableReceiver && operationSign == JetTokens.DOT) {
@@ -682,6 +685,20 @@ public class JetTypeInferrer {
} }
return ErrorUtils.createErrorType("Type for " + expression.getText()); return ErrorUtils.createErrorType("Type for " + expression.getText());
} }
@Nullable
public final ExpressionReceiver getExpressionReceiver(@NotNull JetExpression expression, TypeInferenceContext context) {
JetType type = getType(expression, context);
if (type == null) {
return null;
}
return new ExpressionReceiver(expression, type);
}
@NotNull
public final ExpressionReceiver safeGetExpressionReceiver(@NotNull JetExpression expression, TypeInferenceContext context) {
return new ExpressionReceiver(expression, safeGetType(expression, context));
}
@Nullable @Nullable
public final JetType getType(@NotNull JetExpression expression, TypeInferenceContext context) { public final JetType getType(@NotNull JetExpression expression, TypeInferenceContext context) {
@@ -762,7 +779,7 @@ public class JetTypeInferrer {
} }
} }
else { else {
return getSelectorReturnType(null, expression, context); // TODO : Extensions to this return getSelectorReturnType(ReceiverDescriptor.NO_RECEIVER, expression, context); // TODO : Extensions to this
// assert JetTokens.IDENTIFIER == expression.getReferencedNameElementType(); // assert JetTokens.IDENTIFIER == expression.getReferencedNameElementType();
// if (referencedName != null) { // if (referencedName != null) {
// VariableDescriptor variable = context.scope.getVariable(referencedName); // VariableDescriptor variable = context.scope.getVariable(referencedName);
@@ -895,7 +912,8 @@ public class JetTypeInferrer {
if (receiverTypeRef != null) { if (receiverTypeRef != null) {
receiverType = context.typeResolver.resolveType(context.scope, receiverTypeRef); receiverType = context.typeResolver.resolveType(context.scope, receiverTypeRef);
} else { } else {
receiverType = context.scope.getImplicitReceiver().getReceiverType(); ReceiverDescriptor implicitReceiver = context.scope.getImplicitReceiver();
receiverType = implicitReceiver.exists() ? implicitReceiver.getType() : null;
} }
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl( FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(
@@ -1217,7 +1235,7 @@ public class JetTypeInferrer {
@Override @Override
public JetType visitThisExpression(JetThisExpression expression, TypeInferenceContext context) { public JetType visitThisExpression(JetThisExpression expression, TypeInferenceContext context) {
JetType result = null; JetType result = null;
JetType thisType = null; ReceiverDescriptor thisReceiver = null;
String labelName = expression.getLabelName(); String labelName = expression.getLabelName();
if (labelName != null) { if (labelName != null) {
Collection<DeclarationDescriptor> declarationsByLabel = context.scope.getDeclarationsByLabel(labelName); Collection<DeclarationDescriptor> declarationsByLabel = context.scope.getDeclarationsByLabel(labelName);
@@ -1228,11 +1246,11 @@ public class JetTypeInferrer {
DeclarationDescriptor declarationDescriptor = declarationsByLabel.iterator().next(); DeclarationDescriptor declarationDescriptor = declarationsByLabel.iterator().next();
if (declarationDescriptor instanceof ClassDescriptor) { if (declarationDescriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor; ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
thisType = classDescriptor.getDefaultType(); thisReceiver = classDescriptor.getImplicitReceiver();
} }
else if (declarationDescriptor instanceof FunctionDescriptor) { else if (declarationDescriptor instanceof FunctionDescriptor) {
FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor; FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor;
thisType = functionDescriptor.getReceiverType(); thisReceiver = functionDescriptor.getReceiver();
} }
else { else {
throw new UnsupportedOperationException(); // TODO throw new UnsupportedOperationException(); // TODO
@@ -1246,11 +1264,8 @@ public class JetTypeInferrer {
if (psiElement instanceof JetFunctionLiteralExpression) { if (psiElement instanceof JetFunctionLiteralExpression) {
DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement); DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
if (declarationDescriptor instanceof FunctionDescriptor) { if (declarationDescriptor instanceof FunctionDescriptor) {
thisType = ((FunctionDescriptor) declarationDescriptor).getReceiverType(); thisReceiver = ((FunctionDescriptor) declarationDescriptor).getReceiver();
if (thisType == null) { if (thisReceiver.exists()) {
thisType = JetStandardClasses.getNothingType();
}
else {
context.trace.record(REFERENCE_TARGET, targetLabel, declarationDescriptor); context.trace.record(REFERENCE_TARGET, targetLabel, declarationDescriptor);
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor); context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
} }
@@ -1269,7 +1284,7 @@ public class JetTypeInferrer {
} }
} }
else { else {
thisType = context.scope.getImplicitReceiver().getReceiverType(); thisReceiver = context.scope.getImplicitReceiver();
DeclarationDescriptor declarationDescriptorForUnqualifiedThis = context.scope.getDeclarationDescriptorForUnqualifiedThis(); DeclarationDescriptor declarationDescriptorForUnqualifiedThis = context.scope.getDeclarationDescriptorForUnqualifiedThis();
if (declarationDescriptorForUnqualifiedThis != null) { if (declarationDescriptorForUnqualifiedThis != null) {
@@ -1277,8 +1292,8 @@ public class JetTypeInferrer {
} }
} }
if (thisType != null) { if (thisReceiver != null) {
if (JetStandardClasses.isNothing(thisType)) { if (!thisReceiver.exists()) {
// context.trace.getErrorHandler().genericError(expression.getNode(), "'this' is not defined in this context"); // context.trace.getErrorHandler().genericError(expression.getNode(), "'this' is not defined in this context");
context.trace.report(NO_THIS.on(expression)); context.trace.report(NO_THIS.on(expression));
} }
@@ -1294,6 +1309,7 @@ public class JetTypeInferrer {
if (classifierCandidate instanceof ClassDescriptor) { if (classifierCandidate instanceof ClassDescriptor) {
ClassDescriptor superclass = (ClassDescriptor) classifierCandidate; ClassDescriptor superclass = (ClassDescriptor) classifierCandidate;
JetType thisType = thisReceiver.getType();
Collection<? extends JetType> supertypes = thisType.getConstructor().getSupertypes(); Collection<? extends JetType> supertypes = thisType.getConstructor().getSupertypes();
TypeSubstitutor substitutor = TypeSubstitutor.create(thisType); TypeSubstitutor substitutor = TypeSubstitutor.create(thisType);
for (JetType declaredSupertype : supertypes) { for (JetType declaredSupertype : supertypes) {
@@ -1308,8 +1324,9 @@ public class JetTypeInferrer {
} }
} }
} }
} else { }
result = thisType; else {
result = thisReceiver.getType();
} }
if (result != null) { if (result != null) {
context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getThisReference(), result); context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getThisReference(), result);
@@ -1396,7 +1413,8 @@ public class JetTypeInferrer {
// JetScope compositeScope = new ScopeWithReceiver(context.scope, subjectType, semanticServices.getTypeChecker()); // JetScope compositeScope = new ScopeWithReceiver(context.scope, subjectType, semanticServices.getTypeChecker());
if (callSuffixExpression != null) { if (callSuffixExpression != null) {
// JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false, context); // JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false, context);
JetType selectorReturnType = getSelectorReturnType(subjectType, callSuffixExpression, context);//getType(compositeScope, callSuffixExpression, false, context); assert subjectExpression != null;
JetType selectorReturnType = getSelectorReturnType(new ExpressionReceiver(subjectExpression, subjectType), callSuffixExpression, context);//getType(compositeScope, callSuffixExpression, false, context);
ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression", context); ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression", context);
context.services.checkNullSafety(subjectType, condition.getOperationTokenNode(), getCalleeFunctionDescriptor(callSuffixExpression, context), condition); context.services.checkNullSafety(subjectType, condition.getOperationTokenNode(), getCalleeFunctionDescriptor(callSuffixExpression, context), condition);
} }
@@ -1474,7 +1492,8 @@ public class JetTypeInferrer {
public void visitDecomposerPattern(JetDecomposerPattern pattern) { public void visitDecomposerPattern(JetDecomposerPattern pattern) {
JetExpression decomposerExpression = pattern.getDecomposerExpression(); JetExpression decomposerExpression = pattern.getDecomposerExpression();
if (decomposerExpression != null) { if (decomposerExpression != null) {
JetType selectorReturnType = getSelectorReturnType(subjectType, decomposerExpression, context); ReceiverDescriptor receiver = new TransientReceiver(subjectType);
JetType selectorReturnType = getSelectorReturnType(receiver, decomposerExpression, context);
result[0] = checkPatternType(pattern.getArgumentList(), selectorReturnType == null ? ErrorUtils.createErrorType("No type") : selectorReturnType, scopeToExtend, context); result[0] = checkPatternType(pattern.getArgumentList(), selectorReturnType == null ? ErrorUtils.createErrorType("No type") : selectorReturnType, scopeToExtend, context);
} }
@@ -1840,13 +1859,12 @@ public class JetTypeInferrer {
TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
JetParameter loopParameter = expression.getLoopParameter(); JetParameter loopParameter = expression.getLoopParameter();
JetExpression loopRange = expression.getLoopRange(); JetExpression loopRange = expression.getLoopRange();
JetType loopRangeType = null;
if (loopRange != null) {
loopRangeType = getType(loopRange, context.replaceScope(context.scope));
}
JetType expectedParameterType = null; JetType expectedParameterType = null;
if (loopRangeType != null) { if (loopRange != null) {
expectedParameterType = checkIterableConvention(loopRangeType, loopRange, context); ExpressionReceiver loopRangeReceiver = getExpressionReceiver(loopRange, context.replaceScope(context.scope));
if (loopRangeReceiver != null) {
expectedParameterType = checkIterableConvention(loopRangeReceiver, context);
}
} }
WritableScope loopScope = newWritableScopeImpl(context.scope, context.trace).setDebugName("Scope with for-loop index"); WritableScope loopScope = newWritableScopeImpl(context.scope, context.trace).setDebugName("Scope with for-loop index");
@@ -1882,42 +1900,42 @@ public class JetTypeInferrer {
} }
@Nullable @Nullable
private JetType checkIterableConvention(@NotNull JetType type, @NotNull JetExpression loopRange, TypeInferenceContext context) { private JetType checkIterableConvention(@NotNull ExpressionReceiver loopRange, TypeInferenceContext context) {
ASTNode reportErrorsOn = loopRange.getNode(); JetExpression loopRangeExpression = loopRange.getExpression();
OverloadResolutionResult<FunctionDescriptor> iteratorResolutionResult = callResolver.resolveExactSignature(context.scope, type, "iterator", Collections.<JetType>emptyList()); OverloadResolutionResult<FunctionDescriptor> iteratorResolutionResult = callResolver.resolveExactSignature(context.scope, loopRange, "iterator", Collections.<JetType>emptyList());
if (iteratorResolutionResult.isSuccess()) { if (iteratorResolutionResult.isSuccess()) {
FunctionDescriptor iteratorFunction = iteratorResolutionResult.getDescriptor(); FunctionDescriptor iteratorFunction = iteratorResolutionResult.getDescriptor();
context.trace.record(LOOP_RANGE_ITERATOR, loopRange, iteratorFunction); context.trace.record(LOOP_RANGE_ITERATOR, loopRangeExpression, iteratorFunction);
JetType iteratorType = iteratorFunction.getReturnType(); JetType iteratorType = iteratorFunction.getReturnType();
FunctionDescriptor hasNextFunction = checkHasNextFunctionSupport(loopRange, iteratorType, context); FunctionDescriptor hasNextFunction = checkHasNextFunctionSupport(loopRangeExpression, iteratorType, context);
boolean hasNextFunctionSupported = hasNextFunction != null; boolean hasNextFunctionSupported = hasNextFunction != null;
VariableDescriptor hasNextProperty = checkHasNextPropertySupport(loopRange, iteratorType, context); VariableDescriptor hasNextProperty = checkHasNextPropertySupport(loopRangeExpression, iteratorType, context);
boolean hasNextPropertySupported = hasNextProperty != null; boolean hasNextPropertySupported = hasNextProperty != null;
if (hasNextFunctionSupported && hasNextPropertySupported && !ErrorUtils.isErrorType(iteratorType)) { if (hasNextFunctionSupported && hasNextPropertySupported && !ErrorUtils.isErrorType(iteratorType)) {
// TODO : overload resolution rules impose priorities here??? // TODO : overload resolution rules impose priorities here???
// context.trace.getErrorHandler().genericError(reportErrorsOn, "An ambiguity between 'iterator().hasNext()' function and 'iterator().hasNext' property"); // context.trace.getErrorHandler().genericError(reportErrorsOn, "An ambiguity between 'iterator().hasNext()' function and 'iterator().hasNext' property");
context.trace.report(HAS_NEXT_PROPERTY_AND_FUNCTION_AMBIGUITY.on(reportErrorsOn)); context.trace.report(HAS_NEXT_PROPERTY_AND_FUNCTION_AMBIGUITY.on(loopRangeExpression));
} }
else if (!hasNextFunctionSupported && !hasNextPropertySupported) { else if (!hasNextFunctionSupported && !hasNextPropertySupported) {
// context.trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().hasNext()' function or an 'iterator().hasNext' property"); // context.trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().hasNext()' function or an 'iterator().hasNext' property");
context.trace.report(HAS_NEXT_MISSING.on(reportErrorsOn)); context.trace.report(HAS_NEXT_MISSING.on(loopRangeExpression));
} }
else { else {
context.trace.record(LOOP_RANGE_HAS_NEXT, loopRange, hasNextFunctionSupported ? hasNextFunction : hasNextProperty); context.trace.record(LOOP_RANGE_HAS_NEXT, loopRange.getExpression(), hasNextFunctionSupported ? hasNextFunction : hasNextProperty);
} }
OverloadResolutionResult<FunctionDescriptor> nextResolutionResult = callResolver.resolveExactSignature(context.scope, iteratorType, "next", Collections.<JetType>emptyList()); OverloadResolutionResult<FunctionDescriptor> nextResolutionResult = callResolver.resolveExactSignature(context.scope, new TransientReceiver(iteratorType), "next", Collections.<JetType>emptyList());
if (nextResolutionResult.isAmbiguity()) { if (nextResolutionResult.isAmbiguity()) {
// context.trace.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().next()' is ambiguous for this expression"); // context.trace.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().next()' is ambiguous for this expression");
context.trace.report(NEXT_AMBIGUITY.on(reportErrorsOn)); context.trace.report(NEXT_AMBIGUITY.on(loopRangeExpression));
} else if (nextResolutionResult.isNothing()) { } else if (nextResolutionResult.isNothing()) {
// context.trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().next()' method"); // context.trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().next()' method");
context.trace.report(NEXT_MISSING.on(reportErrorsOn)); context.trace.report(NEXT_MISSING.on(loopRangeExpression));
} else { } else {
FunctionDescriptor nextFunction = nextResolutionResult.getDescriptor(); FunctionDescriptor nextFunction = nextResolutionResult.getDescriptor();
context.trace.record(LOOP_RANGE_NEXT, loopRange, nextFunction); context.trace.record(LOOP_RANGE_NEXT, loopRange.getExpression(), nextFunction);
return nextFunction.getReturnType(); return nextFunction.getReturnType();
} }
} }
@@ -1928,11 +1946,11 @@ public class JetTypeInferrer {
// stringBuffer.append(DescriptorRenderer.TEXT.render(functionDescriptor)).append(" "); // stringBuffer.append(DescriptorRenderer.TEXT.render(functionDescriptor)).append(" ");
// } // }
// errorMessage = stringBuffer.toString(); // errorMessage = stringBuffer.toString();
context.trace.report(ITERATOR_AMBIGUITY.on(reportErrorsOn, iteratorResolutionResult.getDescriptors())); context.trace.report(ITERATOR_AMBIGUITY.on(loopRangeExpression, iteratorResolutionResult.getDescriptors()));
} }
else { else {
// context.trace.getErrorHandler().genericError(reportErrorsOn, errorMessage); // context.trace.getErrorHandler().genericError(reportErrorsOn, errorMessage);
context.trace.report(ITERATOR_MISSING.on(reportErrorsOn)); context.trace.report(ITERATOR_MISSING.on(loopRangeExpression));
} }
} }
return null; return null;
@@ -1940,7 +1958,7 @@ public class JetTypeInferrer {
@Nullable @Nullable
private FunctionDescriptor checkHasNextFunctionSupport(@NotNull JetExpression loopRange, @NotNull JetType iteratorType, TypeInferenceContext context) { private FunctionDescriptor checkHasNextFunctionSupport(@NotNull JetExpression loopRange, @NotNull JetType iteratorType, TypeInferenceContext context) {
OverloadResolutionResult<FunctionDescriptor> hasNextResolutionResult = callResolver.resolveExactSignature(context.scope, iteratorType, "hasNext", Collections.<JetType>emptyList()); OverloadResolutionResult<FunctionDescriptor> hasNextResolutionResult = callResolver.resolveExactSignature(context.scope, new TransientReceiver(iteratorType), "hasNext", Collections.<JetType>emptyList());
if (hasNextResolutionResult.isAmbiguity()) { if (hasNextResolutionResult.isAmbiguity()) {
// context.trace.getErrorHandler().genericError(loopRange.getNode(), "Method 'iterator().hasNext()' is ambiguous for this expression"); // context.trace.getErrorHandler().genericError(loopRange.getNode(), "Method 'iterator().hasNext()' is ambiguous for this expression");
context.trace.report(HAS_NEXT_FUNCTION_AMBIGUITY.on(loopRange)); context.trace.report(HAS_NEXT_FUNCTION_AMBIGUITY.on(loopRange));
@@ -2002,7 +2020,7 @@ public class JetTypeInferrer {
// Clean resolution: no autocasts // Clean resolution: no autocasts
TemporaryBindingTrace cleanResolutionTrace = TemporaryBindingTrace.create(context.trace); TemporaryBindingTrace cleanResolutionTrace = TemporaryBindingTrace.create(context.trace);
TypeInferenceContext cleanResolutionContext = context.replaceBindingTrace(cleanResolutionTrace); TypeInferenceContext cleanResolutionContext = context.replaceBindingTrace(cleanResolutionTrace);
JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression, cleanResolutionContext); JetType selectorReturnType = getSelectorReturnType(new ExpressionReceiver(receiverExpression, receiverType), selectorExpression, cleanResolutionContext);
//TODO move further //TODO move further
if (expression.getOperationSign() == JetTokens.SAFE_ACCESS) { if (expression.getOperationSign() == JetTokens.SAFE_ACCESS) {
@@ -2023,7 +2041,7 @@ public class JetTypeInferrer {
TemporaryBindingTrace autocastResolutionTrace = TemporaryBindingTrace.create(context.trace); TemporaryBindingTrace autocastResolutionTrace = TemporaryBindingTrace.create(context.trace);
TypeInferenceContext autocastResolutionContext = context.replaceBindingTrace(autocastResolutionTrace); TypeInferenceContext autocastResolutionContext = context.replaceBindingTrace(autocastResolutionTrace);
for (JetType possibleType : possibleTypes) { for (JetType possibleType : possibleTypes) {
selectorReturnType = getSelectorReturnType(possibleType, selectorExpression, autocastResolutionContext); selectorReturnType = getSelectorReturnType(new ExpressionReceiver(receiverExpression, possibleType), selectorExpression, autocastResolutionContext);
if (selectorReturnType != null) { if (selectorReturnType != null) {
context.services.checkAutoCast(receiverExpression, possibleType, variableDescriptor, autocastResolutionTrace); context.services.checkAutoCast(receiverExpression, possibleType, variableDescriptor, autocastResolutionTrace);
autocastResolutionTrace.commit(); autocastResolutionTrace.commit();
@@ -2146,20 +2164,20 @@ public class JetTypeInferrer {
} }
@Nullable @Nullable
private JetType getSelectorReturnType(@Nullable JetType receiverType, @NotNull JetExpression selectorExpression, @NotNull TypeInferenceContext context) { private JetType getSelectorReturnType(@NotNull ReceiverDescriptor receiver, @NotNull JetExpression selectorExpression, @NotNull TypeInferenceContext context) {
if (selectorExpression instanceof JetCallExpression) { if (selectorExpression instanceof JetCallExpression) {
return callResolver.resolveCall(context.trace, context.scope, receiverType, (JetCallExpression) selectorExpression, context.expectedType); return callResolver.resolveCall(context.trace, context.scope, receiver, (JetCallExpression) selectorExpression, context.expectedType);
} }
else if (selectorExpression instanceof JetSimpleNameExpression) { else if (selectorExpression instanceof JetSimpleNameExpression) {
JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) selectorExpression; JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) selectorExpression;
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace); TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace);
VariableDescriptor variableDescriptor = callResolver.resolveSimpleProperty(temporaryTrace, context.scope, receiverType, nameExpression, context.expectedType); VariableDescriptor variableDescriptor = callResolver.resolveSimpleProperty(temporaryTrace, context.scope, receiver, nameExpression, context.expectedType);
if (variableDescriptor != null) { if (variableDescriptor != null) {
temporaryTrace.commit(); temporaryTrace.commit();
return context.services.checkEnrichedType(variableDescriptor.getOutType(), nameExpression, context); return context.services.checkEnrichedType(variableDescriptor.getOutType(), nameExpression, context);
} }
TypeInferenceContext newContext = receiverType == null ? context : context.replaceScope(receiverType.getMemberScope()); TypeInferenceContext newContext = receiver.exists() ? context.replaceScope(receiver.getType().getMemberScope()) : context;
JetType jetType = lookupNamespaceOrClassObject(nameExpression, nameExpression.getReferencedName(), newContext); JetType jetType = lookupNamespaceOrClassObject(nameExpression, nameExpression.getReferencedName(), newContext);
if (jetType == null) { if (jetType == null) {
context.trace.report(UNRESOLVED_REFERENCE.on(nameExpression)); context.trace.report(UNRESOLVED_REFERENCE.on(nameExpression));
@@ -2170,10 +2188,11 @@ public class JetTypeInferrer {
} }
else if (selectorExpression instanceof JetQualifiedExpression) { else if (selectorExpression instanceof JetQualifiedExpression) {
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) selectorExpression; JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) selectorExpression;
JetType newReceiverType = getSelectorReturnType(receiverType, qualifiedExpression.getReceiverExpression(), context.replaceExpectedType(NO_EXPECTED_TYPE)); JetExpression newReceiverExpression = qualifiedExpression.getReceiverExpression();
JetType newReceiverType = getSelectorReturnType(receiver, newReceiverExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
JetExpression newSelectorExpression = qualifiedExpression.getSelectorExpression(); JetExpression newSelectorExpression = qualifiedExpression.getSelectorExpression();
if (newReceiverType != null && newSelectorExpression != null) { if (newReceiverType != null && newSelectorExpression != null) {
return getSelectorReturnType(newReceiverType, newSelectorExpression, context); return getSelectorReturnType(new ExpressionReceiver(newReceiverExpression, newReceiverType), newSelectorExpression, context);
} }
} }
else { else {
@@ -2186,7 +2205,7 @@ public class JetTypeInferrer {
@Override @Override
public JetType visitCallExpression(JetCallExpression expression, TypeInferenceContext context) { public JetType visitCallExpression(JetCallExpression expression, TypeInferenceContext context) {
JetType expressionType = callResolver.resolveCall(context.trace, context.scope, null, expression, context.expectedType); JetType expressionType = callResolver.resolveCall(context.trace, context.scope, ReceiverDescriptor.NO_RECEIVER, expression, context.expectedType);
return context.services.checkType(expressionType, expression, context); return context.services.checkType(expressionType, expression, context);
} }
@@ -2220,8 +2239,8 @@ public class JetTypeInferrer {
context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression")); context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression"));
return null; return null;
} }
JetType receiverType = getType(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceScope(context.scope)); ExpressionReceiver receiver = getExpressionReceiver(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceScope(context.scope));
if (receiverType == null) return null; if (receiver == null) return null;
FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName( FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName(
context.trace, context.trace,
@@ -2229,7 +2248,7 @@ public class JetTypeInferrer {
CallMaker.makeCall(expression), CallMaker.makeCall(expression),
expression.getOperationSign(), expression.getOperationSign(),
name, name,
receiverType, receiver,
context.expectedType); context.expectedType);
if (functionDescriptor == null) return null; if (functionDescriptor == null) return null;
@@ -2240,6 +2259,7 @@ public class JetTypeInferrer {
result = JetStandardClasses.getUnitType(); result = JetStandardClasses.getUnitType();
} }
else { else {
JetType receiverType = receiver.getType();
if (!semanticServices.getTypeChecker().isSubtypeOf(returnType, receiverType)) { if (!semanticServices.getTypeChecker().isSubtypeOf(returnType, receiverType)) {
// context.trace.getErrorHandler().genericError(operationSign.getNode(), name + " must return " + receiverType + " but returns " + returnType); // context.trace.getErrorHandler().genericError(operationSign.getNode(), name + " must return " + receiverType + " but returns " + returnType);
context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, name, receiverType, returnType)); context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, name, receiverType, returnType));
@@ -2299,9 +2319,9 @@ public class JetTypeInferrer {
else if (equalsOperations.contains(operationType)) { else if (equalsOperations.contains(operationType)) {
String name = "equals"; String name = "equals";
if (right != null) { if (right != null) {
JetType leftType = safeGetType(left, context.replaceScope(context.scope)); ExpressionReceiver receiver = safeGetExpressionReceiver(left, context.replaceScope(context.scope));
OverloadResolutionResult<FunctionDescriptor> resolutionResult = callResolver.resolveExactSignature( OverloadResolutionResult<FunctionDescriptor> resolutionResult = callResolver.resolveExactSignature(
context.scope, leftType, "equals", context.scope, receiver, "equals",
Collections.singletonList(JetStandardClasses.getNullableAnyType())); Collections.singletonList(JetStandardClasses.getNullableAnyType()));
if (resolutionResult.isSuccess()) { if (resolutionResult.isSuccess()) {
FunctionDescriptor equals = resolutionResult.getDescriptor(); FunctionDescriptor equals = resolutionResult.getDescriptor();
@@ -2380,13 +2400,13 @@ public class JetTypeInferrer {
private void checkInExpression(JetSimpleNameExpression operationSign, JetExpression left, JetExpression right, TypeInferenceContext context) { private void checkInExpression(JetSimpleNameExpression operationSign, JetExpression left, JetExpression right, TypeInferenceContext context) {
String name = "contains"; String name = "contains";
JetType receiverType = context.services.safeGetType(context.scope, right, NO_EXPECTED_TYPE); ExpressionReceiver receiver = safeGetExpressionReceiver(right, context.replaceExpectedType(NO_EXPECTED_TYPE));
FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName( FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName(
context.trace, context.trace,
context.scope, context.scope,
CallMaker.makeCall(operationSign, Collections.singletonList(left)), CallMaker.makeCall(operationSign, Collections.singletonList(left)),
operationSign, operationSign,
name, receiverType, context.expectedType); name, receiver, context.expectedType);
JetType containsType = functionDescriptor != null ? functionDescriptor.getReturnType() : null; JetType containsType = functionDescriptor != null ? functionDescriptor.getReturnType() : null;
ensureBooleanResult(operationSign, name, containsType, context); ensureBooleanResult(operationSign, name, containsType, context);
} }
@@ -2449,16 +2469,16 @@ public class JetTypeInferrer {
public JetType visitArrayAccessExpression(JetArrayAccessExpression expression, TypeInferenceContext contextWithExpectedType) { public JetType visitArrayAccessExpression(JetArrayAccessExpression expression, TypeInferenceContext contextWithExpectedType) {
TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
JetExpression arrayExpression = expression.getArrayExpression(); JetExpression arrayExpression = expression.getArrayExpression();
JetType receiverType = getType(arrayExpression, context.replaceScope(context.scope)); ExpressionReceiver receiver = getExpressionReceiver(arrayExpression, context.replaceScope(context.scope));
if (receiverType != null) { if (receiver != null) {
FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName( FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName(
context.trace, context.trace,
context.scope, context.scope,
CallMaker.makeCall(expression, expression.getIndexExpressions()), CallMaker.makeCall(expression, expression.getIndexExpressions()),
expression, expression,
"get", "get",
receiverType, receiver,
context.expectedType); context.expectedType);
if (functionDescriptor != null) { if (functionDescriptor != null) {
return context.services.checkType(functionDescriptor.getReturnType(), expression, contextWithExpectedType); return context.services.checkType(functionDescriptor.getReturnType(), expression, contextWithExpectedType);
@@ -2469,17 +2489,17 @@ public class JetTypeInferrer {
@Nullable @Nullable
protected JetType getTypeForBinaryCall(JetScope scope, String name, TypeInferenceContext context, JetBinaryExpression binaryExpression) { protected JetType getTypeForBinaryCall(JetScope scope, String name, TypeInferenceContext context, JetBinaryExpression binaryExpression) {
JetType leftType = getType(binaryExpression.getLeft(), context.replaceScope(scope)); ExpressionReceiver receiver = safeGetExpressionReceiver(binaryExpression.getLeft(), context.replaceScope(scope));
FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName( FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName(
context.trace, context.trace,
scope, scope,
CallMaker.makeCall(binaryExpression), CallMaker.makeCall(binaryExpression),
binaryExpression.getOperationReference(), binaryExpression.getOperationReference(),
name, name,
leftType, receiver,
context.expectedType); context.expectedType);
if (functionDescriptor != null) { if (functionDescriptor != null) {
if (leftType != null && leftType.isNullable()) { if (receiver.getType().isNullable()) {
// TODO : better error message for '1 + nullableVar' case // TODO : better error message for '1 + nullableVar' case
JetExpression right = binaryExpression.getRight(); JetExpression right = binaryExpression.getRight();
String rightText = right == null ? "" : right.getText(); String rightText = right == null ? "" : right.getText();
@@ -2719,8 +2739,8 @@ public class JetTypeInferrer {
} }
private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, TypeInferenceContext context) { private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, TypeInferenceContext context) {
JetType receiverType = getType(arrayAccessExpression.getArrayExpression(), context.replaceScope(scope)); ExpressionReceiver receiver = getExpressionReceiver(arrayAccessExpression.getArrayExpression(), context.replaceScope(scope));
if (receiverType == null) return null; if (receiver == null) return null;
// //
Call call = CallMaker.makeCall(arrayAccessExpression, rightHandSide); Call call = CallMaker.makeCall(arrayAccessExpression, rightHandSide);
// // TODO : nasty hack: effort is duplicated // // TODO : nasty hack: effort is duplicated
@@ -2734,7 +2754,7 @@ public class JetTypeInferrer {
scope, scope,
call, call,
arrayAccessExpression, arrayAccessExpression,
"set", receiverType, NO_EXPECTED_TYPE); "set", receiver, NO_EXPECTED_TYPE);
if (functionDescriptor == null) return null; if (functionDescriptor == null) return null;
context.trace.record(REFERENCE_TARGET, operationSign, functionDescriptor); context.trace.record(REFERENCE_TARGET, operationSign, functionDescriptor);
return context.services.checkType(functionDescriptor.getReturnType(), arrayAccessExpression, context); return context.services.checkType(functionDescriptor.getReturnType(), arrayAccessExpression, context);
@@ -3,7 +3,9 @@ package org.jetbrains.jet.resolve;
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.*;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@@ -128,7 +130,7 @@ public class DescriptorRenderer {
@Override @Override
public Void visitVariableDescriptor(VariableDescriptor descriptor, StringBuilder builder) { public Void visitVariableDescriptor(VariableDescriptor descriptor, StringBuilder builder) {
String typeString = renderPropertyPrefixAndComputeTypeString(builder, Collections.<TypeParameterDescriptor>emptyList(), null, descriptor.getOutType(), descriptor.getInType()); String typeString = renderPropertyPrefixAndComputeTypeString(builder, Collections.<TypeParameterDescriptor>emptyList(), ReceiverDescriptor.NO_RECEIVER, descriptor.getOutType(), descriptor.getInType());
renderName(descriptor, builder); renderName(descriptor, builder);
builder.append(" : ").append(escape(typeString)); builder.append(" : ").append(escape(typeString));
return super.visitVariableDescriptor(descriptor, builder); return super.visitVariableDescriptor(descriptor, builder);
@@ -137,7 +139,7 @@ public class DescriptorRenderer {
private String renderPropertyPrefixAndComputeTypeString( private String renderPropertyPrefixAndComputeTypeString(
@NotNull StringBuilder builder, @NotNull StringBuilder builder,
@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<TypeParameterDescriptor> typeParameters,
@Nullable JetType receiverType, @NotNull ReceiverDescriptor receiver,
@Nullable JetType outType, @Nullable JetType outType,
@Nullable JetType inType) { @Nullable JetType inType) {
String typeString = lt() + "no type>"; String typeString = lt() + "no type>";
@@ -161,8 +163,8 @@ public class DescriptorRenderer {
renderTypeParameters(typeParameters, builder); renderTypeParameters(typeParameters, builder);
if (receiverType != null) { if (receiver.exists()) {
builder.append(escape(renderType(receiverType))).append("."); builder.append(escape(renderType(receiver.getType()))).append(".");
} }
return typeString; return typeString;
@@ -172,7 +174,7 @@ public class DescriptorRenderer {
public Void visitPropertyDescriptor(PropertyDescriptor descriptor, StringBuilder builder) { public Void visitPropertyDescriptor(PropertyDescriptor descriptor, StringBuilder builder) {
String typeString = renderPropertyPrefixAndComputeTypeString( String typeString = renderPropertyPrefixAndComputeTypeString(
builder, descriptor.getTypeParameters(), builder, descriptor.getTypeParameters(),
descriptor.getReceiverType(), descriptor.getReceiver(),
descriptor.getOutType(), descriptor.getOutType(),
descriptor.getInType()); descriptor.getInType());
renderName(descriptor, builder); renderName(descriptor, builder);
@@ -185,9 +187,9 @@ public class DescriptorRenderer {
builder.append(renderKeyword("fun")).append(" "); builder.append(renderKeyword("fun")).append(" ");
renderTypeParameters(descriptor.getTypeParameters(), builder); renderTypeParameters(descriptor.getTypeParameters(), builder);
JetType receiverType = descriptor.getReceiverType(); ReceiverDescriptor receiver = descriptor.getReceiver();
if (receiverType != null) { if (receiver.exists()) {
builder.append(escape(renderType(receiverType))).append("."); builder.append(escape(renderType(receiver.getType()))).append(".");
} }
renderName(descriptor, builder); renderName(descriptor, builder);
Binary file not shown.
@@ -89,7 +89,7 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
JetFile file = (JetFile) getElement().getContainingFile(); JetFile file = (JetFile) getElement().getContainingFile();
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file); BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
Collection<? extends DeclarationDescriptor> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression); Collection<? extends DeclarationDescriptor> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression);
if (declarationDescriptors != null) return ResolveResult.EMPTY_ARRAY; if (declarationDescriptors == null) return ResolveResult.EMPTY_ARRAY;
ResolveResult[] results = new ResolveResult[declarationDescriptors.size()]; ResolveResult[] results = new ResolveResult[declarationDescriptors.size()];
int i = 0; int i = 0;
for (DeclarationDescriptor descriptor : declarationDescriptors) { for (DeclarationDescriptor descriptor : declarationDescriptors) {
@@ -3,7 +3,7 @@ fun text() {
"direct:a" on {it.body == "<hello/>"} to "mock:a" "direct:a" on {it.body == "<hello/>"} to "mock:a"
"direct:a" on {it => it.body == "<hello/>"} to "mock:a" "direct:a" on {it => it.body == "<hello/>"} to "mock:a"
bar <!TYPE_MISMATCH!>{1}<!> bar <!TYPE_MISMATCH!>{1}<!>
bar <!TYPE_MISMATCH!>{<!UNRESOLVED_REFERENCE!>it<!> <!UNRESOLVED_REFERENCE!>+<!> 1}<!> bar <!TYPE_MISMATCH!>{<!UNRESOLVED_REFERENCE!>it<!> + 1}<!>
bar {it, it1 => it} bar {it, it1 => it}
bar1 {1} bar1 {1}
@@ -0,0 +1,22 @@
// KT-306 Ambiguity when different this's have same-looking functions
fun test() {
{Foo.() =>
bar()
{Barr.() =>
this.bar()
bar()
}
}
{Barr.() =>
bar()
}
}
class Foo {
fun bar() {}
}
class Barr {
fun bar() {}
}
@@ -0,0 +1,11 @@
// KT-307 Unresolved reference
open class AL {
fun get(i : Int) : Any? = i
}
trait ALE<T> : AL {
fun getOrNull(index: Int, value: T) : T {
return get(index) as? T ?: value
}
}
@@ -167,6 +167,7 @@ fun t26 () : Boolean {
} }
fun box() : String { fun box() : String {
/*
if(!t1()) { if(!t1()) {
return "t1 failed" return "t1 failed"
} }
@@ -242,6 +243,7 @@ fun box() : String {
if(!t25()) { if(!t25()) {
return "t25 failed" return "t25 failed"
} }
*/
if(!t26()) { if(!t26()) {
return "t26 failed" return "t26 failed"
} }
+9 -3
View File
@@ -3,13 +3,19 @@ trait AL {
} }
trait ALE<T> : AL { trait ALE<T> : AL {
fun getOrNull(index: Int, value : T) = get(index) as? T ?: value fun getOrNull(index: Int, value: T) : T {
val r = get(index) as? T
return r ?: value
}
} }
class SmartArrayList() : ALE<String> { open class SmartArrayList() : ALE<String> {
}
class SmartArrayList2() : SmartArrayList(), AL {
} }
fun box() : String { fun box() : String {
val c = SmartArrayList() val c = SmartArrayList2()
return if("239" == c.getOrNull(0, "239")) "OK" else "fail" return if("239" == c.getOrNull(0, "239")) "OK" else "fail"
} }
-2
View File
@@ -1,2 +0,0 @@
val x = 1 : Int?:Any?
val y = null ?: 1
-48
View File
@@ -1,48 +0,0 @@
JetFile: ElvisSplit.jet
NAMESPACE
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('x')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
BINARY_WITH_TYPE
BINARY_WITH_TYPE
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiElement(QUEST)('?')
OPERATION_REFERENCE
PsiElement(COLON)(':')
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Any')
PsiElement(QUEST)('?')
PsiWhiteSpace('\n')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('y')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
BINARY_EXPRESSION
NULL
PsiElement(null)('null')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(ELVIS)('?:')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
@@ -17,7 +17,7 @@ public class TraitsTest extends CodegenTestCase {
} }
public void testMultiple () throws Exception { public void testMultiple () throws Exception {
// blackBoxFile("traits/multiple.jet"); blackBoxFile("traits/multiple.jet");
// System.out.println(generateToText()); System.out.println(generateToText());
} }
} }
@@ -16,6 +16,7 @@ import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.BindingTraceContext; import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResult; import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResult;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.parsing.JetParsingTest; import org.jetbrains.jet.parsing.JetParsingTest;
@@ -106,7 +107,8 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
List<JetType> parameterTypeList = Arrays.asList(parameterType); List<JetType> parameterTypeList = Arrays.asList(parameterType);
JetTypeInferrer.Services typeInferrerServices = JetSemanticServices.createSemanticServices(getProject()).getTypeInferrerServices(new BindingTraceContext(), JetFlowInformationProvider.NONE); JetTypeInferrer.Services typeInferrerServices = JetSemanticServices.createSemanticServices(getProject()).getTypeInferrerServices(new BindingTraceContext(), JetFlowInformationProvider.NONE);
OverloadResolutionResult<FunctionDescriptor> functions = typeInferrerServices.getCallResolver().resolveExactSignature(classDescriptor.getMemberScope(typeArguments), null, name, parameterTypeList); OverloadResolutionResult<FunctionDescriptor> functions = typeInferrerServices.getCallResolver().resolveExactSignature(
classDescriptor.getMemberScope(typeArguments), ReceiverDescriptor.NO_RECEIVER, name, parameterTypeList);
for (FunctionDescriptor function : functions.getDescriptors()) { for (FunctionDescriptor function : functions.getDescriptors()) {
List<ValueParameterDescriptor> unsubstitutedValueParameters = function.getValueParameters(); List<ValueParameterDescriptor> unsubstitutedValueParameters = function.getValueParameters();
for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) { for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
@@ -18,7 +18,7 @@ import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.java.JavaPackageScope; import org.jetbrains.jet.lang.resolve.java.JavaPackageScope;
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
import org.jetbrains.jet.lang.resolve.scopes.*; import org.jetbrains.jet.lang.resolve.scopes.*;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExplicitReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
@@ -504,13 +504,13 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
assertTrue("Error type expected but " + type + " returned", ErrorUtils.isErrorType(type)); assertTrue("Error type expected but " + type + " returned", ErrorUtils.isErrorType(type));
} }
private void assertType(String contextType, String expression, String expectedType) { private void assertType(String contextType, final String expression, String expectedType) {
final JetType thisType = makeType(contextType); final JetType thisType = makeType(contextType);
JetScope scope = new JetScopeAdapter(classDefinitions.BASIC_SCOPE) { JetScope scope = new JetScopeAdapter(classDefinitions.BASIC_SCOPE) {
@NotNull @NotNull
@Override @Override
public ReceiverDescriptor getImplicitReceiver() { public ReceiverDescriptor getImplicitReceiver() {
return new ExplicitReceiver(thisType); return new ExpressionReceiver(JetPsiFactory.createExpression(getProject(), expression), thisType);
} }
}; };
assertType(scope, expression, expectedType); assertType(scope, expression, expectedType);
+348 -192
View File
@@ -1,5 +1,6 @@
package jet.typeinfo; package jet.typeinfo;
import com.sun.org.apache.bcel.internal.generic.MethodGen;
import jet.JetObject; import jet.JetObject;
import jet.Tuple0; import jet.Tuple0;
@@ -38,25 +39,8 @@ public abstract class TypeInfo<T> implements JetObject {
public static final TypeInfo<String> NULLABLE_STRING_TYPE_INFO = getTypeInfo(String.class, true); public static final TypeInfo<String> NULLABLE_STRING_TYPE_INFO = getTypeInfo(String.class, true);
public static final TypeInfo<Tuple0> NULLABLE_TUPLE0_TYPE_INFO = getTypeInfo(Tuple0.class, true); public static final TypeInfo<Tuple0> NULLABLE_TUPLE0_TYPE_INFO = getTypeInfo(Tuple0.class, true);
private TypeInfo<?> typeInfo;
private final Signature signature;
private final boolean nullable;
private final TypeInfoProjection[] projections;
private TypeInfo(Class<T> theClass, boolean nullable) {
this(theClass, nullable, EMPTY);
}
private TypeInfo(Class<T> theClass, boolean nullable, TypeInfoProjection[] projections) {
this.signature = Parser.parse(theClass);
this.nullable = nullable;
this.projections = projections;
if(signature.variables.size() != projections.length)
throw new IllegalStateException("Wrong signature " + theClass.getName());
}
public static <T> TypeInfoProjection invariantProjection(final TypeInfo<T> typeInfo) { public static <T> TypeInfoProjection invariantProjection(final TypeInfo<T> typeInfo) {
return (TypeInfoImpl) typeInfo; return (TypeInfoProjection) typeInfo;
} }
public static <T> TypeInfoProjection inProjection(TypeInfo<T> typeInfo) { public static <T> TypeInfoProjection inProjection(TypeInfo<T> typeInfo) {
@@ -87,103 +71,196 @@ public abstract class TypeInfo<T> implements JetObject {
return new TypeInfoImpl<T>(klazz, nullable, projections); return new TypeInfoImpl<T>(klazz, nullable, projections);
} }
public final Object getClassObject() { public abstract Object getClassObject();
try {
final Class implClass = signature.klazz.getClassLoader().loadClass(signature.klazz.getCanonicalName());
final Field classobj = implClass.getField("$classobj");
return classobj.get(null);
} catch (Exception e) {
return null;
}
}
public final boolean isInstance(Object obj) { public abstract boolean isInstance(Object obj);
if (obj == null) return nullable;
if (obj instanceof JetObject) { public abstract int getProjectionCount();
return ((JetObject) obj).getTypeInfo().isSubtypeOf(this);
public abstract TypeInfoProjection getProjection(int index);
public abstract TypeInfo getArgumentType(Class klass, int index);
public abstract TypeInfo substitute(List<TypeInfo> myVars);
private static class TypeInfoVar<T> extends TypeInfo<T> {
final int varIndex;
final boolean nullable;
private TypeInfoVar(Integer varIndex) {
this.varIndex = varIndex;
nullable = false;
} }
return signature.klazz.isAssignableFrom(obj.getClass()); // TODO public TypeInfoVar(boolean nullable, Integer varIndex) {
} this.nullable = nullable;
this.varIndex = varIndex;
public final boolean isSubtypeOf(TypeInfo<?> superType) {
if (nullable && !superType.nullable) {
return false;
} }
if (!superType.signature.klazz.isAssignableFrom(signature.klazz)) {
return false; @Override
public Object getClassObject() {
throw new UnsupportedOperationException("Abstract TypeInfo");
} }
if (superType.projections == null || superType.projections.length != projections.length) {
throw new IllegalArgumentException("inconsistent type infos for the same class"); @Override
public boolean isInstance(Object obj) {
throw new UnsupportedOperationException("Abstract TypeInfo");
} }
for (int i = 0; i < projections.length; i++) {
// TODO handle variance here @Override
if (!projections[i].equals(superType.projections[i])) { public int getProjectionCount() {
return false; return 0;
}
} }
return true;
}
public final TypeInfoProjection getProjection(int index) { @Override
return projections[index]; public TypeInfoProjection getProjection(int index) {
} throw new UnsupportedOperationException("Abstract TypeInfo");
public final TypeInfo getArgumentType(int index) {
return projections[index].getType();
}
@Override
public final TypeInfo<?> getTypeInfo() {
if (typeInfo == null) {
// TODO: Implementation must be lazy, otherwise the result would be of an infinite size
throw new UnsupportedOperationException(); // TODO
} }
return typeInfo;
}
@Override @Override
public final boolean equals(Object o) { public TypeInfo getArgumentType(Class klass, int index) {
if (this == o) return true; throw new UnsupportedOperationException("Abstract TypeInfo");
if (o == null || getClass() != o.getClass()) return false; }
TypeInfo typeInfo = (TypeInfo) o; @Override
public TypeInfo substitute(List<TypeInfo> myVars) {
if (!signature.klazz.equals(typeInfo.signature.klazz)) return false; return myVars.get(varIndex);
if (nullable != typeInfo.nullable) return false; }
if (!Arrays.equals(projections, typeInfo.projections)) return false;
@Override
return true; protected TypeInfo substitute(TypeInfoProjection[] projections) {
} return projections[varIndex].getType();
}
@Override
public final int hashCode() { @Override
return 31 * signature.klazz.hashCode() + Arrays.hashCode(projections); public TypeInfo<?> getTypeInfo() {
} throw new UnsupportedOperationException("Abstract TypeInfo");
}
@Override
public final String toString() { @Override
StringBuilder sb = new StringBuilder().append(signature.klazz.getName()); public String toString() {
if (projections.length != 0) { return "T:" + varIndex;
sb.append("<");
for (int i = 0; i != projections.length - 1; ++i) {
sb.append(projections[i].toString()).append(",");
}
sb.append(projections[projections.length - 1].toString()).append(">");
} }
if (nullable)
sb.append("?");
return sb.toString();
} }
private static class TypeInfoImpl<T> extends TypeInfo<T> implements TypeInfoProjection { private static class TypeInfoImpl<T> extends TypeInfo<T> implements TypeInfoProjection {
TypeInfoImpl(Class<T> klazz, boolean nullable) { private TypeInfo<?> typeInfo;
super(klazz, nullable); private final Signature signature;
private final boolean nullable;
private final TypeInfoProjection[] projections;
TypeInfoImpl(Class<T> theClass, boolean nullable) {
this(theClass, nullable, EMPTY);
} }
TypeInfoImpl(Class<T> klazz, boolean nullable, TypeInfoProjection[] projections) { private TypeInfoImpl(Class<T> theClass, boolean nullable, TypeInfoProjection[] projections) {
super(klazz, nullable, projections); this.signature = Parser.parse(theClass);
this.nullable = nullable;
this.projections = projections;
if(signature.variables.size() != projections.length)
throw new IllegalStateException("Wrong signature " + theClass.getName());
}
public final TypeInfoProjection getProjection(int index) {
return projections[index];
}
public final Object getClassObject() {
try {
final Class implClass = signature.klazz.getClassLoader().loadClass(signature.klazz.getCanonicalName());
final Field classobj = implClass.getField("$classobj");
return classobj.get(null);
} catch (Exception e) {
return null;
}
}
TypeInfo getSuperTypeInfo(Class klass) {
return signature.superSignatures.get(klass);
}
public final TypeInfo getArgumentType(Class klass, int index) {
if(klass == this.signature.klazz)
return projections[index].getType();
else {
return getSuperTypeInfo(klass).substitute(projections).getArgumentType(klass, index);
}
}
@Override
public TypeInfo substitute(final List<TypeInfo> myVars) {
if(projections.length == 0)
return new TypeInfoImpl(signature.klazz, nullable, EMPTY);
else {
TypeInfoProjection [] proj = new TypeInfoProjection[projections.length];
for(int i = 0; i != proj.length; ++i) {
final int finalI = i;
final TypeInfo substitute = projections[finalI].getType().substitute(myVars);
proj[i] = new TypeInfoProjection(){
@Override
public TypeInfoVariance getVariance() {
return projections[finalI].getVariance();
}
@Override
public TypeInfo getType() {
return substitute;
}
@Override
public String toString() {
return getVariance().toString() + " " + substitute;
}
};
}
return new TypeInfoImpl(signature.klazz, nullable, proj);
}
}
@Override
protected TypeInfo substitute(TypeInfoProjection[] prj) {
if(projections.length == 0)
return new TypeInfoImpl(signature.klazz, nullable, EMPTY);
else {
TypeInfoProjection [] proj = new TypeInfoProjection[projections.length];
for(int i = 0; i != proj.length; ++i) {
final int finalI = i;
final TypeInfo substitute = projections[finalI].getType().substitute(prj);
proj[i] = new TypeInfoProjection(){
@Override
public TypeInfoVariance getVariance() {
return projections[finalI].getVariance();
}
@Override
public TypeInfo getType() {
return substitute;
}
@Override
public String toString() {
return getVariance().toString() + " " + substitute;
}
};
}
return new TypeInfoImpl(signature.klazz, nullable, proj);
}
}
@Override
public final boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TypeInfoImpl typeInfo = (TypeInfoImpl) o;
if (!signature.klazz.equals(typeInfo.signature.klazz)) return false;
if (nullable != typeInfo.nullable) return false;
if (!Arrays.equals(projections, typeInfo.projections)) return false;
return true;
} }
// @NotNull // @NotNull
@@ -197,81 +274,116 @@ public abstract class TypeInfo<T> implements JetObject {
public TypeInfo getType() { public TypeInfo getType() {
return this; return this;
} }
@Override
public final int hashCode() {
return 31 * signature.klazz.hashCode() + Arrays.hashCode(projections);
}
public final boolean isInstance(Object obj) {
if (obj == null) return nullable;
if (obj instanceof JetObject) {
return ((TypeInfoImpl)((JetObject) obj).getTypeInfo()).isSubtypeOf(this);
}
return signature.klazz.isAssignableFrom(obj.getClass()); // TODO
}
@Override
public int getProjectionCount() {
return projections.length;
}
@Override
public final String toString() {
StringBuilder sb = new StringBuilder().append(signature.klazz.getName());
if (projections.length != 0) {
sb.append("<");
for (int i = 0; i != projections.length - 1; ++i) {
sb.append(projections[i].toString()).append(",");
}
sb.append(projections[projections.length - 1].toString()).append(">");
}
if (nullable)
sb.append("?");
return sb.toString();
}
@Override
public final TypeInfo<?> getTypeInfo() {
if (typeInfo == null) {
// TODO: Implementation must be lazy, otherwise the result would be of an infinite size
throw new UnsupportedOperationException(); // TODO
}
return typeInfo;
}
public final boolean isSubtypeOf(TypeInfoImpl<?> superType) {
if (nullable && !superType.nullable) {
return false;
}
if (!superType.signature.klazz.isAssignableFrom(signature.klazz)) {
return false;
}
if (superType.projections == null || superType.projections.length != projections.length) {
throw new IllegalArgumentException("inconsistent type infos for the same class");
}
for (int i = 0; i < projections.length; i++) {
// TODO handle variance here
if (!projections[i].getType().equals(superType.projections[i].getType())) {
return false;
}
}
return true;
}
} }
protected abstract TypeInfo substitute(TypeInfoProjection[] projections);
public static class Signature { public static class Signature {
final Class klazz; final Class klazz;
final List<Var> variables; final List<TypeInfoProjection> variables;
final List<Type> superTypes; final List<TypeInfo> superTypes;
final HashMap<Class,Signature> superSignatures = new HashMap<Class,Signature>(); final HashMap<Class,TypeInfo> superSignatures = new HashMap<Class,TypeInfo>();
public Signature(Class klazz, List<Var> variables, List<Type> superTypes) { public Signature(Class klazz, List<TypeInfoProjection> variables, List<TypeInfo> superTypes) {
this.klazz = klazz; this.klazz = klazz;
this.superTypes = superTypes; this.superTypes = superTypes;
this.variables = variables; this.variables = variables;
for(Type superType : superTypes) { List<TypeInfo> myVars = variables == null ? Collections.<TypeInfo>emptyList() : new LinkedList<TypeInfo>();
if(superType instanceof TypeReal) { if(variables != null)
TypeReal type = (TypeReal) superType; for(int i = 0; i != variables.size(); ++i)
Signature parse = Parser.parse(type.klazz); myVars.add(new TypeInfoVar(false, i));
superSignatures.put(type.klazz, parse);
for(Map.Entry<Class,Signature> entry : parse.superSignatures.entrySet()) { for(TypeInfo superType : superTypes) {
superSignatures.put(entry.getKey(), entry.getValue()); if(superType instanceof TypeInfoImpl) {
TypeInfoImpl type = (TypeInfoImpl) superType;
Signature superSignature = Parser.parse(type.signature.klazz);
TypeInfo substituted = type.substitute(myVars);
superSignatures.put(type.signature.klazz, substituted);
List<TypeInfo> vars = Collections.emptyList();
if(superType.getProjectionCount() != 0) {
vars = new LinkedList<TypeInfo>();
for(int i=0; i != superType.getProjectionCount(); ++i) {
TypeInfo substitute = superType.getProjection(i).getType().substitute(myVars);
vars.add(substitute);
}
}
for(Map.Entry<Class,TypeInfo> entry : superSignature.superSignatures.entrySet()) {
superSignatures.put(entry.getKey(), entry.getValue().substitute(vars));
} }
} }
} }
} }
} }
public static class Var {
final String name;
final TypeInfoVariance variance;
public Var(String name, TypeInfoVariance variance) {
this.name = name;
this.variance = variance;
}
}
public abstract static class Type{
final boolean nullable;
protected Type(boolean nullable) {
this.nullable = nullable;
}
}
public static class TypeVar extends Type {
final int varIndex;
public TypeVar(boolean nullable, int varIndex) {
super(nullable);
this.varIndex = varIndex;
}
}
public static class TypeProj {
public final TypeInfoVariance variance;
public final Type type;
public TypeProj(TypeInfoVariance variance, Type type) {
this.variance = variance;
this.type = type;
}
}
public static class TypeReal extends Type {
public final Class klazz;
public final List<TypeProj> params;
public TypeReal(Class klazz, boolean nullable, List<TypeProj> params) {
super(nullable);
this.params = params;
this.klazz = klazz;
}
}
public static class Parser { public static class Parser {
static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
static final WeakHashMap<Class,Signature> map = new WeakHashMap<Class,Signature>(); static final WeakHashMap<Class,Signature> map = new WeakHashMap<Class,Signature>();
@@ -323,49 +435,76 @@ public abstract class TypeInfo<T> implements JetObject {
TypeVariable[] typeParameters = klass.getTypeParameters(); TypeVariable[] typeParameters = klass.getTypeParameters();
Map<String,Integer> variables; Map<String,Integer> variables;
List<Var> vars; List<TypeInfoProjection> vars;
if(typeParameters == null || typeParameters.length == 0) { if(typeParameters == null || typeParameters.length == 0) {
variables = Collections.emptyMap(); variables = Collections.emptyMap();
vars = Collections.emptyList(); vars = Collections.emptyList();
} }
else { else {
variables = new HashMap<String, Integer>(); variables = new HashMap<String, Integer>();
vars = new LinkedList<Var>(); vars = new LinkedList<TypeInfoProjection>();
for (int i = 0; i < typeParameters.length; i++) { for (int i = 0; i < typeParameters.length; i++) {
TypeVariable typeParameter = typeParameters[i]; TypeVariable typeParameter = typeParameters[i];
variables.put(typeParameter.getName(), i); variables.put(typeParameter.getName(), i);
vars.add(new Var(typeParameter.getName(), TypeInfoVariance.INVARIANT)); final TypeInfoVar typeInfoVar = new TypeInfoVar(false, i);
vars.add(new TypeInfoProjection(){
@Override
public TypeInfoVariance getVariance() {
return TypeInfoVariance.INVARIANT;
}
@Override
public TypeInfo getType() {
return typeInfoVar;
}
@Override
public String toString() {
return typeInfoVar.toString();
}
});
} }
} }
List<Type> types = new LinkedList<Type>(); List<TypeInfo> types = new LinkedList<TypeInfo>();
java.lang.reflect.Type genericSuperclass = klass.getGenericSuperclass(); java.lang.reflect.Type genericSuperclass = klass.getGenericSuperclass();
return new Signature(klass, vars, types); return new Signature(klass, vars, types);
} }
public List<Var> parseVars() { public List<TypeInfoProjection> parseVars() {
List<Var> list = null; List<TypeInfoProjection> list = null;
while(cur != string.length && string[cur] == 'T') { while(cur != string.length && string[cur] == 'T') {
if(list == null) if(list == null) {
list = new LinkedList<Var>(); list = new LinkedList<TypeInfoProjection>();
variables = new HashMap<String, Integer>();
}
list.add(parseVar()); list.add(parseVar());
} }
List<Var> vars = list == null ? Collections.<Var>emptyList() : list; return list == null ? Collections.<TypeInfoProjection>emptyList() : list;
if(vars.isEmpty())
variables = Collections.emptyMap();
else {
variables = new HashMap<String, Integer>();
for(int i=0; i != list.size(); ++i) {
variables.put(list.get(i).name, i);
}
}
return vars;
} }
private Var parseVar() { private TypeInfoProjection parseVar() {
TypeInfoVariance variance = parseVariance(); final TypeInfoVariance variance = parseVariance();
String name = parseName(); String name = parseName();
return new Var(name, variance); final TypeInfoVar typeInfoVar = new TypeInfoVar(variables.size());
variables.put(name, variables.size());
return new TypeInfoProjection(){
@Override
public TypeInfoVariance getVariance() {
return variance;
}
@Override
public TypeInfo getType() {
return typeInfoVar;
}
@Override
public String toString() {
return typeInfoVar.toString();
}
};
} }
private String parseName() { private String parseName() {
@@ -392,18 +531,18 @@ public abstract class TypeInfo<T> implements JetObject {
} }
} }
public List<Type> parseTypes() { public List<TypeInfo> parseTypes() {
List<Type> types = null; List<TypeInfo> types = null;
while(cur != string.length) { while(cur != string.length) {
if(types == null) { if(types == null) {
types = new LinkedList<Type>(); types = new LinkedList<TypeInfo>();
} }
types.add(parseType()); types.add(parseType());
} }
return types == null ? Collections.<Type>emptyList() : types; return types == null ? Collections.<TypeInfo>emptyList() : types;
} }
private Type parseType() { private TypeInfo parseType() {
switch (string[cur]) { switch (string[cur]) {
case 'L': case 'L':
String name = parseName(); String name = parseName();
@@ -413,13 +552,13 @@ public abstract class TypeInfo<T> implements JetObject {
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
List<TypeProj> proj = null; List<TypeInfoProjection> proj = null;
boolean nullable = false; boolean nullable = false;
if(cur != string.length && string[cur] == '<') { if(cur != string.length && string[cur] == '<') {
cur++; cur++;
while(string[cur] != '>') { while(string[cur] != '>') {
if(proj == null) if(proj == null)
proj = new LinkedList<TypeProj>(); proj = new LinkedList<TypeInfoProjection>();
proj.add(parseProjection()); proj.add(parseProjection());
} }
cur++; cur++;
@@ -428,7 +567,9 @@ public abstract class TypeInfo<T> implements JetObject {
cur++; cur++;
nullable = true; nullable = true;
} }
return new TypeReal(aClass, nullable, proj == null ? Collections.<TypeProj>emptyList() : proj); if(proj == null)
proj = Collections.emptyList();
return new TypeInfoImpl(aClass, nullable,proj.toArray(new TypeInfoProjection[proj.size()]));
case 'T': case 'T':
return parseTypeVar(); return parseTypeVar();
@@ -438,7 +579,7 @@ public abstract class TypeInfo<T> implements JetObject {
} }
} }
private Type parseTypeVar() { private TypeInfo parseTypeVar() {
String name = parseName(); String name = parseName();
boolean nullable = false; boolean nullable = false;
if(string[cur] == '?') { if(string[cur] == '?') {
@@ -446,13 +587,28 @@ public abstract class TypeInfo<T> implements JetObject {
cur++; cur++;
} }
return new TypeVar(nullable, variables.get(name)); return new TypeInfoVar(nullable, variables.get(name));
} }
private TypeProj parseProjection() { private TypeInfoProjection parseProjection() {
TypeInfoVariance variance = parseVariance(); final TypeInfoVariance variance = parseVariance();
Type type = parseType(); final TypeInfo type = parseType();
return new TypeProj(variance, type); return new TypeInfoProjection(){
@Override
public TypeInfoVariance getVariance() {
return variance;
}
@Override
public TypeInfo getType() {
return type;
}
@Override
public String toString() {
return type.toString();
}
};
} }
} }
} }
@@ -1,5 +1,7 @@
package jet.typeinfo; package jet.typeinfo;
import java.util.List;
/** /**
* @author alex.tkachman * @author alex.tkachman
*/ */