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.FunctionDescriptor;
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.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
@@ -72,7 +73,7 @@ public class ClassContext {
thisIdx++;
}
final boolean hasReceiver = descriptor.getReceiverType() != null;
final boolean hasReceiver = descriptor.getReceiver().exists();
if (hasReceiver) {
thisIdx++;
}
@@ -102,12 +103,12 @@ public class ClassContext {
return frameMap;
}
private JetType receiverType() {
return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiverType() : null;
private ReceiverDescriptor receiver() {
return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiver() : ReceiverDescriptor.NO_RECEIVER;
}
private boolean hasReceiver() {
return receiverType() != null;
return receiver().exists();
}
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.JetFunctionLiteralExpression;
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.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
@@ -41,7 +42,7 @@ public class ClosureCodegen {
}
public static Method erasedInvokeSignature(FunctionDescriptor fd) {
boolean isExtensionFunction = fd.getReceiverType() != null;
boolean isExtensionFunction = fd.getReceiver().exists();
int paramCount = fd.getValueParameters().size();
if (isExtensionFunction) {
paramCount++;
@@ -150,11 +151,11 @@ public class ClosureCodegen {
iv.load(0, Type.getObjectType(className));
final JetType receiverType = funDescriptor.getReceiverType();
final ReceiverDescriptor receiver = funDescriptor.getReceiver();
int count = 1;
if (receiverType != null) {
if (receiver.exists()) {
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++;
}
@@ -228,7 +229,7 @@ public class ClosureCodegen {
public static String getInternalClassName(FunctionDescriptor descriptor) {
final int paramCount = descriptor.getValueParameters().size();
if (descriptor.getReceiverType() != null) {
if (descriptor.getReceiver().exists()) {
return "jet/ExtensionFunction" + paramCount;
}
else {
@@ -249,7 +250,7 @@ public class ClosureCodegen {
Method descriptor = erasedInvokeSignature(fd);
String owner = getInternalClassName(fd);
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.requestGenerateCallee(Type.getObjectType(getInternalClassName(fd)));
@@ -82,17 +82,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
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) {
markLineNumber(selector);
return selector.visit(this, receiver);
@@ -2033,9 +2022,26 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
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.invokevirtual("jet/typeinfo/TypeInfo", "getArgumentType", "(I)Ljet/typeinfo/TypeInfo;");
v.invokevirtual("jet/typeinfo/TypeInfo", "getArgumentType", "(Ljava/lang/Class;I)Ljet/typeinfo/TypeInfo;");
return;
}
throw new UnsupportedOperationException("don't know what this type parameter resolves to");
@@ -141,7 +141,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override
protected void generateSyntheticParts() {
generateFieldForTypeInfo();
generateFieldForObjectInstance();
generateFieldForClassObject();
@@ -156,25 +155,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
//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() {
if (isNonLiteralObject()) {
Type type = JetTypeMapper.jetImplementationType(descriptor);
@@ -397,6 +377,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
else if(psiElement instanceof PsiClass) {
// todo
PsiClass psiClass = (PsiClass) psiElement;
}
}
@@ -550,7 +531,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.astore(JetTypeMapper.TYPE_OBJECT);
}
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) {
@@ -648,21 +629,79 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if(myClass instanceof JetClass && ((JetClass)myClass).isTrait())
return;
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC,
"getTypeInfo",
"()Ljet/typeinfo/TypeInfo;",
null /* TODO */,
null);
mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv);
ExpressionCodegen.loadTypeInfo(state.getTypeMapper(), descriptor, v);
v.areturn(JetTypeMapper.TYPE_TYPEINFO);
mv.visitMaxs(0, 0);
mv.visitEnd();
JetType defaultType = descriptor.getDefaultType();
if(isParametrizedClass(defaultType)) {
if(!hasDerivedTypeInfoField(defaultType, true)) {
v.visitField(Opcodes.ACC_PRIVATE, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
iv.load(0, JetTypeMapper.TYPE_OBJECT);
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) {
state.forClass().generate(context, declaration.getObjectDeclaration());
state.forClass().generate(context, declaration.getObjectDeclaration());
}
private void genGetSuperTypesTypeInfo() {
@@ -710,4 +749,31 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
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.psi.*;
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.lexer.JetTokens;
import org.jetbrains.jet.resolve.DescriptorRenderer;
@@ -514,11 +515,11 @@ public class JetTypeMapper {
}
public Method mapSignature(String name, FunctionDescriptor f) {
final JetType receiverType = f.getReceiverType();
final ReceiverDescriptor receiver = f.getReceiver();
final List<ValueParameterDescriptor> parameters = f.getValueParameters();
List<Type> parameterTypes = new ArrayList<Type>();
if (receiverType != null) {
parameterTypes.add(mapType(receiverType));
if (receiver.exists()) {
parameterTypes.add(mapType(receiver.getType()));
}
for (ValueParameterDescriptor parameter : parameters) {
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.psi.*;
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.lexer.JetTokens;
import org.objectweb.asm.ClassVisitor;
@@ -42,7 +43,7 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
}
}
}
return null;
return JetStandardClasses.getAnyType();
}
@Override
@@ -60,9 +61,4 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
private String jvmName() {
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.resolve.scopes.JetScope;
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 java.util.Collections;
@@ -23,6 +25,7 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
private Modality modality;
private JetType superclassType;
private final ClassKind kind;
private ClassReceiver implicitReceiver;
public JavaClassDescriptor(DeclarationDescriptor containingDeclaration, @NotNull ClassKind kind) {
@@ -155,4 +158,13 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
public String toString() {
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
}
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;
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.TypeSubstitutor;
@@ -12,8 +13,8 @@ import java.util.Set;
* @author abreslav
*/
public interface CallableDescriptor extends DeclarationDescriptor {
@Nullable
JetType getReceiverType();
@NotNull
ReceiverDescriptor getReceiver();
@NotNull
List<TypeParameterDescriptor> getTypeParameters();
@@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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.TypeProjection;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
@@ -53,4 +54,7 @@ public interface ClassDescriptor extends ClassifierDescriptor {
@NotNull
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.resolve.scopes.JetScope;
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 java.util.Collection;
@@ -21,6 +23,7 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
private FunctionGroup constructors;
private ConstructorDescriptor primaryConstructor;
private JetType superclassType;
private ReceiverDescriptor implicitReceiver;
public ClassDescriptorImpl(
@NotNull DeclarationDescriptor containingDeclaration,
@@ -151,4 +154,13 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
public Modality getModality() {
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.Nullable;
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.JetType;
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.Set;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
/**
* @author abreslav
*/
@@ -21,7 +25,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
private List<TypeParameterDescriptor> typeParameters;
private List<ValueParameterDescriptor> unsubstitutedValueParameters;
private JetType unsubstitutedReturnType;
private JetType receiverType;
private ReceiverDescriptor receiver;
private Modality modality;
private final Set<FunctionDescriptor> overriddenFunctions = Sets.newLinkedHashSet();
@@ -49,11 +53,11 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
@Nullable JetType unsubstitutedReturnType,
@Nullable Modality modality) {
this.receiverType = receiverType;
this.typeParameters = typeParameters;
this.unsubstitutedValueParameters = unsubstitutedValueParameters;
this.unsubstitutedReturnType = unsubstitutedReturnType;
this.modality = modality;
this.receiver = receiverType == null ? NO_RECEIVER : new ExtensionReceiver(this, receiverType);
return this;
}
@@ -61,9 +65,10 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
this.unsubstitutedReturnType = unsubstitutedReturnType;
}
@NotNull
@Override
public JetType getReceiverType() {
return receiverType;
public ReceiverDescriptor getReceiver() {
return receiver;
}
@NotNull
@@ -116,10 +121,9 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
List<TypeParameterDescriptor> substitutedTypeParameters = Lists.newArrayList();
TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(getTypeParameters(), originalSubstitutor, substitutedDescriptor, substitutedTypeParameters);
JetType receiverType = getReceiverType();
JetType substitutedReceiverType = null;
if (receiverType != null) {
substitutedReceiverType = substitutor.substitute(receiverType, Variance.IN_VARIANCE);
if (receiver != NO_RECEIVER) {
substitutedReceiverType = substitutor.substitute(getReceiver().getType(), Variance.IN_VARIANCE);
if (substitutedReceiverType == null) {
return null;
}
@@ -5,11 +5,12 @@ import com.google.common.collect.HashBiMap;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
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.WritableScope;
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 java.util.*;
@@ -97,9 +98,9 @@ public class FunctionDescriptorUtil {
@NotNull
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");
JetType receiverType = descriptor.getReceiverType();
if (receiverType != null) {
parameterScope.setImplicitReceiver(new ExtensionCallableReceiver(descriptor));
ReceiverDescriptor receiver = descriptor.getReceiver();
if (receiver.exists()) {
parameterScope.setImplicitReceiver(receiver);
}
for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
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.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*;
import java.util.Collection;
@@ -94,6 +95,12 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
throw new UnsupportedOperationException(); // TODO
}
@NotNull
@Override
public ReceiverDescriptor getImplicitReceiver() {
throw new UnsupportedOperationException(); // TODO
}
@NotNull
@Override
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.WritableScopeImpl;
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.resolve.DescriptorRenderer;
@@ -38,6 +39,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
private JetType defaultType;
private final ClassKind kind;
private JetType superclassType;
private ClassReceiver implicitReceiver;
// public MutableClassDescriptor(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) {
// this(trace, containingDeclaration, outerScope, ClassKind.CLASS);
@@ -293,4 +295,13 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
public Collection<JetType> getSupertypes() {
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 isDefault;
private final Modality modality;
private final PropertyDescriptor correspondingProperty;
protected PropertyAccessorDescriptor(
@NotNull Modality modality,
@@ -24,6 +25,7 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm
boolean hasBody,
boolean isDefault) {
super(correspondingProperty.getContainingDeclaration(), annotations, name);
this.correspondingProperty = correspondingProperty;
this.modality = modality;
this.hasBody = hasBody;
this.isDefault = isDefault;
@@ -60,4 +62,9 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm
public Modality getModality() {
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.Nullable;
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.TypeSubstitutor;
import org.jetbrains.jet.lang.types.Variance;
@@ -17,7 +19,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member
private final Modality modality;
private final boolean isVar;
private final JetType receiverType;
private final ReceiverDescriptor receiver;
private final List<TypeParameterDescriptor> typeParemeters = Lists.newArrayListWithCapacity(0);
private final PropertyDescriptor original;
private PropertyGetterDescriptor getter;
@@ -38,7 +40,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member
// assert outType != null;
this.isVar = isVar;
this.modality = modality;
this.receiverType = receiverType;
this.receiver = receiverType == null ? ReceiverDescriptor.NO_RECEIVER : new ExtensionReceiver(this, receiverType);
this.original = original == null ? this : original.getOriginal();
}
@@ -83,9 +85,9 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member
return typeParemeters;
}
@Nullable
public JetType getReceiverType() {
return receiverType;
@NotNull
public ReceiverDescriptor getReceiver() {
return receiver;
}
@NotNull
@@ -125,10 +127,9 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member
if (inType == null && outType == null) {
return null; // TODO : tell the user that the property was projected out
}
JetType receiverType = getReceiverType();
return new PropertyDescriptor(
this,
receiverType == null ? null : substitutor.substitute(receiverType, Variance.IN_VARIANCE),
receiver.exists() ? substitutor.substitute(receiver.getType(), Variance.IN_VARIANCE) : null,
inType,
outType
);
@@ -4,6 +4,7 @@ import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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 java.util.Collections;
@@ -32,9 +33,10 @@ public class PropertyGetterDescriptor extends PropertyAccessorDescriptor {
overriddenGetters.add(overriddenGetter);
}
@NotNull
@Override
public JetType getReceiverType() {
return null; // TODO
public ReceiverDescriptor getReceiver() {
return getCorrespondingProperty().getReceiver();
}
@NotNull
@@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
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.JetType;
@@ -41,9 +42,10 @@ public class PropertySetterDescriptor extends PropertyAccessorDescriptor {
overriddenSetters.add(overriddenSetter);
}
@NotNull
@Override
public JetType getReceiverType() {
return null; // TODO
public ReceiverDescriptor getReceiver() {
return getCorrespondingProperty().getReceiver();
}
@NotNull
@@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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 java.util.Collections;
@@ -71,9 +72,10 @@ public abstract class VariableDescriptorImpl extends DeclarationDescriptorImpl i
return Collections.emptyList();
}
@NotNull
@Override
public JetType getReceiverType() {
return null;
public ReceiverDescriptor getReceiver() {
return ReceiverDescriptor.NO_RECEIVER;
}
@NotNull
@@ -106,9 +106,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
COLON_AS(COLON, AS_KEYWORD, AS_SAFE) {
@Override
public JetNodeType parseRightHandSide(IElementType operation, JetExpressionParsing parser) {
parser.myBuilder.disableJoiningComplexTokens();
parser.myJetParsing.parseTypeRef();
parser.myBuilder.enableJoiningComplexTokens();
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.resolve.constants.CompileTimeConstant;
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.JetType;
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) {
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);
}
@@ -8,6 +8,7 @@ import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
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.util.slicedmap.*;
@@ -17,6 +18,8 @@ import java.util.Collection;
* @author abreslav
*/
public interface BindingContext {
WritableSlice<JetElement, ReceiverDescriptor> RECEIVER = Slices.createSimpleSlice("RECEIVER");
WritableSlice<JetAnnotationEntry, AnnotationDescriptor> ANNOTATION = Slices.createSimpleSlice("ANNOTATION");
WritableSlice<JetExpression, CompileTimeConstant<?>> COMPILE_TIME_VALUE = Slices.createSimpleSlice("COMPILE_TIME_VALUE");
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.WritableScope;
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.lexer.JetTokens;
import org.jetbrains.jet.util.slicedmap.WritableSlice;
@@ -275,7 +275,7 @@ public class BodyResolver {
JetTypeReference typeReference = call.getTypeReference();
if (typeReference != 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) {
recordSupertype(typeReference, supertype);
ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
@@ -460,7 +460,7 @@ public class BodyResolver {
typeInferrerForInitializers.getCallResolver().resolveCall(context.getTrace(),
functionInnerScope,
null, call, NO_EXPECTED_TYPE);
ReceiverDescriptor.NO_RECEIVER, call, NO_EXPECTED_TYPE);
// call.getThisReference(),
// classDescriptor,
// classDescriptor.getDefaultType(),
@@ -575,9 +575,9 @@ public class BodyResolver {
for (TypeParameterDescriptor typeParameterDescriptor : propertyDescriptor.getTypeParameters()) {
result.addTypeParameterDescriptor(typeParameterDescriptor);
}
JetType receiverType = propertyDescriptor.getReceiverType();
if (receiverType != null) {
result.setImplicitReceiver(new ExtensionCallableReceiver(propertyDescriptor));
ReceiverDescriptor receiver = propertyDescriptor.getReceiver();
if (receiver.exists()) {
result.setImplicitReceiver(receiver);
}
return result;
}
@@ -799,15 +799,15 @@ public class BodyResolver {
boolean inTrait = classDescriptor.getKind() == ClassKind.TRAIT;
boolean inEnum = classDescriptor.getKind() == ClassKind.ENUM_CLASS;
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) {
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));
}
if (hasAbstractModifier && inTrait && !isPropertyAccessor) {
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));
}
if (function.getBodyExpression() == null && !hasAbstractModifier && !inTrait && nameIdentifier != null && !isPropertyAccessor) {
@@ -21,7 +21,7 @@ public class DescriptorUtils {
@Override
public Boolean visitFunctionDescriptor(FunctionDescriptor descriptor, Void data) {
return descriptor.getReceiverType() != null;
return descriptor.getReceiver().exists();
}
@Override
@@ -31,7 +31,7 @@ public class DescriptorUtils {
@Override
public Boolean visitPropertyDescriptor(PropertyDescriptor descriptor, Void data) {
return descriptor.getReceiverType() != null;
return descriptor.getReceiver().exists();
}
}, null);
}
@@ -13,6 +13,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
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.inference.ConstraintSystem;
@@ -20,7 +21,9 @@ import java.util.*;
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.RECEIVER;
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;
/**
@@ -42,11 +45,11 @@ public class CallResolver {
public VariableDescriptor resolveSimpleProperty(
@NotNull BindingTrace trace,
@NotNull JetScope scope,
@Nullable JetType receiverType,
@NotNull ReceiverDescriptor receiver,
@NotNull final JetSimpleNameExpression nameExpression,
@NotNull JetType expectedType) {
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);
}
@@ -55,11 +58,11 @@ public class CallResolver {
public JetType resolveCall(
@NotNull BindingTrace trace,
@NotNull JetScope scope,
@Nullable JetType receiverType,
@NotNull ReceiverDescriptor receiver,
@NotNull JetCallElement call,
@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();
}
@@ -70,11 +73,11 @@ public class CallResolver {
@NotNull final Call call,
@NotNull final JetReferenceExpression functionReference,
@NotNull String name,
@Nullable JetType receiverType,
@NotNull ReceiverDescriptor receiver,
@NotNull JetType expectedType) {
// TODO : autocasts
// 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);
}
@@ -82,7 +85,7 @@ public class CallResolver {
public FunctionDescriptor resolveSimpleCallToFunctionDescriptor(
@NotNull BindingTrace trace,
@NotNull JetScope scope,
@Nullable JetType receiverType,
@NotNull ReceiverDescriptor receiver,
@NotNull final JetCallElement call,
@NotNull JetType expectedType
) {
@@ -97,7 +100,7 @@ public class CallResolver {
String name = expression.getReferencedName();
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() {
@Override
public <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
@@ -120,7 +123,7 @@ public class CallResolver {
JetValueArgumentList valueArgumentList = call.getValueArgumentList();
ASTNode reportAbsenceOn = valueArgumentList == null ? call.getNode() : valueArgumentList.getNode();
if (calleeExpression instanceof JetConstructorCalleeExpression) {
assert receiverType == null;
assert receiver == NO_RECEIVER;
prioritizedTasks = Lists.newArrayList();
@@ -141,7 +144,7 @@ public class CallResolver {
trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
return checkArgumentTypesAndFail(trace, scope, call);
}
prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(constructors, null, call));
prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(constructors, NO_RECEIVER, call));
}
else {
// trace.getErrorHandler().genericError(calleeExpression.getNode(), "Not a class");
@@ -162,7 +165,7 @@ public class CallResolver {
trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
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 {
throw new UnsupportedOperationException("Type argument inference not implemented for " + call.getText());
@@ -190,45 +193,11 @@ public class CallResolver {
OverloadResolutionResult<D> resultForFirstNonemptyCandidateSet = null;
TracingStrategy tracing = new TracingStrategy() {
@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(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
public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<D> candidates) {
trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, candidates);
@@ -257,8 +226,8 @@ public class CallResolver {
}
@Override
public void missingReceiver(@NotNull BindingTrace trace, @NotNull JetType candidateReceiverType) {
trace.report(MISSING_RECEIVER.on(reference, candidateReceiverType));
public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver) {
trace.report(MISSING_RECEIVER.on(reference, expectedReceiver.getType()));
}
@Override
@@ -340,7 +309,7 @@ public class CallResolver {
traces.put(candidate, temporaryTrace);
JetTypeInferrer.Services temporaryServices = typeInferrer.getServices(temporaryTrace);
tracing.bindReference(temporaryTrace, candidate);
tracing.bindReference(temporaryTrace, task.getReceiver(), candidate);
if (ErrorUtils.isError(candidate)) {
successfulCandidates.put(candidate, candidate);
@@ -394,10 +363,10 @@ public class CallResolver {
checkReceiverAbsence(task, tracing, candidate, temporaryTrace);
// Error is already reported if something is missing
JetType receiverType = task.getReceiverType();
JetType candidateReceiverType = candidate.getReceiverType();
if (receiverType != null && candidateReceiverType != null) {
constraintSystem.addSubtypingConstraint(receiverType, candidateReceiverType);
ReceiverDescriptor receiver = task.getReceiver();
ReceiverDescriptor candidateReceiver = candidate.getReceiver();
if (receiver != NO_RECEIVER && candidateReceiver != NO_RECEIVER) {
constraintSystem.addSubtypingConstraint(receiver.getType(), candidateReceiver.getType());
}
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) {
if (!checkReceiverAbsence(task, tracing, candidate, temporaryTrace)) return false;
JetType receiverType = task.getReceiverType();
JetType candidateReceiverType = candidate.getReceiverType();
if (receiverType != null
&& candidateReceiverType != null
&& !semanticServices.getTypeChecker().isSubtypeOf(receiverType, candidateReceiverType)) {
tracing.missingReceiver(temporaryTrace, candidateReceiverType);
ReceiverDescriptor receiver = task.getReceiver();
ReceiverDescriptor candidateReceiver = candidate.getReceiver();
if (receiver != NO_RECEIVER
&& candidateReceiver != NO_RECEIVER
&& !semanticServices.getTypeChecker().isSubtypeOf(receiver.getType(), candidateReceiver.getType())) {
tracing.missingReceiver(temporaryTrace, candidateReceiver);
return false;
}
return true;
}
private <D extends CallableDescriptor> boolean checkReceiverAbsence(ResolutionTask<D> task, TracingStrategy tracing, D candidate, TemporaryBindingTrace temporaryTrace) {
JetType receiverType = task.getReceiverType();
JetType candidateReceiverType = candidate.getReceiverType();
if (receiverType != null) {
if (candidateReceiverType == null) {
ReceiverDescriptor receiver = task.getReceiver();
ReceiverDescriptor candidateReceiver = candidate.getReceiver();
if (receiver != NO_RECEIVER) {
if (candidateReceiver == NO_RECEIVER) {
tracing.noReceiverAllowed(temporaryTrace);
return false;
}
}
else if (candidateReceiverType != null) {
tracing.missingReceiver(temporaryTrace, candidateReceiverType);
else if (candidateReceiver != NO_RECEIVER) {
tracing.missingReceiver(temporaryTrace, candidateReceiver);
return false;
}
return true;
@@ -658,8 +627,8 @@ public class CallResolver {
}
@NotNull
public OverloadResolutionResult<FunctionDescriptor> resolveExactSignature(@NotNull JetScope scope, @Nullable JetType receiverType, @NotNull String name, @NotNull List<JetType> parameterTypes) {
List<FunctionDescriptor> result = findCandidatesByExactSignature(scope, receiverType, name, parameterTypes);
public OverloadResolutionResult<FunctionDescriptor> resolveExactSignature(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, @NotNull String name, @NotNull List<JetType> parameterTypes) {
List<FunctionDescriptor> result = findCandidatesByExactSignature(scope, receiver, name, parameterTypes);
BindingTraceContext trace = new BindingTraceContext();
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);
}
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();
if (receiverType != null) {
if (receiver != NO_RECEIVER) {
Set<FunctionDescriptor> extensionFunctionDescriptors = scope.getFunctionGroup(name).getFunctionDescriptors();
List<FunctionDescriptor> nonlocal = Lists.newArrayList();
List<FunctionDescriptor> local = Lists.newArrayList();
TaskPrioritizer.splitLexicallyLocalDescriptors(extensionFunctionDescriptors, scope.getContainingDeclaration(), local, nonlocal);
if (findExtensionFunctions(local, receiverType, parameterTypes, result)) {
if (findExtensionFunctions(local, receiver, parameterTypes, 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)) {
return result;
}
findExtensionFunctions(nonlocal, receiverType, parameterTypes, result);
findExtensionFunctions(nonlocal, receiver, parameterTypes, result);
return result;
}
else {
@@ -702,7 +671,7 @@ public class CallResolver {
private boolean lookupExactSignature(Set<FunctionDescriptor> candidates, List<JetType> parameterTypes, List<FunctionDescriptor> result) {
boolean found = false;
for (FunctionDescriptor functionDescriptor : candidates) {
if (functionDescriptor.getReceiverType() != null) continue;
if (functionDescriptor.getReceiver() != NO_RECEIVER) continue;
if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
if (!checkValueParameters(functionDescriptor, parameterTypes)) continue;
result.add(functionDescriptor);
@@ -711,13 +680,13 @@ public class CallResolver {
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;
for (FunctionDescriptor functionDescriptor : candidates) {
JetType functionReceiverType = functionDescriptor.getReceiverType();
if (functionReceiverType == null) continue;
ReceiverDescriptor functionReceiver = functionDescriptor.getReceiver();
if (functionReceiver == NO_RECEIVER) 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;
result.add(functionDescriptor);
found = true;
@@ -744,7 +713,7 @@ public class CallResolver {
Set<FunctionDescriptor> functions = Sets.newLinkedHashSet(scope.getFunctionGroup(name).getFunctionDescriptors());
for (Iterator<FunctionDescriptor> iterator = functions.iterator(); iterator.hasNext(); ) {
FunctionDescriptor functionDescriptor = iterator.next();
if (functionDescriptor.getReceiverType() != null) {
if (functionDescriptor.getReceiver() != NO_RECEIVER) {
iterator.remove();
}
}
@@ -756,10 +725,11 @@ public class CallResolver {
@NotNull
@Override
protected Collection<FunctionDescriptor> getMembersByName(@NotNull JetType receiverType, String name) {
Set<FunctionDescriptor> members = Sets.newHashSet(receiverType.getMemberScope().getFunctionGroup(name).getFunctionDescriptors());
addConstructors(receiverType.getMemberScope(), name, members);
addVariableAsFunction(receiverType.getMemberScope(), name, members, false);
protected Collection<FunctionDescriptor> getMembersByName(@NotNull ReceiverDescriptor receiver, String name) {
JetScope receiverScope = receiver.getType().getMemberScope();
Set<FunctionDescriptor> members = Sets.newHashSet(receiverScope.getFunctionGroup(name).getFunctionDescriptors());
addConstructors(receiverScope, name, members);
addVariableAsFunction(receiverScope, name, members, false);
return members;
}
@@ -769,7 +739,7 @@ public class CallResolver {
Set<FunctionDescriptor> extensionFunctions = Sets.newHashSet(scope.getFunctionGroup(name).getFunctionDescriptors());
for (Iterator<FunctionDescriptor> iterator = extensionFunctions.iterator(); iterator.hasNext(); ) {
FunctionDescriptor descriptor = iterator.next();
if (descriptor.getReceiverType() == null) {
if (descriptor.getReceiver() == NO_RECEIVER) {
iterator.remove();
}
}
@@ -779,8 +749,8 @@ public class CallResolver {
@NotNull
@Override
protected ResolutionTask<FunctionDescriptor> createTask(JetType receiverType, Call call, Collection<FunctionDescriptor> candidates) {
return new ResolutionTask<FunctionDescriptor>(candidates, receiverType, call);
protected ResolutionTask<FunctionDescriptor> createTask(@NotNull ReceiverDescriptor receiver, Call call, Collection<FunctionDescriptor> candidates) {
return new ResolutionTask<FunctionDescriptor>(candidates, receiver, call);
}
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) {
VariableDescriptor variable = scope.getVariable(name);
if (variable != null && variable.getReceiverType() == null) {
if (variable != null && variable.getReceiver() == NO_RECEIVER) {
JetType outType = variable.getOutType();
if (outType != null && JetStandardClasses.isFunctionType(outType)) {
VariableAsFunctionDescriptor functionDescriptor = VariableAsFunctionDescriptor.create(variable);
if ((functionDescriptor.getReceiverType() != null) == receiverNeeded) {
if ((functionDescriptor.getReceiver() != NO_RECEIVER) == receiverNeeded) {
functions.add(functionDescriptor);
}
}
@@ -811,7 +781,7 @@ public class CallResolver {
@Override
protected Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String 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.emptyList();
@@ -819,8 +789,8 @@ public class CallResolver {
@NotNull
@Override
protected Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiverType, String name) {
VariableDescriptor variable = receiverType.getMemberScope().getVariable(name);
protected Collection<VariableDescriptor> getMembersByName(@NotNull ReceiverDescriptor receiver, String name) {
VariableDescriptor variable = receiver.getType().getMemberScope().getVariable(name);
if (variable != null) {
return Collections.singleton(variable);
}
@@ -831,7 +801,7 @@ public class CallResolver {
@Override
protected Collection<VariableDescriptor> getExtensionsByName(JetScope scope, String 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.emptyList();
@@ -839,8 +809,8 @@ public class CallResolver {
@NotNull
@Override
protected ResolutionTask<VariableDescriptor> createTask(JetType receiverType, Call call, Collection<VariableDescriptor> candidates) {
return new ResolutionTask<VariableDescriptor>(candidates, receiverType, call);
protected ResolutionTask<VariableDescriptor> createTask(@NotNull ReceiverDescriptor receiver, Call call, Collection<VariableDescriptor> candidates) {
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.resolve.DescriptorUtils;
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.JetType;
@@ -59,10 +60,10 @@ import java.util.Set;
if (overrides(f, g)) return true;
if (overrides(g, f)) return false;
JetType receiverTypeOfF = f.getReceiverType();
JetType receiverTypeOfG = g.getReceiverType();
if (receiverTypeOfF != null && receiverTypeOfG != null) {
if (!typeMoreSpecific(receiverTypeOfF, receiverTypeOfG)) return false;
ReceiverDescriptor receiverOfF = f.getReceiver();
ReceiverDescriptor receiverOfG = g.getReceiver();
if (f.getReceiver().exists() && g.getReceiver().exists()) {
if (!typeMoreSpecific(receiverOfF.getType(), receiverOfG.getType())) return false;
}
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.ValueArgument;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -19,7 +19,7 @@ import java.util.List;
*/
/*package*/ class ResolutionTask<Descriptor extends CallableDescriptor> {
private final Collection<Descriptor> candidates;
private final JetType receiverType;
private final ReceiverDescriptor receiver;
private final List<JetTypeProjection> typeArguments;
private final List<? extends ValueArgument> valueArguments;
private final List<JetExpression> functionLiteralArguments;
@@ -27,12 +27,12 @@ import java.util.List;
public ResolutionTask(
@NotNull Collection<Descriptor> candidates,
@Nullable JetType receiverType,
@NotNull ReceiverDescriptor receiver,
@NotNull List<JetTypeProjection> typeArguments,
@NotNull List<? extends ValueArgument> valueArguments,
@NotNull List<JetExpression> functionLiteralArguments) {
this.candidates = candidates;
this.receiverType = receiverType;
this.receiver = receiver;
this.typeArguments = typeArguments;
this.valueArguments = valueArguments;
this.functionLiteralArguments = functionLiteralArguments;
@@ -40,10 +40,10 @@ import java.util.List;
public ResolutionTask(
@NotNull Collection<Descriptor> candidates,
@Nullable JetType receiverType,
@NotNull ReceiverDescriptor receiver,
@NotNull Call call
) {
this(candidates, receiverType, call.getTypeArguments(), call.getValueArguments(), call.getFunctionLiteralArguments());
this(candidates, receiver, call.getTypeArguments(), call.getValueArguments(), call.getFunctionLiteralArguments());
}
@NotNull
@@ -51,9 +51,9 @@ import java.util.List;
return candidates;
}
@Nullable
public JetType getReceiverType() {
return receiverType;
@NotNull
public ReceiverDescriptor getReceiver() {
return receiver;
}
@NotNull
@@ -2,7 +2,6 @@ package org.jetbrains.jet.lang.resolve.calls;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
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.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collection;
import java.util.List;
@@ -64,33 +62,33 @@ import java.util.List;
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();
doComputeTasks(scope, receiverType, call, name, result);
doComputeTasks(scope, receiver, call, name, result);
return result;
}
private void doComputeTasks(JetScope scope, JetType receiverType, Call call, String name, List<ResolutionTask<D>> result) {
List<ReceiverDescriptor> receivers = Lists.newArrayList();
scope.getImplicitReceiversHierarchy(receivers);
if (receiverType != null) {
private void doComputeTasks(JetScope scope, ReceiverDescriptor receiver, Call call, String name, List<ResolutionTask<D>> result) {
List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList();
scope.getImplicitReceiversHierarchy(implicitReceivers);
if (receiver != ReceiverDescriptor.NO_RECEIVER) {
Collection<D> extensionFunctions = getExtensionsByName(scope, name);
List<D> nonlocals = Lists.newArrayList();
List<D> locals = Lists.newArrayList();
//noinspection unchecked,RedundantTypeArguments
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, null, call, members);
addTask(result, receiver, call, locals);
addTask(result, ReceiverDescriptor.NO_RECEIVER, call, members);
for (ReceiverDescriptor receiver : receivers) {
Collection<D> memberExtensions = getExtensionsByName(receiver.getReceiverType().getMemberScope(), name);
addTask(result, receiverType, call, memberExtensions);
for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
Collection<D> memberExtensions = getExtensionsByName(implicitReceiver.getType().getMemberScope(), name);
addTask(result, receiver, call, memberExtensions);
}
addTask(result, receiverType, call, nonlocals);
addTask(result, receiver, call, nonlocals);
}
else {
Collection<D> functions = getNonExtensionsByName(scope, name);
@@ -100,13 +98,13 @@ import java.util.List;
//noinspection unchecked,RedundantTypeArguments
TaskPrioritizer.<D>splitLexicallyLocalDescriptors(functions, scope.getContainingDeclaration(), locals, nonlocals);
addTask(result, receiverType, call, locals);
addTask(result, receiver, call, locals);
for (ReceiverDescriptor receiver : receivers) {
doComputeTasks(scope, receiver.getReceiverType(), call, name, result);
for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
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);
@NotNull
protected abstract Collection<D> getMembersByName(@NotNull JetType receiverType, String name);
protected abstract Collection<D> getMembersByName(@NotNull ReceiverDescriptor receiver, String name);
@NotNull
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;
result.add(createTask(receiverType, call, candidates));
result.add(createTask(receiver, call, candidates));
}
@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.ValueParameterDescriptor;
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.Set;
@@ -15,7 +15,7 @@ import java.util.Set;
/*package*/ interface TracingStrategy {
TracingStrategy EMPTY = new TracingStrategy() {
@Override
public void bindReference(@NotNull BindingTrace trace, @NotNull CallableDescriptor descriptor) {}
public void bindReference(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiver, @NotNull CallableDescriptor descriptor) {}
@Override
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) {}
@Override
public void missingReceiver(@NotNull BindingTrace trace, @NotNull JetType candidateReceiverType) {}
public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver) {}
@Override
public void noReceiverAllowed(@NotNull BindingTrace trace) {}
@@ -48,13 +48,13 @@ import java.util.Set;
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);
<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);
@@ -3,7 +3,7 @@ package org.jetbrains.jet.lang.resolve.scopes;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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
@@ -30,5 +30,5 @@ public interface WritableScope extends JetScope {
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.jet.lang.descriptors.*;
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 java.util.*;
@@ -36,7 +35,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
private Map<String, List<DeclarationDescriptor>> labelsToDescriptors;
@Nullable
private ImplicitReceiverDescriptor implicitReceiver;
private ReceiverDescriptor implicitReceiver;
public WritableScopeImpl(@NotNull JetScope scope, @NotNull DeclarationDescriptor owner, @NotNull RedeclarationHandler redeclarationHandler) {
super(scope, redeclarationHandler);
@@ -275,7 +274,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
}
@Override
public void setImplicitReceiver(@NotNull ImplicitReceiverDescriptor implicitReceiver) {
public void setImplicitReceiver(@NotNull ReceiverDescriptor implicitReceiver) {
if (this.implicitReceiver != null) {
throw new UnsupportedOperationException("Receiver redeclared");
}
@@ -284,7 +283,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
@Override
public void getImplicitReceiversHierarchy(@NotNull List<ReceiverDescriptor> result) {
if (implicitReceiver != null && implicitReceiver != ReceiverDescriptor.NO_RECEIVER) {
if (implicitReceiver != null && implicitReceiver.exists()) {
result.add(implicitReceiver);
}
super.getImplicitReceiversHierarchy(result);
@@ -4,7 +4,6 @@ import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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 java.util.Collection;
@@ -147,7 +146,7 @@ public class WriteThroughScope extends WritableScopeWithImports {
}
@Override
public void setImplicitReceiver(@NotNull ImplicitReceiverDescriptor implicitReceiver) {
public void setImplicitReceiver(@NotNull ReceiverDescriptor 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;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
/**
@@ -10,4 +11,9 @@ public class ClassReceiver extends ImplicitReceiverDescriptor {
public ClassReceiver(ClassDescriptor classDescriptor) {
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
*/
public abstract class ImplicitReceiverDescriptor implements ReceiverDescriptor {
private final JetType receiverType;
public abstract class ImplicitReceiverDescriptor extends AbstractReceiverDescriptor {
private final DeclarationDescriptor declarationDescriptor;
protected ImplicitReceiverDescriptor(DeclarationDescriptor declarationDescriptor, JetType receiverType) {
this.receiverType = receiverType;
protected ImplicitReceiverDescriptor(@NotNull DeclarationDescriptor declarationDescriptor, @NotNull JetType receiverType) {
super(receiverType);
this.declarationDescriptor = declarationDescriptor;
}
@Override
@NotNull
public JetType getReceiverType() {
return receiverType;
}
@NotNull
public DeclarationDescriptor getDeclarationDescriptor() {
return declarationDescriptor;
@@ -1,7 +1,6 @@
package org.jetbrains.jet.lang.resolve.scopes.receivers;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
/**
@@ -12,8 +11,18 @@ public interface ReceiverDescriptor {
ReceiverDescriptor NO_RECEIVER = new ReceiverDescriptor() {
@NotNull
@Override
public JetType getReceiverType() {
return JetStandardClasses.getNothingType();
public JetType getType() {
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
@@ -23,5 +32,9 @@ public interface ReceiverDescriptor {
};
@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.WritableScope;
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.util.slicedmap.WritableSlice;
@@ -196,7 +199,7 @@ public class JetTypeInferrer {
}
@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);
if (type != null) {
return type;
@@ -221,9 +224,9 @@ public class JetTypeInferrer {
private void checkNullSafety(@Nullable JetType receiverType, @NotNull ASTNode operationTokenNode, @Nullable FunctionDescriptor callee, @NotNull JetElement element) {
if (receiverType != null && callee != null) {
boolean namespaceType = receiverType instanceof NamespaceType;
JetType calleeReceiverType = callee.getReceiverType();
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();
if (nullableReceiver && calleeForbidsNullableReceiver && operationSign == JetTokens.DOT) {
@@ -682,6 +685,20 @@ public class JetTypeInferrer {
}
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
public final JetType getType(@NotNull JetExpression expression, TypeInferenceContext context) {
@@ -762,7 +779,7 @@ public class JetTypeInferrer {
}
}
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();
// if (referencedName != null) {
// VariableDescriptor variable = context.scope.getVariable(referencedName);
@@ -895,7 +912,8 @@ public class JetTypeInferrer {
if (receiverTypeRef != null) {
receiverType = context.typeResolver.resolveType(context.scope, receiverTypeRef);
} else {
receiverType = context.scope.getImplicitReceiver().getReceiverType();
ReceiverDescriptor implicitReceiver = context.scope.getImplicitReceiver();
receiverType = implicitReceiver.exists() ? implicitReceiver.getType() : null;
}
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(
@@ -1217,7 +1235,7 @@ public class JetTypeInferrer {
@Override
public JetType visitThisExpression(JetThisExpression expression, TypeInferenceContext context) {
JetType result = null;
JetType thisType = null;
ReceiverDescriptor thisReceiver = null;
String labelName = expression.getLabelName();
if (labelName != null) {
Collection<DeclarationDescriptor> declarationsByLabel = context.scope.getDeclarationsByLabel(labelName);
@@ -1228,11 +1246,11 @@ public class JetTypeInferrer {
DeclarationDescriptor declarationDescriptor = declarationsByLabel.iterator().next();
if (declarationDescriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
thisType = classDescriptor.getDefaultType();
thisReceiver = classDescriptor.getImplicitReceiver();
}
else if (declarationDescriptor instanceof FunctionDescriptor) {
FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor;
thisType = functionDescriptor.getReceiverType();
thisReceiver = functionDescriptor.getReceiver();
}
else {
throw new UnsupportedOperationException(); // TODO
@@ -1246,11 +1264,8 @@ public class JetTypeInferrer {
if (psiElement instanceof JetFunctionLiteralExpression) {
DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
if (declarationDescriptor instanceof FunctionDescriptor) {
thisType = ((FunctionDescriptor) declarationDescriptor).getReceiverType();
if (thisType == null) {
thisType = JetStandardClasses.getNothingType();
}
else {
thisReceiver = ((FunctionDescriptor) declarationDescriptor).getReceiver();
if (thisReceiver.exists()) {
context.trace.record(REFERENCE_TARGET, targetLabel, declarationDescriptor);
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
}
@@ -1269,7 +1284,7 @@ public class JetTypeInferrer {
}
}
else {
thisType = context.scope.getImplicitReceiver().getReceiverType();
thisReceiver = context.scope.getImplicitReceiver();
DeclarationDescriptor declarationDescriptorForUnqualifiedThis = context.scope.getDeclarationDescriptorForUnqualifiedThis();
if (declarationDescriptorForUnqualifiedThis != null) {
@@ -1277,8 +1292,8 @@ public class JetTypeInferrer {
}
}
if (thisType != null) {
if (JetStandardClasses.isNothing(thisType)) {
if (thisReceiver != null) {
if (!thisReceiver.exists()) {
// context.trace.getErrorHandler().genericError(expression.getNode(), "'this' is not defined in this context");
context.trace.report(NO_THIS.on(expression));
}
@@ -1294,6 +1309,7 @@ public class JetTypeInferrer {
if (classifierCandidate instanceof ClassDescriptor) {
ClassDescriptor superclass = (ClassDescriptor) classifierCandidate;
JetType thisType = thisReceiver.getType();
Collection<? extends JetType> supertypes = thisType.getConstructor().getSupertypes();
TypeSubstitutor substitutor = TypeSubstitutor.create(thisType);
for (JetType declaredSupertype : supertypes) {
@@ -1308,8 +1324,9 @@ public class JetTypeInferrer {
}
}
}
} else {
result = thisType;
}
else {
result = thisReceiver.getType();
}
if (result != null) {
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());
if (callSuffixExpression != null) {
// 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);
context.services.checkNullSafety(subjectType, condition.getOperationTokenNode(), getCalleeFunctionDescriptor(callSuffixExpression, context), condition);
}
@@ -1474,7 +1492,8 @@ public class JetTypeInferrer {
public void visitDecomposerPattern(JetDecomposerPattern pattern) {
JetExpression decomposerExpression = pattern.getDecomposerExpression();
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);
}
@@ -1840,13 +1859,12 @@ public class JetTypeInferrer {
TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
JetParameter loopParameter = expression.getLoopParameter();
JetExpression loopRange = expression.getLoopRange();
JetType loopRangeType = null;
if (loopRange != null) {
loopRangeType = getType(loopRange, context.replaceScope(context.scope));
}
JetType expectedParameterType = null;
if (loopRangeType != null) {
expectedParameterType = checkIterableConvention(loopRangeType, loopRange, context);
if (loopRange != null) {
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");
@@ -1882,42 +1900,42 @@ public class JetTypeInferrer {
}
@Nullable
private JetType checkIterableConvention(@NotNull JetType type, @NotNull JetExpression loopRange, TypeInferenceContext context) {
ASTNode reportErrorsOn = loopRange.getNode();
OverloadResolutionResult<FunctionDescriptor> iteratorResolutionResult = callResolver.resolveExactSignature(context.scope, type, "iterator", Collections.<JetType>emptyList());
private JetType checkIterableConvention(@NotNull ExpressionReceiver loopRange, TypeInferenceContext context) {
JetExpression loopRangeExpression = loopRange.getExpression();
OverloadResolutionResult<FunctionDescriptor> iteratorResolutionResult = callResolver.resolveExactSignature(context.scope, loopRange, "iterator", Collections.<JetType>emptyList());
if (iteratorResolutionResult.isSuccess()) {
FunctionDescriptor iteratorFunction = iteratorResolutionResult.getDescriptor();
context.trace.record(LOOP_RANGE_ITERATOR, loopRange, iteratorFunction);
context.trace.record(LOOP_RANGE_ITERATOR, loopRangeExpression, iteratorFunction);
JetType iteratorType = iteratorFunction.getReturnType();
FunctionDescriptor hasNextFunction = checkHasNextFunctionSupport(loopRange, iteratorType, context);
FunctionDescriptor hasNextFunction = checkHasNextFunctionSupport(loopRangeExpression, iteratorType, context);
boolean hasNextFunctionSupported = hasNextFunction != null;
VariableDescriptor hasNextProperty = checkHasNextPropertySupport(loopRange, iteratorType, context);
VariableDescriptor hasNextProperty = checkHasNextPropertySupport(loopRangeExpression, iteratorType, context);
boolean hasNextPropertySupported = hasNextProperty != null;
if (hasNextFunctionSupported && hasNextPropertySupported && !ErrorUtils.isErrorType(iteratorType)) {
// TODO : overload resolution rules impose priorities here???
// 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) {
// 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 {
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()) {
// 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()) {
// 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 {
FunctionDescriptor nextFunction = nextResolutionResult.getDescriptor();
context.trace.record(LOOP_RANGE_NEXT, loopRange, nextFunction);
context.trace.record(LOOP_RANGE_NEXT, loopRange.getExpression(), nextFunction);
return nextFunction.getReturnType();
}
}
@@ -1928,11 +1946,11 @@ public class JetTypeInferrer {
// stringBuffer.append(DescriptorRenderer.TEXT.render(functionDescriptor)).append(" ");
// }
// errorMessage = stringBuffer.toString();
context.trace.report(ITERATOR_AMBIGUITY.on(reportErrorsOn, iteratorResolutionResult.getDescriptors()));
context.trace.report(ITERATOR_AMBIGUITY.on(loopRangeExpression, iteratorResolutionResult.getDescriptors()));
}
else {
// context.trace.getErrorHandler().genericError(reportErrorsOn, errorMessage);
context.trace.report(ITERATOR_MISSING.on(reportErrorsOn));
context.trace.report(ITERATOR_MISSING.on(loopRangeExpression));
}
}
return null;
@@ -1940,7 +1958,7 @@ public class JetTypeInferrer {
@Nullable
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()) {
// context.trace.getErrorHandler().genericError(loopRange.getNode(), "Method 'iterator().hasNext()' is ambiguous for this expression");
context.trace.report(HAS_NEXT_FUNCTION_AMBIGUITY.on(loopRange));
@@ -2002,7 +2020,7 @@ public class JetTypeInferrer {
// Clean resolution: no autocasts
TemporaryBindingTrace cleanResolutionTrace = TemporaryBindingTrace.create(context.trace);
TypeInferenceContext cleanResolutionContext = context.replaceBindingTrace(cleanResolutionTrace);
JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression, cleanResolutionContext);
JetType selectorReturnType = getSelectorReturnType(new ExpressionReceiver(receiverExpression, receiverType), selectorExpression, cleanResolutionContext);
//TODO move further
if (expression.getOperationSign() == JetTokens.SAFE_ACCESS) {
@@ -2023,7 +2041,7 @@ public class JetTypeInferrer {
TemporaryBindingTrace autocastResolutionTrace = TemporaryBindingTrace.create(context.trace);
TypeInferenceContext autocastResolutionContext = context.replaceBindingTrace(autocastResolutionTrace);
for (JetType possibleType : possibleTypes) {
selectorReturnType = getSelectorReturnType(possibleType, selectorExpression, autocastResolutionContext);
selectorReturnType = getSelectorReturnType(new ExpressionReceiver(receiverExpression, possibleType), selectorExpression, autocastResolutionContext);
if (selectorReturnType != null) {
context.services.checkAutoCast(receiverExpression, possibleType, variableDescriptor, autocastResolutionTrace);
autocastResolutionTrace.commit();
@@ -2146,20 +2164,20 @@ public class JetTypeInferrer {
}
@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) {
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) {
JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) selectorExpression;
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) {
temporaryTrace.commit();
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);
if (jetType == null) {
context.trace.report(UNRESOLVED_REFERENCE.on(nameExpression));
@@ -2170,10 +2188,11 @@ public class JetTypeInferrer {
}
else if (selectorExpression instanceof JetQualifiedExpression) {
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();
if (newReceiverType != null && newSelectorExpression != null) {
return getSelectorReturnType(newReceiverType, newSelectorExpression, context);
return getSelectorReturnType(new ExpressionReceiver(newReceiverExpression, newReceiverType), newSelectorExpression, context);
}
}
else {
@@ -2186,7 +2205,7 @@ public class JetTypeInferrer {
@Override
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);
}
@@ -2220,8 +2239,8 @@ public class JetTypeInferrer {
context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression"));
return null;
}
JetType receiverType = getType(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceScope(context.scope));
if (receiverType == null) return null;
ExpressionReceiver receiver = getExpressionReceiver(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceScope(context.scope));
if (receiver == null) return null;
FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName(
context.trace,
@@ -2229,7 +2248,7 @@ public class JetTypeInferrer {
CallMaker.makeCall(expression),
expression.getOperationSign(),
name,
receiverType,
receiver,
context.expectedType);
if (functionDescriptor == null) return null;
@@ -2240,6 +2259,7 @@ public class JetTypeInferrer {
result = JetStandardClasses.getUnitType();
}
else {
JetType receiverType = receiver.getType();
if (!semanticServices.getTypeChecker().isSubtypeOf(returnType, receiverType)) {
// context.trace.getErrorHandler().genericError(operationSign.getNode(), name + " must return " + receiverType + " but returns " + returnType);
context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, name, receiverType, returnType));
@@ -2299,9 +2319,9 @@ public class JetTypeInferrer {
else if (equalsOperations.contains(operationType)) {
String name = "equals";
if (right != null) {
JetType leftType = safeGetType(left, context.replaceScope(context.scope));
ExpressionReceiver receiver = safeGetExpressionReceiver(left, context.replaceScope(context.scope));
OverloadResolutionResult<FunctionDescriptor> resolutionResult = callResolver.resolveExactSignature(
context.scope, leftType, "equals",
context.scope, receiver, "equals",
Collections.singletonList(JetStandardClasses.getNullableAnyType()));
if (resolutionResult.isSuccess()) {
FunctionDescriptor equals = resolutionResult.getDescriptor();
@@ -2380,13 +2400,13 @@ public class JetTypeInferrer {
private void checkInExpression(JetSimpleNameExpression operationSign, JetExpression left, JetExpression right, TypeInferenceContext context) {
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(
context.trace,
context.scope,
CallMaker.makeCall(operationSign, Collections.singletonList(left)),
operationSign,
name, receiverType, context.expectedType);
name, receiver, context.expectedType);
JetType containsType = functionDescriptor != null ? functionDescriptor.getReturnType() : null;
ensureBooleanResult(operationSign, name, containsType, context);
}
@@ -2449,16 +2469,16 @@ public class JetTypeInferrer {
public JetType visitArrayAccessExpression(JetArrayAccessExpression expression, TypeInferenceContext contextWithExpectedType) {
TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
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(
context.trace,
context.scope,
CallMaker.makeCall(expression, expression.getIndexExpressions()),
expression,
"get",
receiverType,
receiver,
context.expectedType);
if (functionDescriptor != null) {
return context.services.checkType(functionDescriptor.getReturnType(), expression, contextWithExpectedType);
@@ -2469,17 +2489,17 @@ public class JetTypeInferrer {
@Nullable
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(
context.trace,
scope,
CallMaker.makeCall(binaryExpression),
binaryExpression.getOperationReference(),
name,
leftType,
receiver,
context.expectedType);
if (functionDescriptor != null) {
if (leftType != null && leftType.isNullable()) {
if (receiver.getType().isNullable()) {
// TODO : better error message for '1 + nullableVar' case
JetExpression right = binaryExpression.getRight();
String rightText = right == null ? "" : right.getText();
@@ -2719,8 +2739,8 @@ public class JetTypeInferrer {
}
private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, TypeInferenceContext context) {
JetType receiverType = getType(arrayAccessExpression.getArrayExpression(), context.replaceScope(scope));
if (receiverType == null) return null;
ExpressionReceiver receiver = getExpressionReceiver(arrayAccessExpression.getArrayExpression(), context.replaceScope(scope));
if (receiver == null) return null;
//
Call call = CallMaker.makeCall(arrayAccessExpression, rightHandSide);
// // TODO : nasty hack: effort is duplicated
@@ -2734,7 +2754,7 @@ public class JetTypeInferrer {
scope,
call,
arrayAccessExpression,
"set", receiverType, NO_EXPECTED_TYPE);
"set", receiver, NO_EXPECTED_TYPE);
if (functionDescriptor == null) return null;
context.trace.record(REFERENCE_TARGET, operationSign, functionDescriptor);
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.Nullable;
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.Collections;
@@ -128,7 +130,7 @@ public class DescriptorRenderer {
@Override
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);
builder.append(" : ").append(escape(typeString));
return super.visitVariableDescriptor(descriptor, builder);
@@ -137,7 +139,7 @@ public class DescriptorRenderer {
private String renderPropertyPrefixAndComputeTypeString(
@NotNull StringBuilder builder,
@NotNull List<TypeParameterDescriptor> typeParameters,
@Nullable JetType receiverType,
@NotNull ReceiverDescriptor receiver,
@Nullable JetType outType,
@Nullable JetType inType) {
String typeString = lt() + "no type>";
@@ -161,8 +163,8 @@ public class DescriptorRenderer {
renderTypeParameters(typeParameters, builder);
if (receiverType != null) {
builder.append(escape(renderType(receiverType))).append(".");
if (receiver.exists()) {
builder.append(escape(renderType(receiver.getType()))).append(".");
}
return typeString;
@@ -172,7 +174,7 @@ public class DescriptorRenderer {
public Void visitPropertyDescriptor(PropertyDescriptor descriptor, StringBuilder builder) {
String typeString = renderPropertyPrefixAndComputeTypeString(
builder, descriptor.getTypeParameters(),
descriptor.getReceiverType(),
descriptor.getReceiver(),
descriptor.getOutType(),
descriptor.getInType());
renderName(descriptor, builder);
@@ -185,9 +187,9 @@ public class DescriptorRenderer {
builder.append(renderKeyword("fun")).append(" ");
renderTypeParameters(descriptor.getTypeParameters(), builder);
JetType receiverType = descriptor.getReceiverType();
if (receiverType != null) {
builder.append(escape(renderType(receiverType))).append(".");
ReceiverDescriptor receiver = descriptor.getReceiver();
if (receiver.exists()) {
builder.append(escape(renderType(receiver.getType()))).append(".");
}
renderName(descriptor, builder);
Binary file not shown.
@@ -89,7 +89,7 @@ public abstract class JetPsiReference implements PsiPolyVariantReference {
JetFile file = (JetFile) getElement().getContainingFile();
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file);
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()];
int i = 0;
for (DeclarationDescriptor descriptor : declarationDescriptors) {
@@ -3,7 +3,7 @@ fun text() {
"direct:a" on {it.body == "<hello/>"} to "mock:a"
"direct:a" on {it => it.body == "<hello/>"} to "mock:a"
bar <!TYPE_MISMATCH!>{1}<!>
bar <!TYPE_MISMATCH!>{<!UNRESOLVED_REFERENCE!>it<!> <!UNRESOLVED_REFERENCE!>+<!> 1}<!>
bar <!TYPE_MISMATCH!>{<!UNRESOLVED_REFERENCE!>it<!> + 1}<!>
bar {it, it1 => it}
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 {
/*
if(!t1()) {
return "t1 failed"
}
@@ -242,6 +243,7 @@ fun box() : String {
if(!t25()) {
return "t25 failed"
}
*/
if(!t26()) {
return "t26 failed"
}
+9 -3
View File
@@ -3,13 +3,19 @@ trait 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 {
val c = SmartArrayList()
val c = SmartArrayList2()
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 {
// blackBoxFile("traits/multiple.jet");
// System.out.println(generateToText());
blackBoxFile("traits/multiple.jet");
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.resolve.BindingTraceContext;
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.parsing.JetParsingTest;
@@ -106,7 +107,8 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
List<JetType> parameterTypeList = Arrays.asList(parameterType);
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()) {
List<ValueParameterDescriptor> unsubstitutedValueParameters = function.getValueParameters();
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.JavaSemanticServices;
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.types.*;
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));
}
private void assertType(String contextType, String expression, String expectedType) {
private void assertType(String contextType, final String expression, String expectedType) {
final JetType thisType = makeType(contextType);
JetScope scope = new JetScopeAdapter(classDefinitions.BASIC_SCOPE) {
@NotNull
@Override
public ReceiverDescriptor getImplicitReceiver() {
return new ExplicitReceiver(thisType);
return new ExpressionReceiver(JetPsiFactory.createExpression(getProject(), expression), thisType);
}
};
assertType(scope, expression, expectedType);
+348 -192
View File
@@ -1,5 +1,6 @@
package jet.typeinfo;
import com.sun.org.apache.bcel.internal.generic.MethodGen;
import jet.JetObject;
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<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) {
return (TypeInfoImpl) typeInfo;
return (TypeInfoProjection) 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);
}
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;
}
}
public abstract Object getClassObject();
public final boolean isInstance(Object obj) {
if (obj == null) return nullable;
public abstract boolean isInstance(Object obj);
if (obj instanceof JetObject) {
return ((JetObject) obj).getTypeInfo().isSubtypeOf(this);
public abstract int getProjectionCount();
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 final boolean isSubtypeOf(TypeInfo<?> superType) {
if (nullable && !superType.nullable) {
return false;
public TypeInfoVar(boolean nullable, Integer varIndex) {
this.nullable = nullable;
this.varIndex = varIndex;
}
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
if (!projections[i].equals(superType.projections[i])) {
return false;
}
@Override
public int getProjectionCount() {
return 0;
}
return true;
}
public final TypeInfoProjection getProjection(int index) {
return projections[index];
}
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
@Override
public TypeInfoProjection getProjection(int index) {
throw new UnsupportedOperationException("Abstract TypeInfo");
}
return typeInfo;
}
@Override
public final boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TypeInfo typeInfo = (TypeInfo) 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;
}
@Override
public final int hashCode() {
return 31 * signature.klazz.hashCode() + Arrays.hashCode(projections);
}
@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(">");
@Override
public TypeInfo getArgumentType(Class klass, int index) {
throw new UnsupportedOperationException("Abstract TypeInfo");
}
@Override
public TypeInfo substitute(List<TypeInfo> myVars) {
return myVars.get(varIndex);
}
@Override
protected TypeInfo substitute(TypeInfoProjection[] projections) {
return projections[varIndex].getType();
}
@Override
public TypeInfo<?> getTypeInfo() {
throw new UnsupportedOperationException("Abstract TypeInfo");
}
@Override
public String toString() {
return "T:" + varIndex;
}
if (nullable)
sb.append("?");
return sb.toString();
}
private static class TypeInfoImpl<T> extends TypeInfo<T> implements TypeInfoProjection {
TypeInfoImpl(Class<T> klazz, boolean nullable) {
super(klazz, nullable);
private TypeInfo<?> typeInfo;
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) {
super(klazz, nullable, projections);
private TypeInfoImpl(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 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
@@ -197,81 +274,116 @@ public abstract class TypeInfo<T> implements JetObject {
public TypeInfo getType() {
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 {
final Class klazz;
final List<Var> variables;
final List<Type> superTypes;
final List<TypeInfoProjection> variables;
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.superTypes = superTypes;
this.variables = variables;
for(Type superType : superTypes) {
if(superType instanceof TypeReal) {
TypeReal type = (TypeReal) superType;
Signature parse = Parser.parse(type.klazz);
superSignatures.put(type.klazz, parse);
for(Map.Entry<Class,Signature> entry : parse.superSignatures.entrySet()) {
superSignatures.put(entry.getKey(), entry.getValue());
List<TypeInfo> myVars = variables == null ? Collections.<TypeInfo>emptyList() : new LinkedList<TypeInfo>();
if(variables != null)
for(int i = 0; i != variables.size(); ++i)
myVars.add(new TypeInfoVar(false, i));
for(TypeInfo superType : superTypes) {
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 {
static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
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();
Map<String,Integer> variables;
List<Var> vars;
List<TypeInfoProjection> vars;
if(typeParameters == null || typeParameters.length == 0) {
variables = Collections.emptyMap();
vars = Collections.emptyList();
}
else {
variables = new HashMap<String, Integer>();
vars = new LinkedList<Var>();
vars = new LinkedList<TypeInfoProjection>();
for (int i = 0; i < typeParameters.length; i++) {
TypeVariable typeParameter = typeParameters[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();
return new Signature(klass, vars, types);
}
public List<Var> parseVars() {
List<Var> list = null;
public List<TypeInfoProjection> parseVars() {
List<TypeInfoProjection> list = null;
while(cur != string.length && string[cur] == 'T') {
if(list == null)
list = new LinkedList<Var>();
if(list == null) {
list = new LinkedList<TypeInfoProjection>();
variables = new HashMap<String, Integer>();
}
list.add(parseVar());
}
List<Var> vars = list == null ? Collections.<Var>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;
return list == null ? Collections.<TypeInfoProjection>emptyList() : list;
}
private Var parseVar() {
TypeInfoVariance variance = parseVariance();
private TypeInfoProjection parseVar() {
final TypeInfoVariance variance = parseVariance();
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() {
@@ -392,18 +531,18 @@ public abstract class TypeInfo<T> implements JetObject {
}
}
public List<Type> parseTypes() {
List<Type> types = null;
public List<TypeInfo> parseTypes() {
List<TypeInfo> types = null;
while(cur != string.length) {
if(types == null) {
types = new LinkedList<Type>();
types = new LinkedList<TypeInfo>();
}
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]) {
case 'L':
String name = parseName();
@@ -413,13 +552,13 @@ public abstract class TypeInfo<T> implements JetObject {
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
List<TypeProj> proj = null;
List<TypeInfoProjection> proj = null;
boolean nullable = false;
if(cur != string.length && string[cur] == '<') {
cur++;
while(string[cur] != '>') {
if(proj == null)
proj = new LinkedList<TypeProj>();
proj = new LinkedList<TypeInfoProjection>();
proj.add(parseProjection());
}
cur++;
@@ -428,7 +567,9 @@ public abstract class TypeInfo<T> implements JetObject {
cur++;
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':
return parseTypeVar();
@@ -438,7 +579,7 @@ public abstract class TypeInfo<T> implements JetObject {
}
}
private Type parseTypeVar() {
private TypeInfo parseTypeVar() {
String name = parseName();
boolean nullable = false;
if(string[cur] == '?') {
@@ -446,13 +587,28 @@ public abstract class TypeInfo<T> implements JetObject {
cur++;
}
return new TypeVar(nullable, variables.get(name));
return new TypeInfoVar(nullable, variables.get(name));
}
private TypeProj parseProjection() {
TypeInfoVariance variance = parseVariance();
Type type = parseType();
return new TypeProj(variance, type);
private TypeInfoProjection parseProjection() {
final TypeInfoVariance variance = parseVariance();
final TypeInfo type = parseType();
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;
import java.util.List;
/**
* @author alex.tkachman
*/