Merge remote branch 'origin/master'
Conflicts: compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java
This commit is contained in:
@@ -81,9 +81,14 @@ public class CallableMethod implements Callable {
|
|||||||
public void invokeWithDefault(InstructionAdapter v, int mask) {
|
public void invokeWithDefault(InstructionAdapter v, int mask) {
|
||||||
v.iconst(mask);
|
v.iconst(mask);
|
||||||
String desc = getSignature().getDescriptor().replace(")", "I)");
|
String desc = getSignature().getDescriptor().replace(")", "I)");
|
||||||
if(getInvokeOpcode() != Opcodes.INVOKESTATIC)
|
if("<init>".equals(getSignature().getName())) {
|
||||||
desc = desc.replace("(", "(L" + getOwner() + ";");
|
v.visitMethodInsn(Opcodes.INVOKESPECIAL, getOwner(), "<init>", desc);
|
||||||
v.visitMethodInsn(Opcodes.INVOKESTATIC, getInvokeOpcode() == Opcodes.INVOKEINTERFACE ? getOwner() + "$$TImpl" : getOwner(), getSignature().getName() + "$default", desc);
|
}
|
||||||
|
else {
|
||||||
|
if(getInvokeOpcode() != Opcodes.INVOKESTATIC)
|
||||||
|
desc = desc.replace("(", "(L" + getOwner() + ";");
|
||||||
|
v.visitMethodInsn(Opcodes.INVOKESTATIC, getInvokeOpcode() == Opcodes.INVOKEINTERFACE ? getOwner() + "$$TImpl" : getOwner(), getSignature().getName() + "$default", desc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNeedsThis() {
|
public boolean isNeedsThis() {
|
||||||
|
|||||||
@@ -124,15 +124,17 @@ public abstract class CodegenContext {
|
|||||||
return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName);
|
return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FrameMap prepareFrame() {
|
public FrameMap prepareFrame(JetTypeMapper mapper) {
|
||||||
FrameMap frameMap = new FrameMap();
|
FrameMap frameMap = new FrameMap();
|
||||||
|
|
||||||
if (getContextKind() != OwnerKind.NAMESPACE) {
|
if (getContextKind() != OwnerKind.NAMESPACE) {
|
||||||
frameMap.enterTemp(); // 0 slot for this
|
frameMap.enterTemp(); // 0 slot for this
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getReceiverDescriptor() != null) {
|
CallableDescriptor receiverDescriptor = getReceiverDescriptor();
|
||||||
frameMap.enterTemp(); // Next slot for fake this
|
if (receiverDescriptor != null) {
|
||||||
|
Type type = mapper.mapType(receiverDescriptor.getReceiverParameter().getType());
|
||||||
|
frameMap.enterTemp(type.getSize()); // Next slot for fake this
|
||||||
}
|
}
|
||||||
|
|
||||||
return frameMap;
|
return frameMap;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
@@ -26,17 +27,19 @@ public class FunctionCodegen {
|
|||||||
private final CodegenContext owner;
|
private final CodegenContext owner;
|
||||||
private final ClassBuilder v;
|
private final ClassBuilder v;
|
||||||
private final GenerationState state;
|
private final GenerationState state;
|
||||||
|
private final JetTypeMapper typeMapper;
|
||||||
|
|
||||||
public FunctionCodegen(CodegenContext owner, ClassBuilder v, GenerationState state) {
|
public FunctionCodegen(CodegenContext owner, ClassBuilder v, GenerationState state) {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.v = v;
|
this.v = v;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
|
typeMapper = state.getTypeMapper();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void gen(JetNamedFunction f) {
|
public void gen(JetNamedFunction f) {
|
||||||
final FunctionDescriptor functionDescriptor = state.getBindingContext().get(BindingContext.FUNCTION, f);
|
final FunctionDescriptor functionDescriptor = state.getBindingContext().get(BindingContext.FUNCTION, f);
|
||||||
assert functionDescriptor != null;
|
assert functionDescriptor != null;
|
||||||
Method method = state.getTypeMapper().mapToCallableMethod(functionDescriptor, false, owner.getContextKind()).getSignature();
|
Method method = typeMapper.mapToCallableMethod(functionDescriptor, false, owner.getContextKind()).getSignature();
|
||||||
generateMethod(f, method, functionDescriptor);
|
generateMethod(f, method, functionDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,21 +62,57 @@ public class FunctionCodegen {
|
|||||||
|
|
||||||
OwnerKind kind = context.getContextKind();
|
OwnerKind kind = context.getContextKind();
|
||||||
|
|
||||||
|
ReceiverDescriptor expectedThisObject = functionDescriptor.getExpectedThisObject();
|
||||||
|
ReceiverDescriptor receiverParameter = functionDescriptor.getReceiverParameter();
|
||||||
|
|
||||||
if (kind != OwnerKind.TRAIT_IMPL || bodyExpressions != null) {
|
if (kind != OwnerKind.TRAIT_IMPL || bodyExpressions != null) {
|
||||||
|
boolean isStatic = kind == OwnerKind.NAMESPACE;
|
||||||
|
if (isStatic || kind == OwnerKind.TRAIT_IMPL)
|
||||||
|
flags |= ACC_STATIC;
|
||||||
|
|
||||||
boolean isStatic = kind == OwnerKind.NAMESPACE || kind == OwnerKind.TRAIT_IMPL;
|
boolean isAbstract = !isStatic && !(kind == OwnerKind.TRAIT_IMPL) && (bodyExpressions == null || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration()));
|
||||||
if (isStatic) flags |= ACC_STATIC;
|
|
||||||
|
|
||||||
boolean isAbstract = !isStatic && (bodyExpressions == null || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration()));
|
|
||||||
if (isAbstract) flags |= ACC_ABSTRACT;
|
if (isAbstract) flags |= ACC_ABSTRACT;
|
||||||
|
|
||||||
final MethodVisitor mv = v.newMethod(fun, flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
|
final MethodVisitor mv = v.newMethod(fun, flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
|
||||||
if(kind != OwnerKind.TRAIT_IMPL && v.generateCode()) {
|
if(v.generateCode()) {
|
||||||
int start = functionDescriptor.getReceiverParameter().exists() ? 1 : 0;
|
int start = 0;
|
||||||
|
if(kind != OwnerKind.TRAIT_IMPL) {
|
||||||
|
AnnotationVisitor av = mv.visitAnnotation("Ljet/typeinfo/JetMethod;", true);
|
||||||
|
if(functionDescriptor.getReturnType().isNullable()) {
|
||||||
|
av.visit("nullableReturnType", true);
|
||||||
|
}
|
||||||
|
av.visitEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(kind == OwnerKind.TRAIT_IMPL) {
|
||||||
|
AnnotationVisitor av = mv.visitParameterAnnotation(start++, "Ljet/typeinfo/JetParameter;", true);
|
||||||
|
av.visit("value", "this$self");
|
||||||
|
av.visitEnd();
|
||||||
|
}
|
||||||
|
if(receiverParameter.exists()) {
|
||||||
|
AnnotationVisitor av = mv.visitParameterAnnotation(start++, "Ljet/typeinfo/JetParameter;", true);
|
||||||
|
av.visit("value", "this$receiver");
|
||||||
|
if(receiverParameter.getType().isNullable()) {
|
||||||
|
av.visit("nullable", true);
|
||||||
|
}
|
||||||
|
av.visitEnd();
|
||||||
|
}
|
||||||
|
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
||||||
|
AnnotationVisitor av = mv.visitParameterAnnotation(start++, "Ljet/typeinfo/JetTypeParameter;", true);
|
||||||
|
av.visit("value", typeParameterDescriptor.getName());
|
||||||
|
av.visitEnd();
|
||||||
|
}
|
||||||
for(int i = 0; i != paramDescrs.size(); ++i) {
|
for(int i = 0; i != paramDescrs.size(); ++i) {
|
||||||
AnnotationVisitor annotationVisitor = mv.visitParameterAnnotation(i + start, "Ljet/typeinfo/JetParameterName;", true);
|
AnnotationVisitor av = mv.visitParameterAnnotation(i + start, "Ljet/typeinfo/JetParameter;", true);
|
||||||
annotationVisitor.visit("value", paramDescrs.get(i).getName());
|
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(i);
|
||||||
annotationVisitor.visitEnd();
|
av.visit("value", parameterDescriptor.getName());
|
||||||
|
if(parameterDescriptor.hasDefaultValue()) {
|
||||||
|
av.visit("hasDefaultValue", true);
|
||||||
|
}
|
||||||
|
if(parameterDescriptor.getOutType().isNullable()) {
|
||||||
|
av.visit("nullable", true);
|
||||||
|
}
|
||||||
|
av.visitEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isAbstract && v.generateCode()) {
|
if (!isAbstract && v.generateCode()) {
|
||||||
@@ -82,12 +121,18 @@ public class FunctionCodegen {
|
|||||||
Label methodBegin = new Label();
|
Label methodBegin = new Label();
|
||||||
mv.visitLabel(methodBegin);
|
mv.visitLabel(methodBegin);
|
||||||
|
|
||||||
FrameMap frameMap = context.prepareFrame();
|
FrameMap frameMap = context.prepareFrame(typeMapper);
|
||||||
|
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state);
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state);
|
||||||
|
|
||||||
Type[] argTypes = jvmSignature.getArgumentTypes();
|
Type[] argTypes = jvmSignature.getArgumentTypes();
|
||||||
int add = functionDescriptor.getReceiverParameter().exists() ? state.getTypeMapper().mapType(functionDescriptor.getReceiverParameter().getType()).getSize() : 0;
|
int add = 0;
|
||||||
|
|
||||||
|
if(kind == OwnerKind.TRAIT_IMPL)
|
||||||
|
add++;
|
||||||
|
|
||||||
|
if(receiverParameter.exists())
|
||||||
|
add++;
|
||||||
|
|
||||||
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
||||||
int slot = frameMap.enterTemp();
|
int slot = frameMap.enterTemp();
|
||||||
@@ -114,9 +159,9 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (ValueParameterDescriptor parameter : paramDescrs) {
|
for (ValueParameterDescriptor parameter : paramDescrs) {
|
||||||
Type sharedVarType = state.getTypeMapper().getSharedVarType(parameter);
|
Type sharedVarType = typeMapper.getSharedVarType(parameter);
|
||||||
Type localVarType = state.getTypeMapper().mapType(parameter.getOutType());
|
|
||||||
if (sharedVarType != null) {
|
if (sharedVarType != null) {
|
||||||
|
Type localVarType = typeMapper.mapType(parameter.getOutType());
|
||||||
int index = frameMap.getIndex(parameter);
|
int index = frameMap.getIndex(parameter);
|
||||||
mv.visitTypeInsn(NEW, sharedVarType.getInternalName());
|
mv.visitTypeInsn(NEW, sharedVarType.getInternalName());
|
||||||
mv.visitInsn(DUP);
|
mv.visitInsn(DUP);
|
||||||
@@ -134,13 +179,30 @@ public class FunctionCodegen {
|
|||||||
Label methodEnd = new Label();
|
Label methodEnd = new Label();
|
||||||
mv.visitLabel(methodEnd);
|
mv.visitLabel(methodEnd);
|
||||||
|
|
||||||
// http://youtrack.jetbrains.net/issue/KT-746
|
int k = 0;
|
||||||
// Fill LocalVariableTable with method parameter names
|
|
||||||
for (int i = 0; i < paramDescrs.size(); i++) {
|
if(expectedThisObject.exists()) {
|
||||||
ValueParameterDescriptor parameter = paramDescrs.get(i);
|
Type type = typeMapper.mapType(expectedThisObject.getType());
|
||||||
Type type = state.getTypeMapper().mapType(parameter.getOutType());
|
|
||||||
// TODO: specify signature
|
// TODO: specify signature
|
||||||
mv.visitLocalVariable(parameter.getName(), type.getDescriptor(), null, methodBegin, methodEnd, i + add);
|
mv.visitLocalVariable("this", type.getDescriptor(), null, methodBegin, methodEnd, k++);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(receiverParameter.exists()) {
|
||||||
|
Type type = typeMapper.mapType(receiverParameter.getType());
|
||||||
|
// TODO: specify signature
|
||||||
|
mv.visitLocalVariable("this$receiver", type.getDescriptor(), null, methodBegin, methodEnd, k);
|
||||||
|
k += type.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
||||||
|
mv.visitLocalVariable(typeParameterDescriptor.getName(), JetTypeMapper.TYPE_TYPEINFO.getDescriptor(), null, methodBegin, methodEnd, k++);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ValueParameterDescriptor parameter : paramDescrs) {
|
||||||
|
Type type = typeMapper.mapType(parameter.getOutType());
|
||||||
|
// TODO: specify signature
|
||||||
|
mv.visitLocalVariable(parameter.getName(), type.getDescriptor(), null, methodBegin, methodEnd, k);
|
||||||
|
k += type.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
@@ -164,7 +226,7 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void generateDefaultIfNeeded(CodegenContext.MethodContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
static void generateDefaultIfNeeded(CodegenContext.MethodContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, @Nullable FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
||||||
DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();
|
DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();
|
||||||
|
|
||||||
if(kind != OwnerKind.TRAIT_IMPL) {
|
if(kind != OwnerKind.TRAIT_IMPL) {
|
||||||
@@ -180,15 +242,18 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean needed = false;
|
boolean needed = false;
|
||||||
for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) {
|
if(functionDescriptor != null) {
|
||||||
if(parameterDescriptor.hasDefaultValue()) {
|
for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) {
|
||||||
needed = true;
|
if(parameterDescriptor.hasDefaultValue()) {
|
||||||
break;
|
needed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(needed) {
|
if(needed) {
|
||||||
boolean hasReceiver = functionDescriptor.getReceiverParameter().exists();
|
ReceiverDescriptor receiverParameter = functionDescriptor.getReceiverParameter();
|
||||||
|
boolean hasReceiver = receiverParameter.exists();
|
||||||
boolean isStatic = kind == OwnerKind.NAMESPACE;
|
boolean isStatic = kind == OwnerKind.NAMESPACE;
|
||||||
|
|
||||||
if(kind == OwnerKind.TRAIT_IMPL) {
|
if(kind == OwnerKind.TRAIT_IMPL) {
|
||||||
@@ -203,46 +268,42 @@ public class FunctionCodegen {
|
|||||||
state.getTypeMapper().mapType(((ClassDescriptor) contextClass).getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
|
state.getTypeMapper().mapType(((ClassDescriptor) contextClass).getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
|
||||||
|
|
||||||
String descriptor = jvmSignature.getDescriptor().replace(")","I)");
|
String descriptor = jvmSignature.getDescriptor().replace(")","I)");
|
||||||
if(!isStatic)
|
boolean isConstructor = "<init>".equals(jvmSignature.getName());
|
||||||
|
if(!isStatic && !isConstructor)
|
||||||
descriptor = descriptor.replace("(","(L" + ownerInternalName + ";");
|
descriptor = descriptor.replace("(","(L" + ownerInternalName + ";");
|
||||||
final MethodVisitor mv = v.newMethod(null, flags | ACC_STATIC, jvmSignature.getName() + "$default", descriptor, null, null);
|
final MethodVisitor mv = v.newMethod(null, flags | (isConstructor ? 0 : ACC_STATIC), isConstructor ? "<init>" : jvmSignature.getName() + "$default", descriptor, null, null);
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
if (v.generateCode()) {
|
if (v.generateCode()) {
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
|
|
||||||
FrameMap frameMap = owner.prepareFrame();
|
FrameMap frameMap = owner.prepareFrame(state.getTypeMapper());
|
||||||
|
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), owner, state);
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), owner, state);
|
||||||
|
|
||||||
int var = 0;
|
int var = 0;
|
||||||
if(!isStatic) {
|
if(!isStatic) {
|
||||||
frameMap.enterTemp();
|
|
||||||
var++;
|
var++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type receiverType = receiverParameter.exists() ? state.getTypeMapper().mapType(receiverParameter.getType()) : Type.DOUBLE_TYPE;
|
||||||
if(hasReceiver) {
|
if(hasReceiver) {
|
||||||
frameMap.enterTemp();
|
var += receiverType.getSize();
|
||||||
var++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
|
List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
|
||||||
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
||||||
int slot = frameMap.enterTemp();
|
if(typeParameterDescriptor.isReified()) {
|
||||||
codegen.addTypeParameter(typeParameterDescriptor, StackValue.local(slot, JetTypeMapper.TYPE_TYPEINFO));
|
codegen.addTypeParameter(typeParameterDescriptor, StackValue.local(var++, JetTypeMapper.TYPE_TYPEINFO));
|
||||||
var++;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Type[] argTypes = jvmSignature.getArgumentTypes();
|
Type[] argTypes = jvmSignature.getArgumentTypes();
|
||||||
List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
|
List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
|
||||||
for (int i = 0; i < paramDescrs.size(); i++) {
|
for (int i = 0; i < paramDescrs.size(); i++) {
|
||||||
ValueParameterDescriptor parameter = paramDescrs.get(i);
|
|
||||||
int size = argTypes[i + (hasReceiver ? 1 : 0)].getSize();
|
int size = argTypes[i + (hasReceiver ? 1 : 0)].getSize();
|
||||||
var += size;
|
var += size;
|
||||||
frameMap.enter(parameter, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
frameMap.enterTemp();
|
|
||||||
|
|
||||||
int maskIndex = var;
|
int maskIndex = var;
|
||||||
|
|
||||||
var = 0;
|
var = 0;
|
||||||
@@ -251,7 +312,8 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(hasReceiver) {
|
if(hasReceiver) {
|
||||||
mv.visitVarInsn(ALOAD, var++); // todo - Long etc.
|
iv.load(var, receiverType);
|
||||||
|
var += receiverType.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
int extra = hasReceiver ? 1 : 0;
|
int extra = hasReceiver ? 1 : 0;
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
|
CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
|
||||||
|
|
||||||
Method method;
|
Method constructorMethod;
|
||||||
CallableMethod callableMethod;
|
CallableMethod callableMethod;
|
||||||
if (constructorDescriptor == null) {
|
if (constructorDescriptor == null) {
|
||||||
List<Type> parameterTypes = new ArrayList<Type>();
|
List<Type> parameterTypes = new ArrayList<Type>();
|
||||||
@@ -282,17 +282,17 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO);
|
parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
method = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
constructorMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
||||||
callableMethod = new CallableMethod("", method, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
|
callableMethod = new CallableMethod("", constructorMethod, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
|
callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
|
||||||
method = callableMethod.getSignature();
|
constructorMethod = callableMethod.getSignature();
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectOrClosureCodegen closure = context.closure;
|
ObjectOrClosureCodegen closure = context.closure;
|
||||||
if(closure != null) {
|
if(closure != null) {
|
||||||
final List<Type> consArgTypes = new LinkedList<Type>(Arrays.asList(method.getArgumentTypes()));
|
final List<Type> consArgTypes = new LinkedList<Type>(Arrays.asList(constructorMethod.getArgumentTypes()));
|
||||||
|
|
||||||
int insert = 0;
|
int insert = 0;
|
||||||
if(closure.captureThis) {
|
if(closure.captureThis) {
|
||||||
@@ -319,11 +319,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
method = new Method("<init>", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()]));
|
constructorMethod = new Method("<init>", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
int flags = Opcodes.ACC_PUBLIC; // TODO
|
int flags = Opcodes.ACC_PUBLIC; // TODO
|
||||||
final MethodVisitor mv = v.newMethod(myClass, flags, "<init>", method.getDescriptor(), null, null);
|
final MethodVisitor mv = v.newMethod(myClass, flags, "<init>", constructorMethod.getDescriptor(), null, null);
|
||||||
if (!v.generateCode()) return;
|
if (!v.generateCode()) return;
|
||||||
|
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
@@ -470,6 +470,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
mv.visitInsn(Opcodes.RETURN);
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
|
|
||||||
|
FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod, constructorDescriptor, OwnerKind.IMPLEMENTATION );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateTraitMethods(ExpressionCodegen codegen) {
|
private void generateTraitMethods(ExpressionCodegen codegen) {
|
||||||
|
|||||||
@@ -348,9 +348,6 @@ public class JetTypeMapper {
|
|||||||
final JetType receiverType = !receiverTypeRef.exists() ? null : receiverTypeRef.getType();
|
final JetType receiverType = !receiverTypeRef.exists() ? null : receiverTypeRef.getType();
|
||||||
final List<ValueParameterDescriptor> parameters = f.getValueParameters();
|
final List<ValueParameterDescriptor> parameters = f.getValueParameters();
|
||||||
List<Type> parameterTypes = new ArrayList<Type>();
|
List<Type> parameterTypes = new ArrayList<Type>();
|
||||||
if (receiverType != null) {
|
|
||||||
parameterTypes.add(mapType(receiverType));
|
|
||||||
}
|
|
||||||
if(kind == OwnerKind.TRAIT_IMPL) {
|
if(kind == OwnerKind.TRAIT_IMPL) {
|
||||||
ClassDescriptor containingDeclaration = (ClassDescriptor) f.getContainingDeclaration();
|
ClassDescriptor containingDeclaration = (ClassDescriptor) f.getContainingDeclaration();
|
||||||
JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, bindingContext);
|
JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, bindingContext);
|
||||||
@@ -362,6 +359,9 @@ public class JetTypeMapper {
|
|||||||
valueParameterTypes.add(type);
|
valueParameterTypes.add(type);
|
||||||
parameterTypes.add(type);
|
parameterTypes.add(type);
|
||||||
}
|
}
|
||||||
|
if (receiverType != null) {
|
||||||
|
parameterTypes.add(mapType(receiverType));
|
||||||
|
}
|
||||||
for (TypeParameterDescriptor parameterDescriptor : f.getTypeParameters()) {
|
for (TypeParameterDescriptor parameterDescriptor : f.getTypeParameters()) {
|
||||||
if(parameterDescriptor.isReified()) {
|
if(parameterDescriptor.isReified()) {
|
||||||
parameterTypes.add(TYPE_TYPEINFO);
|
parameterTypes.add(TYPE_TYPEINFO);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
|
|||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||||
import org.jetbrains.jet.lang.types.Variance;
|
import org.jetbrains.jet.lang.types.Variance;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -17,6 +18,9 @@ import java.util.List;
|
|||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
public class SignatureUtil {
|
public class SignatureUtil {
|
||||||
|
private SignatureUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
public static String classToSignature(JetClass type, BindingContext bindingContext, JetTypeMapper typeMapper) {
|
public static String classToSignature(JetClass type, BindingContext bindingContext, JetTypeMapper typeMapper) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
genTypeParams(type, sb);
|
genTypeParams(type, sb);
|
||||||
@@ -33,7 +37,7 @@ public class SignatureUtil {
|
|||||||
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||||
if(descriptor instanceof ClassDescriptor) {
|
if(descriptor instanceof ClassDescriptor) {
|
||||||
JetType defaultType = ((ClassDescriptor) descriptor).getDefaultType();
|
JetType defaultType = ((ClassDescriptor) descriptor).getDefaultType();
|
||||||
org.objectweb.asm.Type type = typeMapper.mapType(defaultType, OwnerKind.IMPLEMENTATION);
|
Type type = typeMapper.mapType(defaultType, OwnerKind.IMPLEMENTATION);
|
||||||
if(JetTypeMapper.isPrimitive(type)) {
|
if(JetTypeMapper.isPrimitive(type)) {
|
||||||
type = JetTypeMapper.boxType(type);
|
type = JetTypeMapper.boxType(type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import org.jetbrains.jet.codegen.ExpressionCodegen;
|
|||||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||||
import org.jetbrains.jet.codegen.StackValue;
|
import org.jetbrains.jet.codegen.StackValue;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
import org.objectweb.asm.commons.InstructionAdapter;
|
import org.objectweb.asm.commons.InstructionAdapter;
|
||||||
|
|
||||||
@@ -31,11 +32,11 @@ public class BinaryOp implements IntrinsicMethod {
|
|||||||
if (receiver != null) {
|
if (receiver != null) {
|
||||||
receiver.put(expectedType, v);
|
receiver.put(expectedType, v);
|
||||||
}
|
}
|
||||||
codegen.gen(arguments.get(0), expectedType);
|
codegen.gen(arguments.get(0), shift() ? Type.INT_TYPE : expectedType);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
codegen.gen(arguments.get(0), expectedType);
|
codegen.gen(arguments.get(0), expectedType);
|
||||||
codegen.gen(arguments.get(1), expectedType);
|
codegen.gen(arguments.get(1), shift() ? Type.INT_TYPE : expectedType);
|
||||||
}
|
}
|
||||||
v.visitInsn(expectedType.getOpcode(opcode));
|
v.visitInsn(expectedType.getOpcode(opcode));
|
||||||
|
|
||||||
@@ -44,4 +45,8 @@ public class BinaryOp implements IntrinsicMethod {
|
|||||||
}
|
}
|
||||||
return StackValue.onStack(expectedType);
|
return StackValue.onStack(expectedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean shift() {
|
||||||
|
return opcode == Opcodes.ISHL || opcode == Opcodes.ISHR || opcode == Opcodes.IUSHR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,16 +18,24 @@ import java.util.List;
|
|||||||
public class RangeTo implements IntrinsicMethod {
|
public class RangeTo implements IntrinsicMethod {
|
||||||
@Override
|
@Override
|
||||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||||
JetBinaryExpression expression = (JetBinaryExpression) element;
|
if(arguments.size()==1) {
|
||||||
final Type leftType = codegen.expressionType(expression.getLeft());
|
receiver.put(Type.INT_TYPE, v);
|
||||||
if (JetTypeMapper.isIntPrimitive(leftType)) {
|
codegen.gen(arguments.get(0), Type.INT_TYPE);
|
||||||
codegen.gen(expression.getLeft(), Type.INT_TYPE);
|
|
||||||
codegen.gen(expression.getRight(), Type.INT_TYPE);
|
|
||||||
v.invokestatic("jet/IntRange", "rangeTo", "(II)Ljet/IntRange;");
|
v.invokestatic("jet/IntRange", "rangeTo", "(II)Ljet/IntRange;");
|
||||||
return StackValue.onStack(JetTypeMapper.TYPE_INT_RANGE);
|
return StackValue.onStack(JetTypeMapper.TYPE_INT_RANGE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException("ranges are only supported for int objects");
|
JetBinaryExpression expression = (JetBinaryExpression) element;
|
||||||
|
final Type leftType = codegen.expressionType(expression.getLeft());
|
||||||
|
if (JetTypeMapper.isIntPrimitive(leftType)) {
|
||||||
|
codegen.gen(expression.getLeft(), Type.INT_TYPE);
|
||||||
|
codegen.gen(expression.getRight(), Type.INT_TYPE);
|
||||||
|
v.invokestatic("jet/IntRange", "rangeTo", "(II)Ljet/IntRange;");
|
||||||
|
return StackValue.onStack(JetTypeMapper.TYPE_INT_RANGE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException("ranges are only supported for int objects");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Type reference element.
|
||||||
|
* Underlying token is {@link org.jetbrains.jet.JetNodeTypes#TYPE_REFERENCE}
|
||||||
|
*
|
||||||
* @author max
|
* @author max
|
||||||
*/
|
*/
|
||||||
public class JetTypeReference extends JetElement {
|
public class JetTypeReference extends JetElement {
|
||||||
|
|||||||
@@ -41,11 +41,15 @@ public interface BindingContext {
|
|||||||
WritableSlice<JetExpression, ResolvedCall<FunctionDescriptor>> INDEXED_LVALUE_SET = Slices.createSimpleSlice();
|
WritableSlice<JetExpression, ResolvedCall<FunctionDescriptor>> INDEXED_LVALUE_SET = Slices.createSimpleSlice();
|
||||||
|
|
||||||
WritableSlice<JetExpression, JetType> AUTOCAST = Slices.createSimpleSlice();
|
WritableSlice<JetExpression, JetType> AUTOCAST = Slices.createSimpleSlice();
|
||||||
|
|
||||||
|
/** A scope where type of expression has been resolved */
|
||||||
WritableSlice<JetExpression, JetScope> RESOLUTION_SCOPE = Slices.createSimpleSlice();
|
WritableSlice<JetExpression, JetScope> RESOLUTION_SCOPE = Slices.createSimpleSlice();
|
||||||
|
|
||||||
WritableSlice<JetExpression, Boolean> VARIABLE_REASSIGNMENT = Slices.createSimpleSetSlice();
|
WritableSlice<JetExpression, Boolean> VARIABLE_REASSIGNMENT = Slices.createSimpleSetSlice();
|
||||||
WritableSlice<ValueParameterDescriptor, Boolean> AUTO_CREATED_IT = Slices.createSimpleSetSlice();
|
WritableSlice<ValueParameterDescriptor, Boolean> AUTO_CREATED_IT = Slices.createSimpleSetSlice();
|
||||||
WritableSlice<JetExpression, DeclarationDescriptor> VARIABLE_ASSIGNMENT = Slices.createSimpleSlice();
|
WritableSlice<JetExpression, DeclarationDescriptor> VARIABLE_ASSIGNMENT = Slices.createSimpleSlice();
|
||||||
|
|
||||||
|
/** Has type of current expression has been already resolved */
|
||||||
WritableSlice<JetExpression, Boolean> PROCESSED = Slices.createSimpleSetSlice();
|
WritableSlice<JetExpression, Boolean> PROCESSED = Slices.createSimpleSetSlice();
|
||||||
WritableSlice<JetElement, Boolean> STATEMENT = Slices.createRemovableSetSlice();
|
WritableSlice<JetElement, Boolean> STATEMENT = Slices.createRemovableSetSlice();
|
||||||
WritableSlice<CallableMemberDescriptor, Boolean> DELEGATED = Slices.createRemovableSetSlice();
|
WritableSlice<CallableMemberDescriptor, Boolean> DELEGATED = Slices.createRemovableSetSlice();
|
||||||
|
|||||||
@@ -49,11 +49,14 @@ public class TypeResolver {
|
|||||||
JetTypeElement typeElement = typeReference.getTypeElement();
|
JetTypeElement typeElement = typeReference.getTypeElement();
|
||||||
JetType type = resolveTypeElement(scope, annotations, typeElement, false);
|
JetType type = resolveTypeElement(scope, annotations, typeElement, false);
|
||||||
trace.record(BindingContext.TYPE, typeReference, type);
|
trace.record(BindingContext.TYPE, typeReference, type);
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JetType resolveTypeElement(final JetScope scope, final List<AnnotationDescriptor> annotations, JetTypeElement typeElement, final boolean nullable) {
|
private JetType resolveTypeElement(final JetScope scope, final List<AnnotationDescriptor> annotations,
|
||||||
|
JetTypeElement typeElement, final boolean nullable) {
|
||||||
|
|
||||||
final JetType[] result = new JetType[1];
|
final JetType[] result = new JetType[1];
|
||||||
if (typeElement != null) {
|
if (typeElement != null) {
|
||||||
typeElement.accept(new JetVisitorVoid() {
|
typeElement.accept(new JetVisitorVoid() {
|
||||||
@@ -70,6 +73,7 @@ public class TypeResolver {
|
|||||||
resolveTypeProjections(scope, ErrorUtils.createErrorType("No type").getConstructor(), type.getTypeArguments());
|
resolveTypeProjections(scope, ErrorUtils.createErrorType("No type").getConstructor(), type.getTypeArguments());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (classifierDescriptor instanceof TypeParameterDescriptor) {
|
if (classifierDescriptor instanceof TypeParameterDescriptor) {
|
||||||
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) classifierDescriptor;
|
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) classifierDescriptor;
|
||||||
|
|
||||||
@@ -268,6 +272,8 @@ public class TypeResolver {
|
|||||||
ClassifierDescriptor classifierDescriptor;
|
ClassifierDescriptor classifierDescriptor;
|
||||||
if (userType.isAbsoluteInRootNamespace()) {
|
if (userType.isAbsoluteInRootNamespace()) {
|
||||||
classifierDescriptor = JetModuleUtil.getRootNamespaceType(userType).getMemberScope().getClassifier(referencedName);
|
classifierDescriptor = JetModuleUtil.getRootNamespaceType(userType).getMemberScope().getClassifier(referencedName);
|
||||||
|
trace.record(BindingContext.RESOLUTION_SCOPE, userType.getReferenceExpression(),
|
||||||
|
JetModuleUtil.getRootNamespaceType(userType).getMemberScope());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
JetUserType qualifier = userType.getQualifier();
|
JetUserType qualifier = userType.getQualifier();
|
||||||
@@ -278,7 +284,9 @@ public class TypeResolver {
|
|||||||
return ErrorUtils.getErrorClass();
|
return ErrorUtils.getErrorClass();
|
||||||
}
|
}
|
||||||
classifierDescriptor = scope.getClassifier(referencedName);
|
classifierDescriptor = scope.getClassifier(referencedName);
|
||||||
|
trace.record(BindingContext.RESOLUTION_SCOPE, userType.getReferenceExpression(), scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
return classifierDescriptor;
|
return classifierDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
fun escapeChar(c : Char) : String? = when (c) {
|
||||||
|
'\\' => "\\\\"
|
||||||
|
'\n' => "\\n"
|
||||||
|
'"' => "\\\""
|
||||||
|
else => String.valueOf(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun String.escape(i : Int = 0, result : String = "") : String =
|
||||||
|
if (i == length) result
|
||||||
|
else escape(i + 1, result + escapeChar(get(i)))
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
val s = " System.out?.println(\"fun escapeChar(c : Char) : String? = when (c) {\");\n System.out?.println(\" '\\\\\\\\' => \\\"\\\\\\\\\\\\\\\\\\\"\");\n System.out?.println(\" '\\\\n' => \\\"\\\\\\\\n\\\"\");\n System.out?.println(\" '\\\"' => \\\"\\\\\\\\\\\\\\\"\\\"\");\n System.out?.println(\" else => String.valueOf(c)\");\n System.out?.println(\"}\");\n System.out?.println();\n System.out?.println(\"fun String.escape(i : Int = 0, result : String = \\\"\\\") : String =\");\n System.out?.println(\" if (i == length) result\");\n System.out?.println(\" else escape(i + 1, result + escapeChar(this.get(i)))\");\n System.out?.println();\n System.out?.println(\"fun main(args : Array<String>) {\");\n System.out?.println(\" val s = \\\"\" + s.escape() + \"\\\";\");\n System.out?.println(s);\n}\n";
|
||||||
|
System.out?.println("fun escapeChar(c : Char) : String? = when (c) {");
|
||||||
|
System.out?.println(" '\\\\' => \"\\\\\\\\\"");
|
||||||
|
System.out?.println(" '\\n' => \"\\\\n\"");
|
||||||
|
System.out?.println(" '\"' => \"\\\\\\\"\"");
|
||||||
|
System.out?.println(" else => String.valueOf(c)");
|
||||||
|
System.out?.println("}");
|
||||||
|
System.out?.println();
|
||||||
|
System.out?.println("fun String.escape(i : Int = 0, result : String = \"\") : String =");
|
||||||
|
System.out?.println(" if (i == length) result");
|
||||||
|
System.out?.println(" else escape(i + 1, result + escapeChar(this.get(i)))");
|
||||||
|
System.out?.println();
|
||||||
|
System.out?.println("fun main(args : Array<String>) {");
|
||||||
|
System.out?.println(" val s = \"" + s.escape() + "\";");
|
||||||
|
System.out?.println(s);
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace demo_range
|
||||||
|
|
||||||
|
fun Int?.rangeTo(other : Int?) : IntRange = this.sure().rangeTo(other.sure())
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
val x : Int? = 10
|
||||||
|
val y : Int? = 12
|
||||||
|
|
||||||
|
for (i in x..y)
|
||||||
|
System.out?.println(i.inv())
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace bitwise_demo
|
||||||
|
|
||||||
|
fun Long?.shl(bits : Int?) : Long = this.sure().shl(bits.sure())
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
val x : Long? = 10
|
||||||
|
val y : Int? = 12
|
||||||
|
|
||||||
|
System.out?.println(x.shl(y))
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -317,7 +317,7 @@ public class PrimitiveTypesTest extends CodegenTestCase {
|
|||||||
|
|
||||||
public void testKt737() throws Exception {
|
public void testKt737() throws Exception {
|
||||||
loadText("fun box() = if(3.compareTo(2) != 1) \"fail\" else if(5.byt.compareTo(10.lng) >= 0) \"fail\" else \"OK\"");
|
loadText("fun box() = if(3.compareTo(2) != 1) \"fail\" else if(5.byt.compareTo(10.lng) >= 0) \"fail\" else \"OK\"");
|
||||||
System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
assertEquals("OK", blackBox());
|
assertEquals("OK", blackBox());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,4 +337,19 @@ public class PrimitiveTypesTest extends CodegenTestCase {
|
|||||||
// System.out.println(generateToText());
|
// System.out.println(generateToText());
|
||||||
blackBox();
|
blackBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testKt752 () {
|
||||||
|
blackBoxFile("regressions/kt752.jet");
|
||||||
|
// System.out.println(generateToText());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testKt753 () {
|
||||||
|
blackBoxFile("regressions/kt753.jet");
|
||||||
|
// System.out.println(generateToText());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testKt684 () {
|
||||||
|
blackBoxFile("regressions/kt684.jet");
|
||||||
|
// System.out.println(generateToText());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ class JetSimpleNameReference extends JetPsiReference {
|
|||||||
private Object[] collectLookupElements(BindingContext bindingContext, JetScope scope) {
|
private Object[] collectLookupElements(BindingContext bindingContext, JetScope scope) {
|
||||||
List<LookupElement> result = Lists.newArrayList();
|
List<LookupElement> result = Lists.newArrayList();
|
||||||
for (final DeclarationDescriptor descriptor : scope.getAllDescriptors()) {
|
for (final DeclarationDescriptor descriptor : scope.getAllDescriptors()) {
|
||||||
PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor.getOriginal());
|
|
||||||
LookupElementBuilder element = LookupElementBuilder.create(descriptor.getName());
|
LookupElementBuilder element = LookupElementBuilder.create(descriptor.getName());
|
||||||
String typeText = "";
|
String typeText = "";
|
||||||
String tailText = "";
|
String tailText = "";
|
||||||
@@ -108,9 +107,12 @@ class JetSimpleNameReference extends JetPsiReference {
|
|||||||
typeText = DescriptorRenderer.TEXT.render(descriptor);
|
typeText = DescriptorRenderer.TEXT.render(descriptor);
|
||||||
}
|
}
|
||||||
element = element.setTailText(tailText, tailTextGrayed).setTypeText(typeText);
|
element = element.setTailText(tailText, tailTextGrayed).setTypeText(typeText);
|
||||||
|
|
||||||
|
PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor.getOriginal());
|
||||||
if (declaration != null) {
|
if (declaration != null) {
|
||||||
element = element.setIcon(declaration.getIcon(Iconable.ICON_FLAG_OPEN | Iconable.ICON_FLAG_VISIBILITY));
|
element = element.setIcon(declaration.getIcon(Iconable.ICON_FLAG_OPEN | Iconable.ICON_FLAG_VISIBILITY));
|
||||||
}
|
}
|
||||||
|
|
||||||
result.add(element);
|
result.add(element);
|
||||||
}
|
}
|
||||||
return result.toArray();
|
return result.toArray();
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
open class MySecondClass() {
|
||||||
|
}
|
||||||
|
|
||||||
|
open class MyFirstClass<T> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class A() : My<caret> {
|
||||||
|
public fun test() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: MySecondClass, MyFirstClass
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Test.SubTest.AnotherTest
|
||||||
|
|
||||||
|
open class TestClass {
|
||||||
|
}
|
||||||
|
|
||||||
|
class A() : Test.SubTest.AnotherTest.Te<caret> {
|
||||||
|
public fun test() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: TestClass
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
open class MyClass() {
|
||||||
|
}
|
||||||
|
|
||||||
|
class A() : My<caret> {
|
||||||
|
public fun test() {
|
||||||
|
val a : MyC<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: MyClass
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package org.jetbrains.jet.completion;
|
||||||
|
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.JetTestCaseBuilder;
|
||||||
|
import org.jetbrains.jet.plugin.PluginTestCaseBase;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nikolay.Krasko
|
||||||
|
*/
|
||||||
|
public class JetBasicCompletionTest extends JetCompletionTestBase {
|
||||||
|
private final String myPath;
|
||||||
|
private final String myName;
|
||||||
|
|
||||||
|
public JetBasicCompletionTest(@NotNull String path, @NotNull String name) {
|
||||||
|
myPath = path;
|
||||||
|
myName = name;
|
||||||
|
|
||||||
|
// Set name explicitly because otherwise there will be "TestCase.fName cannot be null"
|
||||||
|
setName("testCompletionExecute");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCompletionExecute() {
|
||||||
|
doTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTestDataPath() {
|
||||||
|
return new File(PluginTestCaseBase.getTestDataPathBase(), myPath).getPath() +
|
||||||
|
File.separator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "test" + myName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static TestSuite suite() {
|
||||||
|
TestSuite suite = new TestSuite();
|
||||||
|
|
||||||
|
JetTestCaseBuilder.appendTestsInDirectory(
|
||||||
|
PluginTestCaseBase.getTestDataPathBase(), "/completion/basic/", false,
|
||||||
|
JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) {
|
||||||
|
return new JetBasicCompletionTest(dataPath, name);
|
||||||
|
}
|
||||||
|
}, suite);
|
||||||
|
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,10 +22,10 @@ public class KeywordsCompletionTest extends JetCompletionTestBase {
|
|||||||
myName = name;
|
myName = name;
|
||||||
|
|
||||||
// Set name explicitly because otherwise there will be "TestCase.fName cannot be null"
|
// Set name explicitly because otherwise there will be "TestCase.fName cannot be null"
|
||||||
setName("testComletionExecute");
|
setName("testCompletionExecute");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testComletionExecute() {
|
public void testCompletionExecute() {
|
||||||
doTest();
|
doTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package jet.typeinfo;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for method
|
||||||
|
*
|
||||||
|
* The fact of receiver presence must be deducted from presence of 'this$receiver' parameter
|
||||||
|
*
|
||||||
|
* @author alex.tkachman
|
||||||
|
*/
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface JetMethod {
|
||||||
|
/**
|
||||||
|
* @return type projections or empty
|
||||||
|
*/
|
||||||
|
JetTypeProjection[] returnTypeProjections() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return is this type returnTypeNullable
|
||||||
|
*/
|
||||||
|
boolean nullableReturnType() default false;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package jet.typeinfo;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for parameters
|
||||||
|
*
|
||||||
|
* @author alex.tkachman
|
||||||
|
*/
|
||||||
|
@Target({ElementType.PARAMETER})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface JetParameter {
|
||||||
|
/**
|
||||||
|
* @return name of parameter
|
||||||
|
*/
|
||||||
|
String name ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return type projections or empty
|
||||||
|
*/
|
||||||
|
JetTypeProjection[] typeProjections() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return is this type nullable
|
||||||
|
*/
|
||||||
|
boolean nullable () default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return if this parameter has default value
|
||||||
|
*/
|
||||||
|
boolean hasDefaultValue () default false;
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package jet.typeinfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author alex.tkachman
|
||||||
|
*/
|
||||||
|
public @interface JetTypeDescriptor{
|
||||||
|
//
|
||||||
|
// case of type parameter
|
||||||
|
//
|
||||||
|
String varName() default "";
|
||||||
|
boolean reified () default true;
|
||||||
|
TypeInfoVariance variance() default TypeInfoVariance.INVARIANT;
|
||||||
|
int [] upperBounds() default {};
|
||||||
|
|
||||||
|
//
|
||||||
|
// case of real type
|
||||||
|
//
|
||||||
|
Class javaClass() default Object.class;
|
||||||
|
JetTypeProjection [] projections() default {};
|
||||||
|
}
|
||||||
+7
-2
@@ -6,10 +6,15 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Annotation for parameters
|
||||||
|
*
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
@Target({ElementType.PARAMETER})
|
@Target({ElementType.PARAMETER})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface JetParameterName {
|
public @interface JetTypeParameter {
|
||||||
String value ();
|
/**
|
||||||
|
* @return name of parameter
|
||||||
|
*/
|
||||||
|
String name();
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package jet.typeinfo;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author alex.tkachman
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface JetTypeProjection {
|
||||||
|
/**
|
||||||
|
* @return variance of the type
|
||||||
|
*/
|
||||||
|
TypeInfoVariance variance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return index of the class in the per class table of JetTypeDescriptor
|
||||||
|
*/
|
||||||
|
int typeDescriptorIndex();
|
||||||
|
}
|
||||||
@@ -60,7 +60,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
// @NotNull
|
// @NotNull
|
||||||
@Override
|
@Override
|
||||||
public TypeInfoVariance getVariance() {
|
public TypeInfoVariance getVariance() {
|
||||||
return TypeInfoVariance.IN_VARIANCE;
|
return TypeInfoVariance.IN;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,7 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
// @NotNull
|
// @NotNull
|
||||||
@Override
|
@Override
|
||||||
public TypeInfoVariance getVariance() {
|
public TypeInfoVariance getVariance() {
|
||||||
return TypeInfoVariance.OUT_VARIANCE;
|
return TypeInfoVariance.OUT;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -606,11 +606,11 @@ public abstract class TypeInfo<T> implements JetObject {
|
|||||||
private TypeInfoVariance parseVariance() {
|
private TypeInfoVariance parseVariance() {
|
||||||
if(string[cur] == 'i' && string[cur+1] == 'n' && string[cur+2] == ' ' ) {
|
if(string[cur] == 'i' && string[cur+1] == 'n' && string[cur+2] == ' ' ) {
|
||||||
cur += 3;
|
cur += 3;
|
||||||
return TypeInfoVariance.IN_VARIANCE;
|
return TypeInfoVariance.IN;
|
||||||
}
|
}
|
||||||
else if (string[cur] == 'o' && string[cur+1] == 'u' && string[cur+2] == 't' && string[cur+3] == ' ') {
|
else if (string[cur] == 'o' && string[cur+1] == 'u' && string[cur+2] == 't' && string[cur+3] == ' ') {
|
||||||
cur += 4;
|
cur += 4;
|
||||||
return TypeInfoVariance.OUT_VARIANCE;
|
return TypeInfoVariance.OUT;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return TypeInfoVariance.INVARIANT;
|
return TypeInfoVariance.INVARIANT;
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ package jet.typeinfo;
|
|||||||
*/
|
*/
|
||||||
public enum TypeInfoVariance {
|
public enum TypeInfoVariance {
|
||||||
INVARIANT("") ,
|
INVARIANT("") ,
|
||||||
IN_VARIANCE("in"),
|
IN("in"),
|
||||||
OUT_VARIANCE("out");
|
OUT("out");
|
||||||
|
|
||||||
private final String label;
|
private final String label;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user