Merge remote-tracking branch 'origin/master'

This commit is contained in:
svtk
2011-12-08 13:43:56 +04:00
80 changed files with 2197 additions and 498 deletions
@@ -19,7 +19,7 @@ import java.util.List;
*/ */
public class CallableMethod implements Callable { public class CallableMethod implements Callable {
private String owner; private String owner;
private final Method signature; private final JvmMethodSignature signature;
private int invokeOpcode; private int invokeOpcode;
private final List<Type> valueParameterTypes; private final List<Type> valueParameterTypes;
private ClassDescriptor thisClass = null; private ClassDescriptor thisClass = null;
@@ -27,7 +27,7 @@ public class CallableMethod implements Callable {
private CallableDescriptor receiverFunction = null; private CallableDescriptor receiverFunction = null;
private Type generateCalleeType = null; private Type generateCalleeType = null;
public CallableMethod(String owner, Method signature, int invokeOpcode, List<Type> valueParameterTypes) { public CallableMethod(String owner, JvmMethodSignature signature, int invokeOpcode, List<Type> valueParameterTypes) {
this.owner = owner; this.owner = owner;
this.signature = signature; this.signature = signature;
this.invokeOpcode = invokeOpcode; this.invokeOpcode = invokeOpcode;
@@ -38,7 +38,7 @@ public class CallableMethod implements Callable {
return owner; return owner;
} }
public Method getSignature() { public JvmMethodSignature getSignature() {
return signature; return signature;
} }
@@ -67,7 +67,7 @@ public class CallableMethod implements Callable {
} }
void invoke(InstructionAdapter v) { void invoke(InstructionAdapter v) {
v.visitMethodInsn(getInvokeOpcode(), getOwner(), getSignature().getName(), getSignature().getDescriptor()); v.visitMethodInsn(getInvokeOpcode(), getOwner(), getSignature().getAsmMethod().getName(), getSignature().getAsmMethod().getDescriptor());
} }
public void requestGenerateCallee(Type objectType) { public void requestGenerateCallee(Type objectType) {
@@ -80,14 +80,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().getAsmMethod().getDescriptor().replace(")", "I)");
if("<init>".equals(getSignature().getName())) { if("<init>".equals(getSignature().getAsmMethod().getName())) {
v.visitMethodInsn(Opcodes.INVOKESPECIAL, getOwner(), "<init>", desc); v.visitMethodInsn(Opcodes.INVOKESPECIAL, getOwner(), "<init>", desc);
} }
else { else {
if(getInvokeOpcode() != Opcodes.INVOKESTATIC) if(getInvokeOpcode() != Opcodes.INVOKESTATIC)
desc = desc.replace("(", "(L" + getOwner() + ";"); desc = desc.replace("(", "(L" + getOwner() + ";");
v.visitMethodInsn(Opcodes.INVOKESTATIC, getInvokeOpcode() == Opcodes.INVOKEINTERFACE ? getOwner() + "$$TImpl" : getOwner(), getSignature().getName() + "$default", desc); v.visitMethodInsn(Opcodes.INVOKESTATIC, getInvokeOpcode() == Opcodes.INVOKEINTERFACE ? getOwner() + "$$TImpl" : getOwner(), getSignature().getAsmMethod().getName() + "$default", desc);
} }
} }
@@ -10,7 +10,6 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody; import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFunctionLiteral;
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression; import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
@@ -54,7 +53,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
public static CallableMethod asCallableMethod(FunctionDescriptor fd) { public static CallableMethod asCallableMethod(FunctionDescriptor fd) {
Method descriptor = erasedInvokeSignature(fd); Method descriptor = erasedInvokeSignature(fd);
String owner = getInternalClassName(fd); String owner = getInternalClassName(fd);
final CallableMethod result = new CallableMethod(owner, descriptor, INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes())); final CallableMethod result = new CallableMethod(owner, new JvmMethodSignature(descriptor, null), INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
if (fd.getReceiverParameter().exists()) { if (fd.getReceiverParameter().exists()) {
result.setNeedsReceiver(fd); result.setNeedsReceiver(fd);
} }
@@ -63,7 +62,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
} }
public Method invokeSignature(FunctionDescriptor fd) { public Method invokeSignature(FunctionDescriptor fd) {
return state.getTypeMapper().mapSignature("invoke", fd); return state.getTypeMapper().mapSignature("invoke", fd).getAsmMethod();
} }
public GeneratedAnonymousClassDescriptor gen(JetFunctionLiteralExpression fun) { public GeneratedAnonymousClassDescriptor gen(JetFunctionLiteralExpression fun) {
@@ -100,7 +99,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
generateBridge(name, funDescriptor, fun, cv); generateBridge(name, funDescriptor, fun, cv);
captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral()); captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral());
ClassDescriptor thisDescriptor = context.getThisDescriptor(); ClassDescriptor thisDescriptor = context.getThisDescriptor();
final Type enclosingType = thisDescriptor == null ? null : Type.getObjectType(thisDescriptor.getName()); final Type enclosingType = thisDescriptor == null ? null : state.getTypeMapper().mapType(thisDescriptor.getDefaultType());
if (enclosingType == null) if (enclosingType == null)
captureThis = false; captureThis = false;
@@ -164,9 +163,9 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
Collections.<TypeParameterDescriptor>emptyList(), Collections.<TypeParameterDescriptor>emptyList(),
Collections.singleton((funDescriptor.getReceiverParameter().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity)).getDefaultType()), JetScope.EMPTY, Collections.<ConstructorDescriptor>emptySet(), null); Collections.singleton((funDescriptor.getReceiverParameter().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity)).getDefaultType()), JetScope.EMPTY, Collections.<ConstructorDescriptor>emptySet(), null);
final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this); final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this, state.getTypeMapper());
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state); FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor); fc.generateMethod(body, new JvmMethodSignature(invokeSignature(funDescriptor), null), funDescriptor);
return closureContext.outerWasUsed; return closureContext.outerWasUsed;
} }
@@ -177,7 +176,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
if(bridge.getDescriptor().equals(delegate.getDescriptor())) if(bridge.getDescriptor().equals(delegate.getDescriptor()))
return; return;
final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "invoke", bridge.getDescriptor(), state.getTypeMapper().genericSignature(funDescriptor), new String[0]); final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "invoke", bridge.getDescriptor(), null, new String[0]);
if (cv.generateCode()) { if (cv.generateCode()) {
mv.visitCode(); mv.visitCode();
@@ -104,24 +104,24 @@ public abstract class CodegenContext {
return new ClassContext(descriptor, kind, this, typeMapper); return new ClassContext(descriptor, kind, this, typeMapper);
} }
public CodegenContext intoAnonymousClass(@NotNull ObjectOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind) { public CodegenContext intoAnonymousClass(@NotNull ObjectOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind, JetTypeMapper typeMapper) {
return new AnonymousClassContext(descriptor, kind, this, closure); return new AnonymousClassContext(descriptor, kind, this, closure, typeMapper);
} }
public MethodContext intoFunction(FunctionDescriptor descriptor) { public MethodContext intoFunction(FunctionDescriptor descriptor) {
return new MethodContext(descriptor, getContextKind(), this); return new MethodContext(descriptor, getContextKind(), this);
} }
public ConstructorContext intoConstructor(ConstructorDescriptor descriptor) { public ConstructorContext intoConstructor(ConstructorDescriptor descriptor, JetTypeMapper typeMapper) {
if(descriptor == null) { if(descriptor == null) {
descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.<AnnotationDescriptor>emptyList(), true) descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.<AnnotationDescriptor>emptyList(), true)
.initialize(Collections.<TypeParameterDescriptor>emptyList(), Collections.<ValueParameterDescriptor>emptyList(), Modality.OPEN, Visibility.PUBLIC); .initialize(Collections.<TypeParameterDescriptor>emptyList(), Collections.<ValueParameterDescriptor>emptyList(), Modality.OPEN, Visibility.PUBLIC);
} }
return new ConstructorContext(descriptor, getContextKind(), this); return new ConstructorContext(descriptor, getContextKind(), this, typeMapper);
} }
public ClosureContext intoClosure(FunctionDescriptor funDescriptor, ClassDescriptor classDescriptor, String internalClassName, ClosureCodegen closureCodegen) { public ClosureContext intoClosure(FunctionDescriptor funDescriptor, ClassDescriptor classDescriptor, String internalClassName, ClosureCodegen closureCodegen, JetTypeMapper typeMapper) {
return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName); return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName, typeMapper);
} }
public FrameMap prepareFrame(JetTypeMapper mapper) { public FrameMap prepareFrame(JetTypeMapper mapper) {
@@ -170,12 +170,12 @@ public abstract class CodegenContext {
return parentContext != null ? parentContext.lookupInContext(d, v, result) : null; return parentContext != null ? parentContext.lookupInContext(d, v, result) : null;
} }
public Type enclosingClassType() { public Type enclosingClassType(JetTypeMapper typeMapper) {
CodegenContext cur = getParentContext(); CodegenContext cur = getParentContext();
while(cur != null && !(cur.getContextDescriptor() instanceof ClassDescriptor)) while(cur != null && !(cur.getContextDescriptor() instanceof ClassDescriptor))
cur = cur.getParentContext(); cur = cur.getParentContext();
return cur == null ? null : Type.getObjectType(cur.getContextDescriptor().getName()); return cur == null ? null : typeMapper.mapType(((ClassDescriptor)cur.getContextDescriptor()).getDefaultType());
} }
public int getTypeInfoConstantIndex(JetType type) { public int getTypeInfoConstantIndex(JetType type) {
@@ -290,8 +290,8 @@ public abstract class CodegenContext {
return getParentContext().lookupInContext(d, v, result); return getParentContext().lookupInContext(d, v, result);
} }
public Type enclosingClassType() { public Type enclosingClassType(JetTypeMapper typeMapper) {
return getParentContext().enclosingClassType(); return getParentContext().enclosingClassType(typeMapper);
} }
@Override @Override
@@ -305,10 +305,10 @@ public abstract class CodegenContext {
} }
public static class ConstructorContext extends MethodContext { public static class ConstructorContext extends MethodContext {
public ConstructorContext(ConstructorDescriptor contextType, OwnerKind kind, CodegenContext parent) { public ConstructorContext(ConstructorDescriptor contextType, OwnerKind kind, CodegenContext parent, JetTypeMapper typeMapper) {
super(contextType, kind, parent); super(contextType, kind, parent);
final Type type = enclosingClassType(); final Type type = enclosingClassType(typeMapper);
outerExpression = type != null outerExpression = type != null
? local1 ? local1
: null; : null;
@@ -323,7 +323,7 @@ public abstract class CodegenContext {
public ClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, JetTypeMapper typeMapper) { public ClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, JetTypeMapper typeMapper) {
super(contextType, contextKind, parentContext, null); super(contextType, contextKind, parentContext, null);
final Type type = enclosingClassType(); final Type type = enclosingClassType(typeMapper);
outerExpression = type != null outerExpression = type != null
? StackValue.field(type, typeMapper.getFQName(contextType), "this$0", false) ? StackValue.field(type, typeMapper.getFQName(contextType), "this$0", false)
: null; : null;
@@ -341,10 +341,10 @@ public abstract class CodegenContext {
} }
public static class AnonymousClassContext extends CodegenContext { public static class AnonymousClassContext extends CodegenContext {
public AnonymousClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closure) { public AnonymousClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closure, JetTypeMapper typeMapper) {
super(contextType, contextKind, parentContext, closure); super(contextType, contextKind, parentContext, closure);
final Type type = enclosingClassType(); final Type type = enclosingClassType(typeMapper);
outerExpression = type != null outerExpression = type != null
? StackValue.field(type, closure.state.getTypeMapper().mapType(contextType.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "this$0", false) ? StackValue.field(type, closure.state.getTypeMapper().mapType(contextType.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "this$0", false)
: null; : null;
@@ -364,11 +364,11 @@ public abstract class CodegenContext {
public static class ClosureContext extends ReceiverContext { public static class ClosureContext extends ReceiverContext {
private ClassDescriptor classDescriptor; private ClassDescriptor classDescriptor;
public ClosureContext(FunctionDescriptor contextType, ClassDescriptor classDescriptor, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closureCodegen, String internalClassName) { public ClosureContext(FunctionDescriptor contextType, ClassDescriptor classDescriptor, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closureCodegen, String internalClassName, JetTypeMapper typeMapper) {
super(contextType, OwnerKind.IMPLEMENTATION, parentContext, closureCodegen); super(contextType, OwnerKind.IMPLEMENTATION, parentContext, closureCodegen);
this.classDescriptor = classDescriptor; this.classDescriptor = classDescriptor;
final Type type = enclosingClassType(); final Type type = enclosingClassType(typeMapper);
outerExpression = type != null outerExpression = type != null
? StackValue.field(type, internalClassName, "this$0", false) ? StackValue.field(type, internalClassName, "this$0", false)
: null; : null;
@@ -43,9 +43,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
private static final String CLASS_NO_PATTERN_MATCHED_EXCEPTION = "jet/NoPatternMatchedException"; private static final String CLASS_NO_PATTERN_MATCHED_EXCEPTION = "jet/NoPatternMatchedException";
private static final String CLASS_TYPE_CAST_EXCEPTION = "jet/TypeCastException"; private static final String CLASS_TYPE_CAST_EXCEPTION = "jet/TypeCastException";
private final Stack<Label> myContinueTargets = new Stack<Label>();
private final Stack<Label> myBreakTargets = new Stack<Label>();
private int myLastLineNumber = -1; private int myLastLineNumber = -1;
final InstructionAdapter v; final InstructionAdapter v;
@@ -60,7 +57,29 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
private final CodegenContext context; private final CodegenContext context;
private final IntrinsicMethods intrinsics; private final IntrinsicMethods intrinsics;
private final ArrayList<JetTryExpression> stackOfFinallyBlocks = new ArrayList<JetTryExpression>(); private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>();
static class BlockStackElement {
}
static class LoopBlockStackElement extends BlockStackElement {
final Label continueLabel;
final Label breakLabel;
LoopBlockStackElement(Label breakLabel, Label continueLabel) {
this.breakLabel = breakLabel;
this.continueLabel = continueLabel;
}
}
static class FinallyBlockStackElement extends BlockStackElement {
final JetTryExpression expression;
FinallyBlockStackElement(JetTryExpression expression) {
this.expression = expression;
}
}
public ExpressionCodegen(MethodVisitor v, public ExpressionCodegen(MethodVisitor v,
FrameMap myMap, FrameMap myMap,
@@ -225,11 +244,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override @Override
public StackValue visitWhileExpression(JetWhileExpression expression, StackValue receiver) { public StackValue visitWhileExpression(JetWhileExpression expression, StackValue receiver) {
Label condition = new Label(); Label condition = new Label();
myContinueTargets.push(condition);
v.mark(condition); v.mark(condition);
Label end = continueLabel != null ? continueLabel : new Label(); Label end = continueLabel != null ? continueLabel : new Label();
myBreakTargets.push(end); blockStackElements.push(new LoopBlockStackElement(end, condition));
Label savedContinueLabel = continueLabel; Label savedContinueLabel = continueLabel;
continueLabel = condition; continueLabel = condition;
@@ -243,8 +261,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
continueLabel = savedContinueLabel; continueLabel = savedContinueLabel;
if(end != continueLabel) if(end != continueLabel)
v.mark(end); v.mark(end);
myBreakTargets.pop();
myContinueTargets.pop(); blockStackElements.pop();
return StackValue.onStack(Type.VOID_TYPE); return StackValue.onStack(Type.VOID_TYPE);
} }
@@ -253,10 +271,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
public StackValue visitDoWhileExpression(JetDoWhileExpression expression, StackValue receiver) { public StackValue visitDoWhileExpression(JetDoWhileExpression expression, StackValue receiver) {
Label condition = new Label(); Label condition = new Label();
v.mark(condition); v.mark(condition);
myContinueTargets.push(condition);
Label end = new Label(); Label end = new Label();
myBreakTargets.push(end);
blockStackElements.push(new LoopBlockStackElement(end, condition));
gen(expression.getBody(), Type.VOID_TYPE); gen(expression.getBody(), Type.VOID_TYPE);
@@ -265,8 +283,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.mark(end); v.mark(end);
myBreakTargets.pop(); blockStackElements.pop();
myContinueTargets.pop();
return StackValue.onStack(Type.VOID_TYPE); return StackValue.onStack(Type.VOID_TYPE);
} }
@@ -328,8 +345,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
Label begin = new Label(); Label begin = new Label();
myContinueTargets.push(begin); blockStackElements.push(new LoopBlockStackElement(end, begin));
myBreakTargets.push(end);
v.mark(begin); v.mark(begin);
v.load(iteratorVar, asmIterType); v.load(iteratorVar, asmIterType);
@@ -365,8 +381,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
//noinspection ConstantConditions //noinspection ConstantConditions
v.visitLocalVariable(loopParameter.getName(), asmParamType.getDescriptor(), null, begin, end, paramIndex); v.visitLocalVariable(loopParameter.getName(), asmParamType.getDescriptor(), null, begin, end, paramIndex);
myFrameMap.leaveTemp(); myFrameMap.leaveTemp();
myBreakTargets.pop();
myContinueTargets.pop(); blockStackElements.pop();
} }
private OwnerKind contextKind() { private OwnerKind contextKind() {
@@ -398,8 +414,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
Label condition = new Label(); Label condition = new Label();
Label increment = new Label(); Label increment = new Label();
v.mark(condition); v.mark(condition);
myContinueTargets.push(increment);
myBreakTargets.push(end); blockStackElements.push(new LoopBlockStackElement(end, increment));
generateCondition(asmParamType, end); generateCondition(asmParamType, end);
@@ -414,8 +430,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final int paramIndex = myFrameMap.leave(parameterDescriptor); final int paramIndex = myFrameMap.leave(parameterDescriptor);
//noinspection ConstantConditions //noinspection ConstantConditions
v.visitLocalVariable(expression.getLoopParameter().getName(), asmParamType.getDescriptor(), null, condition, end, paramIndex); v.visitLocalVariable(expression.getLoopParameter().getName(), asmParamType.getDescriptor(), null, condition, end, paramIndex);
myBreakTargets.pop();
myContinueTargets.pop(); blockStackElements.pop();
} }
protected void generatePrologue() { protected void generatePrologue() {
@@ -536,21 +552,51 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override @Override
public StackValue visitBreakExpression(JetBreakExpression expression, StackValue receiver) { public StackValue visitBreakExpression(JetBreakExpression expression, StackValue receiver) {
JetSimpleNameExpression labelElement = expression.getTargetLabel(); JetSimpleNameExpression labelElement = expression.getTargetLabel();
Label label = labelElement == null ? myBreakTargets.peek() : null; // TODO: for(int i = blockStackElements.size()-1; i >= 0; --i) {
BlockStackElement stackElement = blockStackElements.get(i);
v.goTo(label); if(stackElement instanceof FinallyBlockStackElement) {
return StackValue.none(); FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement;
JetTryExpression jetTryExpression = finallyBlockStackElement.expression;
gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE);
}
else if(stackElement instanceof LoopBlockStackElement) {
LoopBlockStackElement loopBlockStackElement = (LoopBlockStackElement) stackElement;
Label label = labelElement == null ? loopBlockStackElement.breakLabel : null; // TODO:
v.goTo(label);
return StackValue.none();
}
else {
throw new UnsupportedOperationException();
}
}
throw new UnsupportedOperationException();
} }
@Override @Override
public StackValue visitContinueExpression(JetContinueExpression expression, StackValue receiver) { public StackValue visitContinueExpression(JetContinueExpression expression, StackValue receiver) {
String labelName = expression.getLabelName(); JetSimpleNameExpression labelElement = expression.getTargetLabel();
Label label = labelName == null ? myContinueTargets.peek() : null; // TODO: for(int i = blockStackElements.size()-1; i >= 0; --i) {
BlockStackElement stackElement = blockStackElements.get(i);
if(stackElement instanceof FinallyBlockStackElement) {
FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement;
JetTryExpression jetTryExpression = finallyBlockStackElement.expression;
gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE);
}
else if(stackElement instanceof LoopBlockStackElement) {
LoopBlockStackElement loopBlockStackElement = (LoopBlockStackElement) stackElement;
Label label = labelElement == null ? loopBlockStackElement.continueLabel : null; // TODO:
v.goTo(label);
return StackValue.none();
}
else {
throw new UnsupportedOperationException();
}
}
v.goTo(label); throw new UnsupportedOperationException();
return StackValue.none();
} }
private StackValue generateSingleBranchIf(StackValue condition, JetExpression expression, boolean inverse) { private StackValue generateSingleBranchIf(StackValue condition, JetExpression expression, boolean inverse) {
@@ -763,12 +809,18 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
private void doFinallyOnReturnOrThrow() { private void doFinallyOnReturnOrThrow() {
if(stackOfFinallyBlocks.size() > 0) { for(int i = blockStackElements.size()-1; i >= 0; --i) {
JetTryExpression jetTryExpression = stackOfFinallyBlocks.remove(stackOfFinallyBlocks.size()-1); BlockStackElement stackElement = blockStackElements.get(i);
//noinspection ConstantConditions if(stackElement instanceof FinallyBlockStackElement) {
gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE); FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement;
doFinallyOnReturnOrThrow(); JetTryExpression jetTryExpression = finallyBlockStackElement.expression;
stackOfFinallyBlocks.add(jetTryExpression); blockStackElements.pop();
gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE);
blockStackElements.push(finallyBlockStackElement);
}
else {
break;
}
} }
} }
@@ -991,7 +1043,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
} }
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, functionDescriptor.getName(), typeMapper.mapSignature(functionDescriptor.getName(),functionDescriptor).getDescriptor()); v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, functionDescriptor.getName(), typeMapper.mapSignature(functionDescriptor.getName(),functionDescriptor).getAsmMethod().getDescriptor());
StackValue.onStack(asmType(functionDescriptor.getReturnType())).coerce(type, v); StackValue.onStack(asmType(functionDescriptor.getReturnType())).coerce(type, v);
} }
@@ -1034,7 +1086,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
} }
if(!(containingDeclaration instanceof JavaNamespaceDescriptor) && !(containingDeclaration instanceof JavaClassDescriptor)) if(!(containingDeclaration instanceof JavaNamespaceDescriptor) && !(containingDeclaration instanceof JavaClassDescriptor))
getter = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION); getter = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION).getAsmMethod();
else else
getter = null; getter = null;
} }
@@ -1043,10 +1095,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
setter = null; setter = null;
} }
else { else {
if(!(containingDeclaration instanceof JavaNamespaceDescriptor) && !(containingDeclaration instanceof JavaClassDescriptor)) if(!(containingDeclaration instanceof JavaNamespaceDescriptor) && !(containingDeclaration instanceof JavaClassDescriptor)) {
setter = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION); JvmMethodSignature jvmMethodSignature = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
else setter = jvmMethodSignature != null ? jvmMethodSignature.getAsmMethod() : null;
} else {
setter = null; setter = null;
}
} }
} }
@@ -1119,7 +1173,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final CallableMethod callableMethod = (CallableMethod) callable; final CallableMethod callableMethod = (CallableMethod) callable;
invokeMethodWithArguments(callableMethod, expression, receiver); invokeMethodWithArguments(callableMethod, expression, receiver);
final Type callReturnType = callableMethod.getSignature().getReturnType(); final Type callReturnType = callableMethod.getSignature().getAsmMethod().getReturnType();
return returnValueAsStackValue((FunctionDescriptor) fd, callReturnType); return returnValueAsStackValue((FunctionDescriptor) fd, callReturnType);
} }
else { else {
@@ -1478,7 +1532,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
pushTypeArguments(resolvedCall); pushTypeArguments(resolvedCall);
pushMethodArguments(resolvedCall, callableMethod.getValueParameterTypes()); pushMethodArguments(resolvedCall, callableMethod.getValueParameterTypes());
callableMethod.invoke(v); callableMethod.invoke(v);
return returnValueAsStackValue((FunctionDescriptor) op, callableMethod.getSignature().getReturnType()); return returnValueAsStackValue((FunctionDescriptor) op, callableMethod.getSignature().getAsmMethod().getReturnType());
} }
} }
} }
@@ -1850,7 +1904,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
CallableMethod callableMethod = (CallableMethod) callable; CallableMethod callableMethod = (CallableMethod) callable;
genToJVMStack(expression.getBaseExpression()); genToJVMStack(expression.getBaseExpression());
callableMethod.invoke(v); callableMethod.invoke(v);
return returnValueAsStackValue((FunctionDescriptor) op, callableMethod.getSignature().getReturnType()); return returnValueAsStackValue((FunctionDescriptor) op, callableMethod.getSignature().getAsmMethod().getReturnType());
} }
} }
@@ -1958,26 +2012,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} else { } else {
ClassDescriptor classDecl = (ClassDescriptor) constructorDescriptor.getContainingDeclaration(); ClassDescriptor classDecl = (ClassDescriptor) constructorDescriptor.getContainingDeclaration();
receiver.put(receiver.type, v);
v.anew(type); v.anew(type);
v.dup();
// TODO typechecker must verify that we're the outer class of the instance being created // TODO typechecker must verify that we're the outer class of the instance being created
//noinspection ConstantConditions //noinspection ConstantConditions
if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) { if(!receiver.type.equals(Type.VOID_TYPE)) {
if(!receiver.type.equals(Type.VOID_TYPE)) { receiver.put(receiver.type, v);
// class object is in receiver
v.dupX1();
v.swap();
}
else {
// this$0 need to be put on stack
v.dup();
v.load(0, typeMapper.mapType(classDecl.getDefaultType(), OwnerKind.IMPLEMENTATION));
}
}
else {
// regular case
v.dup();
} }
CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION); CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION);
@@ -2128,7 +2169,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
else { else {
CallableMethod accessor = typeMapper.mapToCallableMethod(operationDescriptor, false, OwnerKind.IMPLEMENTATION); CallableMethod accessor = typeMapper.mapToCallableMethod(operationDescriptor, false, OwnerKind.IMPLEMENTATION);
boolean isGetter = accessor.getSignature().getName().equals("get"); boolean isGetter = accessor.getSignature().getAsmMethod().getName().equals("get");
ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression); ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression);
ResolvedCall<FunctionDescriptor> resolvedGetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression); ResolvedCall<FunctionDescriptor> resolvedGetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression);
@@ -2137,7 +2178,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
FunctionDescriptor getterDescriptor = resolvedGetCall == null ? null : resolvedGetCall.getResultingDescriptor(); FunctionDescriptor getterDescriptor = resolvedGetCall == null ? null : resolvedGetCall.getResultingDescriptor();
Type asmType; Type asmType;
Type[] argumentTypes = accessor.getSignature().getArgumentTypes(); Type[] argumentTypes = accessor.getSignature().getAsmMethod().getArgumentTypes();
int index = 0; int index = 0;
if(isGetter) { if(isGetter) {
Callable callable = resolveToCallable(getterDescriptor, false); Callable callable = resolveToCallable(getterDescriptor, false);
@@ -2158,7 +2199,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
index++; index++;
} }
} }
asmType = accessor.getSignature().getReturnType(); asmType = accessor.getSignature().getAsmMethod().getReturnType();
} }
else { else {
assert resolvedSetCall != null; assert resolvedSetCall != null;
@@ -2219,9 +2260,12 @@ The "returned" value of try expression with no finally is either the last expres
If finally block is present, its last expression is the value of try expression. If finally block is present, its last expression is the value of try expression.
*/ */
Label savedContinueLabel = continueLabel;
continueLabel = null;
JetFinallySection finallyBlock = expression.getFinallyBlock(); JetFinallySection finallyBlock = expression.getFinallyBlock();
if(finallyBlock != null) { if(finallyBlock != null) {
stackOfFinallyBlocks.add(expression); blockStackElements.push(new FinallyBlockStackElement(expression));
} }
JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression); JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression);
@@ -2278,9 +2322,11 @@ If finally block is present, its last expression is the value of try expression.
v.nop(); v.nop();
if(finallyBlock != null) { if(finallyBlock != null) {
stackOfFinallyBlocks.remove(stackOfFinallyBlocks.size()-1); blockStackElements.pop();
} }
continueLabel = savedContinueLabel;
return StackValue.onStack(expectedAsmType); return StackValue.onStack(expectedAsmType);
} }
@@ -2575,13 +2621,21 @@ If finally block is present, its last expression is the value of try expression.
public StackValue visitWhenExpression(JetWhenExpression expression, StackValue receiver) { public StackValue visitWhenExpression(JetWhenExpression expression, StackValue receiver) {
JetExpression expr = expression.getSubjectExpression(); JetExpression expr = expression.getSubjectExpression();
final Type subjectType = expressionType(expr); final Type subjectType = expressionType(expr);
final Type resultType = expressionType(expression);
final int subjectLocal = myFrameMap.enterTemp(subjectType.getSize()); final int subjectLocal = myFrameMap.enterTemp(subjectType.getSize());
gen(expr, subjectType); gen(expr, subjectType);
v.store(subjectLocal, subjectType); v.store(subjectLocal, subjectType);
Label end = new Label(); Label end = new Label();
Label nextCondition = null;
boolean hasElse = false; boolean hasElse = false;
for (JetWhenEntry whenEntry : expression.getEntries()) {
if(whenEntry.isElse()) {
hasElse = true;
break;
}
}
Label nextCondition = null;
for (JetWhenEntry whenEntry : expression.getEntries()) { for (JetWhenEntry whenEntry : expression.getEntries()) {
if (nextCondition != null) { if (nextCondition != null) {
v.mark(nextCondition); v.mark(nextCondition);
@@ -2601,13 +2655,13 @@ If finally block is present, its last expression is the value of try expression.
} }
} }
} }
else {
hasElse = true;
}
v.visitLabel(thisEntry); v.visitLabel(thisEntry);
genToJVMStack(whenEntry.getExpression()); gen(whenEntry.getExpression(), resultType);
mark.dropTo(); mark.dropTo();
v.goTo(end); if (!whenEntry.isElse()) {
v.goTo(end);
}
} }
if (!hasElse && nextCondition != null) { if (!hasElse && nextCondition != null) {
v.mark(nextCondition); v.mark(nextCondition);
@@ -2616,7 +2670,7 @@ If finally block is present, its last expression is the value of try expression.
v.mark(end); v.mark(end);
myFrameMap.leaveTemp(subjectType.getSize()); myFrameMap.leaveTemp(subjectType.getSize());
return StackValue.onStack(expressionType(expression)); return StackValue.onStack(resultType);
} }
private StackValue generateWhenCondition(Type subjectType, int subjectLocal, JetWhenCondition condition, @Nullable Label nextEntry) { private StackValue generateWhenCondition(Type subjectType, int subjectLocal, JetWhenCondition condition, @Nullable Label nextEntry) {
@@ -6,13 +6,19 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.StdlibNames;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; 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.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Label; import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.InstructionAdapter;
import org.objectweb.asm.commons.Method; import org.objectweb.asm.commons.Method;
import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.signature.SignatureWriter;
import org.objectweb.asm.util.CheckSignatureAdapter;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@@ -40,11 +46,11 @@ public class FunctionCodegen {
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 = typeMapper.mapToCallableMethod(functionDescriptor, false, owner.getContextKind()).getSignature(); JvmMethodSignature method = typeMapper.mapToCallableMethod(functionDescriptor, false, owner.getContextKind()).getSignature();
generateMethod(f, method, functionDescriptor); generateMethod(f, method, functionDescriptor);
} }
public void generateMethod(JetDeclarationWithBody f, Method jvmMethod, FunctionDescriptor functionDescriptor) { public void generateMethod(JetDeclarationWithBody f, JvmMethodSignature jvmMethod, FunctionDescriptor functionDescriptor) {
CodegenContext.MethodContext funContext = owner.intoFunction(functionDescriptor); CodegenContext.MethodContext funContext = owner.intoFunction(functionDescriptor);
final JetExpression bodyExpression = f.getBodyExpression(); final JetExpression bodyExpression = f.getBodyExpression();
@@ -52,7 +58,7 @@ public class FunctionCodegen {
} }
private void generatedMethod(JetExpression bodyExpressions, private void generatedMethod(JetExpression bodyExpressions,
Method jvmSignature, JvmMethodSignature jvmSignature,
CodegenContext.MethodContext context, CodegenContext.MethodContext context,
FunctionDescriptor functionDescriptor, JetDeclarationWithBody fun) FunctionDescriptor functionDescriptor, JetDeclarationWithBody fun)
{ {
@@ -73,45 +79,45 @@ public class FunctionCodegen {
boolean isAbstract = !isStatic && !(kind == OwnerKind.TRAIT_IMPL) && (bodyExpressions == null || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration())); boolean isAbstract = !isStatic && !(kind == OwnerKind.TRAIT_IMPL) && (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.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor(), jvmSignature.getGenericsSignature(), null);
if(v.generateCode()) { if(v.generateCode()) {
int start = 0; int start = 0;
if(kind != OwnerKind.TRAIT_IMPL) { if(kind != OwnerKind.TRAIT_IMPL) {
AnnotationVisitor av = mv.visitAnnotation("Ljet/typeinfo/JetMethod;", true); AnnotationVisitor av = mv.visitAnnotation(StdlibNames.JET_METHOD_TYPE.getDescriptor(), true);
if(functionDescriptor.getReturnType().isNullable()) { if(functionDescriptor.getReturnType().isNullable()) {
av.visit("nullableReturnType", true); av.visit(StdlibNames.JET_METHOD_NULLABLE_RETURN_TYPE_FIELD, true);
} }
av.visitEnd(); av.visitEnd();
} }
if(kind == OwnerKind.TRAIT_IMPL) { if(kind == OwnerKind.TRAIT_IMPL) {
AnnotationVisitor av = mv.visitParameterAnnotation(start++, "Ljet/typeinfo/JetParameter;", true); AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_PARAMETER_DESCRIPTOR, true);
av.visit("value", "this$self"); av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, "this$self");
av.visitEnd(); av.visitEnd();
} }
if(receiverParameter.exists()) { if(receiverParameter.exists()) {
AnnotationVisitor av = mv.visitParameterAnnotation(start++, "Ljet/typeinfo/JetParameter;", true); AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_PARAMETER_DESCRIPTOR, true);
av.visit("value", "this$receiver"); av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, "this$receiver");
if(receiverParameter.getType().isNullable()) { if(receiverParameter.getType().isNullable()) {
av.visit("nullable", true); av.visit(StdlibNames.JET_PARAMETER_NULLABLE_FIELD, true);
} }
av.visitEnd(); av.visitEnd();
} }
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) { for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
AnnotationVisitor av = mv.visitParameterAnnotation(start++, "Ljet/typeinfo/JetTypeParameter;", true); AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_TYPE_PARAMETER_DESCRIPTOR, true);
av.visit("value", typeParameterDescriptor.getName()); av.visit(StdlibNames.JET_TYPE_PARAMETER_NAME_FIELD, typeParameterDescriptor.getName());
av.visitEnd(); av.visitEnd();
} }
for(int i = 0; i != paramDescrs.size(); ++i) { for(int i = 0; i != paramDescrs.size(); ++i) {
AnnotationVisitor av = mv.visitParameterAnnotation(i + start, "Ljet/typeinfo/JetParameter;", true); AnnotationVisitor av = mv.visitParameterAnnotation(i + start, StdlibNames.JET_PARAMETER_DESCRIPTOR, true);
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(i); ValueParameterDescriptor parameterDescriptor = paramDescrs.get(i);
av.visit("name", parameterDescriptor.getName()); av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, parameterDescriptor.getName());
if(parameterDescriptor.hasDefaultValue()) { if(parameterDescriptor.hasDefaultValue()) {
av.visit("hasDefaultValue", true); av.visit(StdlibNames.JET_PARAMETER_HAS_DEFAULT_FIELD, true);
} }
if(parameterDescriptor.getOutType().isNullable()) { if(parameterDescriptor.getOutType().isNullable()) {
av.visit("nullable", true); av.visit(StdlibNames.JET_PARAMETER_NULLABLE_FIELD, true);
} }
av.visitEnd(); av.visitEnd();
} }
@@ -124,9 +130,9 @@ public class FunctionCodegen {
FrameMap frameMap = context.prepareFrame(typeMapper); FrameMap frameMap = context.prepareFrame(typeMapper);
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getAsmMethod().getReturnType(), context, state);
Type[] argTypes = jvmSignature.getArgumentTypes(); Type[] argTypes = jvmSignature.getAsmMethod().getArgumentTypes();
int add = 0; int add = 0;
if(kind == OwnerKind.TRAIT_IMPL) if(kind == OwnerKind.TRAIT_IMPL)
@@ -155,8 +161,8 @@ public class FunctionCodegen {
Type argType = argTypes[i]; Type argType = argTypes[i];
iv.load(i + 1, argType); iv.load(i + 1, argType);
} }
iv.invokeinterface(dk.getOwnerClass(), jvmSignature.getName(), jvmSignature.getDescriptor()); iv.invokeinterface(dk.getOwnerClass(), jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor());
iv.areturn(jvmSignature.getReturnType()); iv.areturn(jvmSignature.getAsmMethod().getReturnType());
} }
else { else {
for (ValueParameterDescriptor parameter : paramDescrs) { for (ValueParameterDescriptor parameter : paramDescrs) {
@@ -209,11 +215,11 @@ public class FunctionCodegen {
mv.visitMaxs(0, 0); mv.visitMaxs(0, 0);
mv.visitEnd(); mv.visitEnd();
generateBridgeIfNeeded(owner, state, v, jvmSignature, functionDescriptor, kind); generateBridgeIfNeeded(owner, state, v, jvmSignature.getAsmMethod(), functionDescriptor, kind);
} }
} }
generateDefaultIfNeeded(context, state, v, jvmSignature, functionDescriptor, kind); generateDefaultIfNeeded(context, state, v, jvmSignature.getAsmMethod(), functionDescriptor, kind);
} }
static void generateBridgeIfNeeded(CodegenContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) { static void generateBridgeIfNeeded(CodegenContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
@@ -379,7 +385,7 @@ public class FunctionCodegen {
Type type1 = state.getTypeMapper().mapType(overriddenFunction.getOriginal().getReturnType()); Type type1 = state.getTypeMapper().mapType(overriddenFunction.getOriginal().getReturnType());
Type type2 = state.getTypeMapper().mapType(functionDescriptor.getReturnType()); Type type2 = state.getTypeMapper().mapType(functionDescriptor.getReturnType());
if(!type1.equals(type2)) { if(!type1.equals(type2)) {
Method overriden = state.getTypeMapper().mapSignature(overriddenFunction.getName(), overriddenFunction.getOriginal()); Method overriden = state.getTypeMapper().mapSignature(overriddenFunction.getName(), overriddenFunction.getOriginal()).getAsmMethod();
int flags = ACC_PUBLIC; // TODO. int flags = ACC_PUBLIC; // TODO.
final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overriden.getDescriptor(), null, null); final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overriden.getDescriptor(), null, null);
@@ -140,13 +140,13 @@ public class GenerationState {
closure.cv = nameAndVisitor.getSecond(); closure.cv = nameAndVisitor.getSecond();
closure.name = nameAndVisitor.getFirst(); closure.name = nameAndVisitor.getFirst();
final CodegenContext objectContext = closure.context.intoAnonymousClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION); final CodegenContext objectContext = closure.context.intoAnonymousClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION, typeMapper);
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate(null); new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate(null);
ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration); ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration);
CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION); CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, callableMethod.getSignature(), objectContext.outerWasUsed, null); return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, callableMethod.getSignature().getAsmMethod(), objectContext.outerWasUsed, null);
} }
public static void prepareAnonymousClasses(JetElement aClass, final JetTypeMapper typeMapper) { public static void prepareAnonymousClasses(JetElement aClass, final JetTypeMapper typeMapper) {
@@ -138,8 +138,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue(); FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
FunctionDescriptor original = (FunctionDescriptor) entry.getKey(); FunctionDescriptor original = (FunctionDescriptor) entry.getKey();
Method method = typeMapper.mapSignature(bridge.getName(), bridge); Method method = typeMapper.mapSignature(bridge.getName(), bridge).getAsmMethod();
Method originalMethod = typeMapper.mapSignature(original.getName(), original); Method originalMethod = typeMapper.mapSignature(original.getName(), original).getAsmMethod();
Type[] argTypes = method.getArgumentTypes(); Type[] argTypes = method.getArgumentTypes();
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, bridge.getName(), method.getDescriptor(), null, null); MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, bridge.getName(), method.getDescriptor(), null, null);
@@ -166,8 +166,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue(); PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
PropertyDescriptor original = (PropertyDescriptor) entry.getKey(); PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION); Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod();
Method originalMethod = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION); Method originalMethod = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION).getAsmMethod();
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null); MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
InstructionAdapter iv = null; InstructionAdapter iv = null;
if (v.generateCode()) { if (v.generateCode()) {
@@ -186,8 +186,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
mv.visitEnd(); mv.visitEnd();
} }
method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION); method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod();
originalMethod = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION); originalMethod = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION).getAsmMethod();
mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null); mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
if (v.generateCode()) { if (v.generateCode()) {
mv.visitCode(); mv.visitCode();
@@ -267,7 +267,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass); ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass);
CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor); CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, typeMapper);
Method constructorMethod; Method constructorMethod;
CallableMethod callableMethod; CallableMethod callableMethod;
@@ -283,11 +283,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
constructorMethod = 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("", constructorMethod, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList()); callableMethod = new CallableMethod("", new JvmMethodSignature(constructorMethod, null) /* TODO */, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
} }
else { else {
callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind); callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
constructorMethod = callableMethod.getSignature(); constructorMethod = callableMethod.getSignature().getAsmMethod();
} }
ObjectOrClosureCodegen closure = context.closure; ObjectOrClosureCodegen closure = context.closure;
@@ -471,7 +471,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
mv.visitMaxs(0, 0); mv.visitMaxs(0, 0);
mv.visitEnd(); mv.visitEnd();
FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod, constructorDescriptor, OwnerKind.IMPLEMENTATION ); FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod, constructorDescriptor, OwnerKind.IMPLEMENTATION);
} }
private void generateTraitMethods(ExpressionCodegen codegen) { private void generateTraitMethods(ExpressionCodegen codegen) {
@@ -490,8 +490,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if(jetClass.isTrait()) { if(jetClass.isTrait()) {
int flags = Opcodes.ACC_PUBLIC; // TODO. int flags = Opcodes.ACC_PUBLIC; // TODO.
Method function = typeMapper.mapSignature(fun.getName(), fun); Method function = typeMapper.mapSignature(fun.getName(), fun).getAsmMethod();
Method functionOriginal = typeMapper.mapSignature(fun.getName(), fun.getOriginal()); Method functionOriginal = typeMapper.mapSignature(fun.getName(), fun.getOriginal()).getAsmMethod();
final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null); final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null);
if (v.generateCode()) { if (v.generateCode()) {
@@ -629,7 +629,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind); CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
int flags = Opcodes.ACC_PUBLIC; // TODO int flags = Opcodes.ACC_PUBLIC; // TODO
final MethodVisitor mv = v.newMethod(constructor, flags, "<init>", method.getSignature().getDescriptor(), null, null); final MethodVisitor mv = v.newMethod(constructor, flags, "<init>", method.getSignature().getAsmMethod().getDescriptor(), null, null);
if (v.generateCode()) { if (v.generateCode()) {
mv.visitCode(); mv.visitCode();
@@ -5,6 +5,7 @@ import jet.JetObject;
import jet.typeinfo.TypeInfo; import jet.typeinfo.TypeInfo;
import jet.typeinfo.TypeInfoProjection; import jet.typeinfo.TypeInfoProjection;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
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;
@@ -17,6 +18,9 @@ import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method; import org.objectweb.asm.commons.Method;
import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.signature.SignatureWriter;
import org.objectweb.asm.util.CheckSignatureAdapter;
import java.util.*; import java.util.*;
@@ -82,7 +86,7 @@ public class JetTypeMapper {
public static final Type TYPE_LONG_ITERATOR = Type.getObjectType("jet/LongIterator"); public static final Type TYPE_LONG_ITERATOR = Type.getObjectType("jet/LongIterator");
public static final Type TYPE_FLOAT_ITERATOR = Type.getObjectType("jet/FloatIterator"); public static final Type TYPE_FLOAT_ITERATOR = Type.getObjectType("jet/FloatIterator");
public static final Type TYPE_DOUBLE_ITERATOR = Type.getObjectType("jet/DoubleIterator"); public static final Type TYPE_DOUBLE_ITERATOR = Type.getObjectType("jet/DoubleIterator");
public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) { public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) {
this.standardLibrary = standardLibrary; this.standardLibrary = standardLibrary;
this.bindingContext = bindingContext; this.bindingContext = bindingContext;
@@ -151,13 +155,23 @@ public class JetTypeMapper {
} }
@NotNull public Type mapReturnType(final JetType jetType) { @NotNull public Type mapReturnType(final JetType jetType) {
return mapReturnType(jetType, null);
}
@NotNull private Type mapReturnType(final JetType jetType, @Nullable SignatureVisitor signatureVisitor) {
if (jetType.equals(JetStandardClasses.getUnitType()) || jetType.equals(JetStandardClasses.getNothingType())) { if (jetType.equals(JetStandardClasses.getUnitType()) || jetType.equals(JetStandardClasses.getNothingType())) {
if (signatureVisitor != null) {
signatureVisitor.visitBaseType('V');
}
return Type.VOID_TYPE; return Type.VOID_TYPE;
} }
if (jetType.equals(JetStandardClasses.getNullableNothingType())) { if (jetType.equals(JetStandardClasses.getNullableNothingType())) {
if (signatureVisitor != null) {
visitAsmType(signatureVisitor, TYPE_OBJECT);
}
return TYPE_OBJECT; return TYPE_OBJECT;
} }
return mapType(jetType, OwnerKind.IMPLEMENTATION); return mapType(jetType, OwnerKind.IMPLEMENTATION, signatureVisitor);
} }
private HashMap<DeclarationDescriptor,Map<DeclarationDescriptor,String>> naming = new HashMap<DeclarationDescriptor, Map<DeclarationDescriptor, String>>(); private HashMap<DeclarationDescriptor,Map<DeclarationDescriptor,String>> naming = new HashMap<DeclarationDescriptor, Map<DeclarationDescriptor, String>>();
@@ -201,15 +215,28 @@ public class JetTypeMapper {
return name; return name;
} }
@NotNull public Type mapType(final JetType jetType) { @NotNull public Type mapType(final JetType jetType) {
return mapType(jetType, OwnerKind.IMPLEMENTATION); return mapType(jetType, (SignatureVisitor) null);
}
@NotNull private Type mapType(JetType jetType, @Nullable SignatureVisitor signatureVisitor) {
return mapType(jetType, OwnerKind.IMPLEMENTATION, signatureVisitor);
} }
@NotNull public Type mapType(@NotNull final JetType jetType, OwnerKind kind) { @NotNull public Type mapType(@NotNull final JetType jetType, OwnerKind kind) {
return mapType(jetType, kind, null);
}
@NotNull private Type mapType(JetType jetType, OwnerKind kind, @Nullable SignatureVisitor signatureVisitor) {
return mapType(jetType, kind, signatureVisitor, false);
}
@NotNull private Type mapType(JetType jetType, OwnerKind kind, @Nullable SignatureVisitor signatureVisitor, boolean typeParameter) {
Type known = knowTypes.get(jetType); Type known = knowTypes.get(jetType);
if(known != null) if (known != null) {
return known; return mapKnownAsmType(jetType, known, signatureVisitor, typeParameter);
}
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
if (standardLibrary.getArray().equals(descriptor)) { if (standardLibrary.getArray().equals(descriptor)) {
@@ -217,10 +244,18 @@ public class JetTypeMapper {
throw new UnsupportedOperationException("arrays must have one type argument"); throw new UnsupportedOperationException("arrays must have one type argument");
} }
JetType memberType = jetType.getArguments().get(0).getType(); JetType memberType = jetType.getArguments().get(0).getType();
if(!isGenericsArray(jetType))
if (signatureVisitor != null) {
SignatureVisitor arraySignatureVisitor = signatureVisitor.visitArrayType();
// TODO: box
mapType(memberType, kind, arraySignatureVisitor);
}
if (!isGenericsArray(jetType)) {
return Type.getType("[" + boxType(mapType(memberType, kind)).getDescriptor()); return Type.getType("[" + boxType(mapType(memberType, kind)).getDescriptor());
else } else {
return ARRAY_GENERIC_TYPE; return ARRAY_GENERIC_TYPE;
}
} }
if (JetStandardClasses.getAny().equals(descriptor)) { if (JetStandardClasses.getAny().equals(descriptor)) {
@@ -228,16 +263,64 @@ public class JetTypeMapper {
} }
if (descriptor instanceof ClassDescriptor) { if (descriptor instanceof ClassDescriptor) {
String name = getFQName(descriptor); String name = getFQName(descriptor);
return Type.getObjectType(name + (kind == OwnerKind.TRAIT_IMPL ? "$$TImpl" : "")); Type asmType = Type.getObjectType(name + (kind == OwnerKind.TRAIT_IMPL ? "$$TImpl" : ""));
if (signatureVisitor != null) {
signatureVisitor.visitClassType(asmType.getInternalName());
for (TypeProjection proj : jetType.getArguments()) {
// TODO: +-
SignatureVisitor argumentSignatureVisitor = signatureVisitor.visitTypeArgument('=');
mapType(proj.getType(), kind, argumentSignatureVisitor, true);
}
signatureVisitor.visitEnd();
}
return asmType;
} }
if (descriptor instanceof TypeParameterDescriptor) { if (descriptor instanceof TypeParameterDescriptor) {
if (signatureVisitor != null) {
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) jetType.getConstructor().getDeclarationDescriptor();
signatureVisitor.visitTypeVariable(typeParameterDescriptor.getName());
}
return mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind); return mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind);
} }
throw new UnsupportedOperationException("Unknown type " + jetType); throw new UnsupportedOperationException("Unknown type " + jetType);
} }
private Type mapKnownAsmType(JetType jetType, Type asmType, @Nullable SignatureVisitor signatureVisitor, boolean genericTypeParameter) {
if (signatureVisitor != null) {
if (genericTypeParameter) {
visitAsmType(signatureVisitor, boxType(asmType));
} else {
visitAsmType(signatureVisitor, asmType);
}
}
return asmType;
}
private void visitAsmType(SignatureVisitor visitor, Type asmType) {
switch (asmType.getSort()) {
case Type.OBJECT:
visitor.visitClassType(asmType.getInternalName());
visitor.visitEnd();
return;
case Type.ARRAY:
SignatureVisitor elementSignatureVisitor = visitor.visitArrayType();
visitAsmType(elementSignatureVisitor, asmType.getElementType());
return;
default:
String descriptor = asmType.getDescriptor();
if (descriptor.length() != 1) {
throw new IllegalStateException();
}
visitor.visitBaseType(descriptor.charAt(0));
}
}
public static Type unboxType(final Type type) { public static Type unboxType(final Type type) {
if (type == JL_INTEGER_TYPE) { if (type == JL_INTEGER_TYPE) {
@@ -292,6 +375,7 @@ public class JetTypeMapper {
return asmType; return asmType;
} }
private static final boolean DEBUG_SIGNATURE_WRITER = true;
public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, boolean superCall, OwnerKind kind) { public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, boolean superCall, OwnerKind kind) {
if(functionDescriptor == null) if(functionDescriptor == null)
@@ -299,7 +383,7 @@ public class JetTypeMapper {
final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration(); final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration();
final List<Type> valueParameterTypes = new ArrayList<Type>(); final List<Type> valueParameterTypes = new ArrayList<Type>();
Method descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, kind); JvmMethodSignature descriptor = mapSignature(functionDescriptor.getOriginal(), true, valueParameterTypes, kind);
String owner; String owner;
int invokeOpcode; int invokeOpcode;
ClassDescriptor thisClass; ClassDescriptor thisClass;
@@ -326,7 +410,7 @@ public class JetTypeMapper {
? (superCall ? Opcodes.INVOKESTATIC : Opcodes.INVOKEINTERFACE) ? (superCall ? Opcodes.INVOKESTATIC : Opcodes.INVOKEINTERFACE)
: (superCall ? Opcodes.INVOKESPECIAL : Opcodes.INVOKEVIRTUAL); : (superCall ? Opcodes.INVOKESPECIAL : Opcodes.INVOKEVIRTUAL);
if(isInterface && superCall) { if(isInterface && superCall) {
descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, OwnerKind.TRAIT_IMPL); descriptor = mapSignature(functionDescriptor.getOriginal(), false, valueParameterTypes, OwnerKind.TRAIT_IMPL);
} }
thisClass = (ClassDescriptor) functionParent; thisClass = (ClassDescriptor) functionParent;
} }
@@ -343,7 +427,36 @@ public class JetTypeMapper {
return result; return result;
} }
private Method mapSignature(FunctionDescriptor f, List<Type> valueParameterTypes, OwnerKind kind) { private JvmMethodSignature mapSignature(FunctionDescriptor f, boolean needGenericSignature, List<Type> valueParameterTypes, OwnerKind kind) {
for (ValueParameterDescriptor valueParameterDescriptor : f.getValueParameters()) {
if (valueParameterDescriptor.hasDefaultValue()) {
// TODO
needGenericSignature = false;
}
}
if (kind == OwnerKind.TRAIT_IMPL) {
needGenericSignature = false;
}
SignatureWriter signatureWriter = null;
SignatureVisitor signatureVisitor = null;
if (needGenericSignature) {
signatureWriter = new SignatureWriter();
signatureVisitor = DEBUG_SIGNATURE_WRITER ? new CheckSignatureAdapter(CheckSignatureAdapter.METHOD_SIGNATURE, signatureWriter) : signatureWriter;
}
for (TypeParameterDescriptor typeParameterDescriptor : f.getTypeParameters()) {
if (signatureVisitor != null) {
signatureVisitor.visitFormalTypeParameter(typeParameterDescriptor.getName());
SignatureVisitor classBoundVisitor = signatureVisitor.visitClassBound();
// TODO: wrong base
visitAsmType(classBoundVisitor, TYPE_OBJECT);
// TODO: interfaces
}
}
final ReceiverDescriptor receiverTypeRef = f.getReceiverParameter(); final ReceiverDescriptor receiverTypeRef = f.getReceiverParameter();
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();
@@ -351,32 +464,36 @@ public class JetTypeMapper {
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);
Type type = mapType(jetType); Type type = mapType(jetType, signatureVisitor);
if(type.getInternalName().equals("java/lang/Object")) { if(type.getInternalName().equals("java/lang/Object")) {
jetType = containingDeclaration.getDefaultType(); jetType = containingDeclaration.getDefaultType();
type = mapType(jetType); type = mapType(jetType, signatureVisitor);
} }
valueParameterTypes.add(type); valueParameterTypes.add(type);
parameterTypes.add(type); parameterTypes.add(type);
} }
if (receiverType != null) { if (receiverType != null) {
parameterTypes.add(mapType(receiverType)); parameterTypes.add(mapType(receiverType, signatureVisitor != null ? signatureVisitor.visitParameterType() : null));
} }
for (TypeParameterDescriptor parameterDescriptor : f.getTypeParameters()) { for (TypeParameterDescriptor parameterDescriptor : f.getTypeParameters()) {
if(parameterDescriptor.isReified()) { if(parameterDescriptor.isReified()) {
parameterTypes.add(TYPE_TYPEINFO); parameterTypes.add(TYPE_TYPEINFO);
if (signatureVisitor != null) {
visitAsmType(signatureVisitor.visitParameterType(), TYPE_TYPEINFO);
}
} }
} }
for (ValueParameterDescriptor parameter : parameters) { for (ValueParameterDescriptor parameter : parameters) {
Type type = mapType(parameter.getOutType()); Type type = mapType(parameter.getOutType(), signatureVisitor != null ? signatureVisitor.visitParameterType() : null);
valueParameterTypes.add(type); valueParameterTypes.add(type);
parameterTypes.add(type); parameterTypes.add(type);
} }
Type returnType = f instanceof ConstructorDescriptor ? Type.VOID_TYPE : mapReturnType(f.getReturnType()); Type returnType = f instanceof ConstructorDescriptor ? Type.VOID_TYPE : mapReturnType(f.getReturnType(), signatureVisitor != null ? signatureVisitor.visitReturnType() : null);
return new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()])); Method method = new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
return new JvmMethodSignature(method, signatureWriter != null ? signatureWriter.toString() : null);
} }
public Method mapSignature(String name, FunctionDescriptor f) { public JvmMethodSignature mapSignature(String name, FunctionDescriptor f) {
final ReceiverDescriptor receiver = f.getReceiverParameter(); final ReceiverDescriptor receiver = f.getReceiverParameter();
final List<ValueParameterDescriptor> parameters = f.getValueParameters(); final List<ValueParameterDescriptor> parameters = f.getValueParameters();
List<Type> parameterTypes = new ArrayList<Type>(); List<Type> parameterTypes = new ArrayList<Type>();
@@ -387,40 +504,12 @@ public class JetTypeMapper {
parameterTypes.add(mapType(parameter.getOutType())); parameterTypes.add(mapType(parameter.getOutType()));
} }
Type returnType = mapReturnType(f.getReturnType()); Type returnType = mapReturnType(f.getReturnType());
return new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()])); // TODO: proper generic signature
return new JvmMethodSignature(new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()])), null);
} }
public String genericSignature(FunctionDescriptor f) {
StringBuffer answer = new StringBuffer();
final List<TypeParameterDescriptor> typeParameters = f.getTypeParameters();
if (!typeParameters.isEmpty()) {
answer.append('<');
for (TypeParameterDescriptor p : typeParameters) {
appendTypeParameterSignature(answer, p);
}
answer.append('>');
}
answer.append('('); public JvmMethodSignature mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
for (ValueParameterDescriptor p : f.getValueParameters()) {
appendType(answer, p.getOutType());
}
answer.append(')');
appendType(answer, f.getReturnType());
return answer.toString();
}
private void appendType(StringBuffer answer, JetType type) {
answer.append(mapType(type).getDescriptor()); // TODO: type parameter references!
}
private static void appendTypeParameterSignature(StringBuffer answer, TypeParameterDescriptor p) {
answer.append(p.getName()); // TODO: BOUND!
}
public Method mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
Type returnType = mapType(descriptor.getOutType()); Type returnType = mapType(descriptor.getOutType());
String name = PropertyCodegen.getterName(descriptor.getName()); String name = PropertyCodegen.getterName(descriptor.getName());
ArrayList<Type> params = new ArrayList<Type>(); ArrayList<Type> params = new ArrayList<Type>();
@@ -440,10 +529,12 @@ public class JetTypeMapper {
} }
} }
return new Method(name, returnType, params.toArray(new Type[params.size()])); // TODO: proper generic signature
return new JvmMethodSignature(new Method(name, returnType, params.toArray(new Type[params.size()])), null);
} }
public Method mapSetterSignature(PropertyDescriptor descriptor, OwnerKind kind) { @Nullable
public JvmMethodSignature mapSetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
JetType inType = descriptor.getInType(); JetType inType = descriptor.getInType();
if(inType == null) if(inType == null)
return null; return null;
@@ -468,10 +559,11 @@ public class JetTypeMapper {
params.add(mapType(inType)); params.add(mapType(inType));
return new Method(name, Type.VOID_TYPE, params.toArray(new Type[params.size()])); // TODO: proper generic signature
return new JvmMethodSignature(new Method(name, Type.VOID_TYPE, params.toArray(new Type[params.size()])), null);
} }
private Method mapConstructorSignature(ConstructorDescriptor descriptor, List<Type> valueParameterTypes) { private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor, List<Type> valueParameterTypes) {
List<ValueParameterDescriptor> parameters = descriptor.getOriginal().getValueParameters(); List<ValueParameterDescriptor> parameters = descriptor.getOriginal().getValueParameters();
List<Type> parameterTypes = new ArrayList<Type>(); List<Type> parameterTypes = new ArrayList<Type>();
ClassDescriptor classDescriptor = descriptor.getContainingDeclaration(); ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
@@ -491,12 +583,13 @@ public class JetTypeMapper {
valueParameterTypes.add(type); valueParameterTypes.add(type);
} }
return new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); Method method = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
return new JvmMethodSignature(method, null); // TODO: generics signature
} }
public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind) { public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind) {
List<Type> valueParameterTypes = new ArrayList<Type>(); List<Type> valueParameterTypes = new ArrayList<Type>();
final Method method = mapConstructorSignature(descriptor, valueParameterTypes); final JvmMethodSignature method = mapConstructorSignature(descriptor, valueParameterTypes);
String owner = mapType(descriptor.getContainingDeclaration().getDefaultType(), kind).getInternalName(); String owner = mapType(descriptor.getContainingDeclaration().getDefaultType(), kind).getInternalName();
return new CallableMethod(owner, method, INVOKESPECIAL, valueParameterTypes); return new CallableMethod(owner, method, INVOKESPECIAL, valueParameterTypes);
} }
@@ -0,0 +1,28 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.objectweb.asm.commons.Method;
/**
* @author Stepan Koltsov
*/
public class JvmMethodSignature {
private final Method asmMethod;
/** Null when we don't care about type parameters */
private final String genericsSignature;
public JvmMethodSignature(@NotNull Method asmMethod, @Nullable String genericsSignature) {
this.asmMethod = asmMethod;
this.genericsSignature = genericsSignature;
}
public Method getAsmMethod() {
return asmMethod;
}
public String getGenericsSignature() {
return genericsSignature;
}
}
@@ -133,7 +133,7 @@ public class PropertyCodegen {
if(isTrait && !(kind instanceof OwnerKind.DelegateKind)) if(isTrait && !(kind instanceof OwnerKind.DelegateKind))
flags |= Opcodes.ACC_ABSTRACT; flags |= Opcodes.ACC_ABSTRACT;
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind).getDescriptor(); final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind).getAsmMethod().getDescriptor();
String getterName = getterName(propertyDescriptor.getName()); String getterName = getterName(propertyDescriptor.getName());
MethodVisitor mv = v.newMethod(origin, flags, getterName, signature, null, null); MethodVisitor mv = v.newMethod(origin, flags, getterName, signature, null, null);
if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) { if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
@@ -179,7 +179,7 @@ public class PropertyCodegen {
if(isTrait && !(kind instanceof OwnerKind.DelegateKind)) if(isTrait && !(kind instanceof OwnerKind.DelegateKind))
flags |= Opcodes.ACC_ABSTRACT; flags |= Opcodes.ACC_ABSTRACT;
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind).getDescriptor(); final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind).getAsmMethod().getDescriptor();
MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), signature, null, null); MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), signature, null, null);
if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) { if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
mv.visitCode(); mv.visitCode();
@@ -29,6 +29,6 @@ public class PsiMethodCall implements IntrinsicMethod {
List<JetExpression> arguments, StackValue receiver) { List<JetExpression> arguments, StackValue receiver) {
final CallableMethod callableMethod = codegen.getTypeMapper().mapToCallableMethod(myMethod, false, OwnerKind.IMPLEMENTATION); final CallableMethod callableMethod = codegen.getTypeMapper().mapToCallableMethod(myMethod, false, OwnerKind.IMPLEMENTATION);
codegen.invokeMethodWithArguments(callableMethod, (JetCallExpression) element, receiver); codegen.invokeMethodWithArguments(callableMethod, (JetCallExpression) element, receiver);
return StackValue.onStack(callableMethod.getSignature().getReturnType()); return StackValue.onStack(callableMethod.getSignature().getAsmMethod().getReturnType());
} }
} }
@@ -14,6 +14,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.StdlibNames;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.plugin.JetFileType; import org.jetbrains.jet.plugin.JetFileType;
@@ -267,7 +268,7 @@ public class JavaDescriptorResolver {
return javaFacade.findClass(qualifiedName, javaSearchScope); return javaFacade.findClass(qualifiedName, javaSearchScope);
} }
private PsiPackage findPackage(String qualifiedName) { /*package*/ PsiPackage findPackage(String qualifiedName) {
return javaFacade.findPackage(qualifiedName); return javaFacade.findPackage(qualifiedName);
} }
@@ -354,13 +355,13 @@ public class JavaDescriptorResolver {
PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes(); PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
attributes.toString(); attributes.toString();
if (annotation.getQualifiedName().equals("jet.typeinfo.JetParameter")) { if (annotation.getQualifiedName().equals(StdlibNames.JET_PARAMETER_CLASS)) {
PsiLiteralExpression nameExpression = (PsiLiteralExpression) annotation.findAttributeValue("name"); PsiLiteralExpression nameExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_PARAMETER_NAME_FIELD);
if (nameExpression != null) { if (nameExpression != null) {
name = (String) nameExpression.getValue(); name = (String) nameExpression.getValue();
} }
PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue("nullable"); PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_PARAMETER_NULLABLE_FIELD);
if (nullableExpression != null) { if (nullableExpression != null) {
nullable = (Boolean) nullableExpression.getValue(); nullable = (Boolean) nullableExpression.getValue();
} else { } else {
@@ -479,7 +480,7 @@ public class JavaDescriptorResolver {
DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor), DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor),
typeParameters, typeParameters,
semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptorImpl, parameters), semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptorImpl, parameters),
semanticServices.getTypeTransformer().transformToType(returnType), semanticServices.getDescriptorResolver().makeReturnType(returnType, method),
Modality.convertFromFlags(method.hasModifierProperty(PsiModifier.ABSTRACT), !method.hasModifierProperty(PsiModifier.FINAL)), Modality.convertFromFlags(method.hasModifierProperty(PsiModifier.ABSTRACT), !method.hasModifierProperty(PsiModifier.FINAL)),
resolveVisibilityFromPsiModifiers(method) resolveVisibilityFromPsiModifiers(method)
); );
@@ -491,6 +492,30 @@ public class JavaDescriptorResolver {
return substitutedFunctionDescriptor; return substitutedFunctionDescriptor;
} }
private JetType makeReturnType(PsiType returnType, PsiMethod method) {
boolean changeNullable = false;
boolean nullable = true;
for (PsiAnnotation annotation : method.getModifierList().getAnnotations()) {
if (annotation.getQualifiedName().equals(StdlibNames.JET_METHOD_CLASS)) {
PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_METHOD_NULLABLE_RETURN_TYPE_FIELD);
if (nullableExpression != null) {
nullable = (Boolean) nullableExpression.getValue();
} else {
// default value of parameter
nullable = false;
changeNullable = true;
}
}
}
JetType transformedType = semanticServices.getTypeTransformer().transformToType(returnType);
if (changeNullable) {
return TypeUtils.makeNullableAsSpecified(transformedType, nullable);
} else {
return transformedType;
}
}
private static Visibility resolveVisibilityFromPsiModifiers(PsiModifierListOwner modifierListOwner) { private static Visibility resolveVisibilityFromPsiModifiers(PsiModifierListOwner modifierListOwner) {
//TODO report error //TODO report error
return modifierListOwner.hasModifierProperty(PsiModifier.PUBLIC) ? Visibility.PUBLIC : return modifierListOwner.hasModifierProperty(PsiModifier.PUBLIC) ? Visibility.PUBLIC :
@@ -1,10 +1,17 @@
package org.jetbrains.jet.lang.resolve.java; package org.jetbrains.jet.lang.resolve.java;
import com.google.common.collect.Sets;
import com.intellij.psi.PsiClass; import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiPackage;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
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.JetScopeImpl; import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
@@ -14,11 +21,13 @@ import java.util.Set;
public class JavaPackageScope extends JetScopeImpl { public class JavaPackageScope extends JetScopeImpl {
private final JavaSemanticServices semanticServices; private final JavaSemanticServices semanticServices;
private final DeclarationDescriptor containingDescriptor; private final DeclarationDescriptor containingDescriptor;
private final String packagePrefix; private final String packageFQN;
private Collection<DeclarationDescriptor> allDescriptors;
public JavaPackageScope(@NotNull String packageFQN, DeclarationDescriptor containingDescriptor, JavaSemanticServices semanticServices) { public JavaPackageScope(@NotNull String packageFQN, DeclarationDescriptor containingDescriptor, JavaSemanticServices semanticServices) {
this.semanticServices = semanticServices; this.semanticServices = semanticServices;
this.packagePrefix = packageFQN.isEmpty() ? "" : packageFQN + "."; this.packageFQN = packageFQN;
this.containingDescriptor = containingDescriptor; this.containingDescriptor = containingDescriptor;
} }
@@ -36,7 +45,7 @@ public class JavaPackageScope extends JetScopeImpl {
@Override @Override
public Set<FunctionDescriptor> getFunctions(@NotNull String name) { public Set<FunctionDescriptor> getFunctions(@NotNull String name) {
// TODO: what is GlobalSearchScope // TODO: what is GlobalSearchScope
PsiClass psiClass = semanticServices.getDescriptorResolver().javaFacade.findClass(packagePrefix + "namespace"); PsiClass psiClass = semanticServices.getDescriptorResolver().javaFacade.findClass(getQualifiedName("namespace"));
if (psiClass == null) { if (psiClass == null) {
return Collections.emptySet(); return Collections.emptySet();
} }
@@ -54,7 +63,35 @@ public class JavaPackageScope extends JetScopeImpl {
return containingDescriptor; return containingDescriptor;
} }
private String getQualifiedName(String name) { @NotNull
return packagePrefix + name; @Override
public Collection<DeclarationDescriptor> getAllDescriptors() {
if (allDescriptors == null) {
allDescriptors = Sets.newHashSet();
final PsiPackage javaPackage = semanticServices.getDescriptorResolver().findPackage(packageFQN);
if (javaPackage != null) {
final JavaDescriptorResolver descriptorResolver = semanticServices.getDescriptorResolver();
for (PsiPackage psiSubPackage : javaPackage.getSubPackages()) {
allDescriptors.add(descriptorResolver.resolveNamespace(psiSubPackage.getQualifiedName()));
}
for (PsiClass psiClass : javaPackage.getClasses()) {
if (psiClass.hasModifierProperty(PsiModifier.PUBLIC)) {
allDescriptors.add(descriptorResolver.resolveClass(psiClass));
}
}
}
}
return allDescriptors;
} }
private String getQualifiedName(String name) {
return (packageFQN.isEmpty() ? "" : packageFQN + ".") + name;
}
} }
@@ -0,0 +1,108 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
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.types.JetType;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import java.util.List;
import static org.jetbrains.jet.lang.diagnostics.Errors.UNRESOLVED_REFERENCE;
import static org.jetbrains.jet.lang.diagnostics.Errors.UNSUPPORTED;
/**
* @author abreslav
*/
public class ImportsResolver {
private final TopDownAnalysisContext context;
public ImportsResolver(@NotNull TopDownAnalysisContext context) {
this.context = context;
}
public void processTypeImports() {
for (JetNamespace jetNamespace : context.getNamespaceDescriptors().keySet()) {
processImports(jetNamespace, context.getNamespaceScopes().get(jetNamespace), context.getDeclaringScopes().get(jetNamespace));
}
}
private void processImports(@NotNull JetNamespace namespace, @NotNull WritableScope namespaceScope, @NotNull JetScope outerScope) {
context.getConfiguration().addDefaultImports(context.getTrace(), namespaceScope);
List<JetImportDirective> importDirectives = namespace.getImportDirectives();
for (JetImportDirective importDirective : importDirectives) {
if (importDirective.isAbsoluteInRootNamespace()) {
context.getTrace().report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO
continue;
}
if (importDirective.isAllUnder()) {
JetExpression importedReference = importDirective.getImportedReference();
if (importedReference != null) {
ExpressionTypingServices typeInferrerServices = context.getSemanticServices().getTypeInferrerServices(context.getTrace());
JetType type = typeInferrerServices.getTypeWithNamespaces(namespaceScope, importedReference);
if (type != null) {
namespaceScope.importScope(type.getMemberScope());
}
}
}
else {
ClassifierDescriptor classifierDescriptor = null;
NamespaceDescriptor namespaceDescriptor = null;
JetSimpleNameExpression referenceExpression = null;
JetExpression importedReference = importDirective.getImportedReference();
if (importedReference instanceof JetDotQualifiedExpression) {
JetDotQualifiedExpression reference = (JetDotQualifiedExpression) importedReference;
JetType type = context.getSemanticServices().getTypeInferrerServices(context.getTrace()).getTypeWithNamespaces(namespaceScope, reference.getReceiverExpression());
JetExpression selectorExpression = reference.getSelectorExpression();
if (selectorExpression != null) {
referenceExpression = (JetSimpleNameExpression) selectorExpression;
String referencedName = referenceExpression.getReferencedName();
if (type != null && referencedName != null) {
classifierDescriptor = type.getMemberScope().getClassifier(referencedName);
namespaceDescriptor = type.getMemberScope().getNamespace(referencedName);
}
}
}
else {
assert importedReference instanceof JetSimpleNameExpression;
referenceExpression = (JetSimpleNameExpression) importedReference;
String referencedName = referenceExpression.getReferencedName();
if (referencedName != null) {
classifierDescriptor = outerScope.getClassifier(referencedName);
namespaceDescriptor = outerScope.getNamespace(referencedName);
if (classifierDescriptor == null && namespaceDescriptor == null) {
context.getTrace().report(UNRESOLVED_REFERENCE.on(referenceExpression));
}
}
}
String aliasName = importDirective.getAliasName();
if (aliasName == null) {
aliasName = referenceExpression != null ? referenceExpression.getReferencedName() : null;
}
if (classifierDescriptor != null) {
context.getTrace().record(BindingContext.REFERENCE_TARGET, referenceExpression, classifierDescriptor);
if (aliasName != null) {
namespaceScope.importClassifierAlias(aliasName, classifierDescriptor);
}
}
if (namespaceDescriptor != null) {
if (classifierDescriptor == null) {
context.getTrace().record(BindingContext.REFERENCE_TARGET, referenceExpression, namespaceDescriptor);
}
if (aliasName != null) {
namespaceScope.importNamespaceAlias(aliasName, namespaceDescriptor);
}
}
}
}
}
}
@@ -0,0 +1,32 @@
package org.jetbrains.jet.lang.resolve;
import org.objectweb.asm.Type;
/**
* @author Stepan Koltsov
*/
public class StdlibNames {
public static final Type JET_PARAMETER_TYPE = Type.getObjectType("jet/typeinfo/JetParameter");
public static final String JET_PARAMETER_CLASS = "jet.typeinfo.JetParameter";
public static final String JET_PARAMETER_DESCRIPTOR = "Ljet/typeinfo/JetParameter;";
public static final String JET_PARAMETER_NAME_FIELD = "name";
public static final String JET_PARAMETER_HAS_DEFAULT_FIELD = "hasDefault";
public static final String JET_PARAMETER_NULLABLE_FIELD = "nullable";
public static final Type JET_TYPE_PARAMETER_TYPE = Type.getObjectType("jet/typeinfo/JetTypeParameter");
public static final String JET_TYPE_PARAMETER_CLASS = "jet.typeinfo.JetTypeParameter";
public static final String JET_TYPE_PARAMETER_DESCRIPTOR = "Ljet/typeinfo/JetTypeParameter;";
public static final String JET_TYPE_PARAMETER_NAME_FIELD = "name";
public static final Type JET_METHOD_TYPE = Type.getObjectType("jet/typeinfo/JetMethod");
public static final String JET_METHOD_CLASS = "jet.typeinfo.JetMethod";
public static final String JET_METHOD_DESCRIPTOR = "Ljet/typeinfo/JetMethod;";
public static final String JET_METHOD_NULLABLE_RETURN_TYPE_FIELD = "nullableReturnType";
}
@@ -15,7 +15,10 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.resolve.scopes.WriteThroughScope; import org.jetbrains.jet.lang.resolve.scopes.WriteThroughScope;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeConstructor;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
@@ -30,17 +33,19 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.*;
*/ */
public class TypeHierarchyResolver { public class TypeHierarchyResolver {
private final TopDownAnalysisContext context; private final TopDownAnalysisContext context;
private final ImportsResolver importsResolver;
private LinkedList<MutableClassDescriptor> topologicalOrder; private LinkedList<MutableClassDescriptor> topologicalOrder;
public TypeHierarchyResolver(TopDownAnalysisContext context) { public TypeHierarchyResolver(TopDownAnalysisContext context) {
this.context = context; this.context = context;
this.importsResolver = new ImportsResolver(context);
} }
public void process(@NotNull JetScope outerScope, @NotNull NamespaceLike owner, @NotNull Collection<? extends JetDeclaration> declarations) { public void process(@NotNull JetScope outerScope, @NotNull NamespaceLike owner, @NotNull Collection<? extends JetDeclaration> declarations) {
collectNamespacesAndClassifiers(outerScope, outerScope, owner, declarations); // namespaceScopes, classes collectNamespacesAndClassifiers(outerScope, outerScope, owner, declarations); // namespaceScopes, classes
processTypeImports(); importsResolver.processTypeImports();
createTypeConstructors(); // create type constructors for classes and generic parameters, supertypes are not filled in createTypeConstructors(); // create type constructors for classes and generic parameters, supertypes are not filled in
resolveTypesInClassHeaders(); // Generic bounds and types in supertype lists (no expressions or constructor resolution) resolveTypesInClassHeaders(); // Generic bounds and types in supertype lists (no expressions or constructor resolution)
@@ -75,7 +80,6 @@ public class TypeHierarchyResolver {
WriteThroughScope namespaceScope = new WriteThroughScope(outerScope, namespaceDescriptor.getMemberScope(), new TraceBasedRedeclarationHandler(context.getTrace())); WriteThroughScope namespaceScope = new WriteThroughScope(outerScope, namespaceDescriptor.getMemberScope(), new TraceBasedRedeclarationHandler(context.getTrace()));
namespaceScope.changeLockLevel(WritableScope.LockLevel.BOTH); namespaceScope.changeLockLevel(WritableScope.LockLevel.BOTH);
context.getConfiguration().addDefaultImports(context.getTrace(), namespaceScope);
context.getNamespaceScopes().put(namespace, namespaceScope); context.getNamespaceScopes().put(namespace, namespaceScope);
context.getDeclaringScopes().put(namespace, outerScope); context.getDeclaringScopes().put(namespace, outerScope);
@@ -233,82 +237,6 @@ public class TypeHierarchyResolver {
return ClassKind.CLASS; return ClassKind.CLASS;
} }
private void processTypeImports() {
for (JetNamespace jetNamespace : context.getNamespaceDescriptors().keySet()) {
processImports(jetNamespace, context.getNamespaceScopes().get(jetNamespace), context.getDeclaringScopes().get(jetNamespace));
}
}
private void processImports(@NotNull JetNamespace namespace, @NotNull WritableScope namespaceScope, @NotNull JetScope outerScope) {
List<JetImportDirective> importDirectives = namespace.getImportDirectives();
for (JetImportDirective importDirective : importDirectives) {
if (importDirective.isAbsoluteInRootNamespace()) {
context.getTrace().report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO
continue;
}
if (importDirective.isAllUnder()) {
JetExpression importedReference = importDirective.getImportedReference();
if (importedReference != null) {
ExpressionTypingServices typeInferrerServices = context.getSemanticServices().getTypeInferrerServices(context.getTrace());
JetType type = typeInferrerServices.getTypeWithNamespaces(namespaceScope, importedReference);
if (type != null) {
namespaceScope.importScope(type.getMemberScope());
}
}
}
else {
ClassifierDescriptor classifierDescriptor = null;
NamespaceDescriptor namespaceDescriptor = null;
JetSimpleNameExpression referenceExpression = null;
JetExpression importedReference = importDirective.getImportedReference();
if (importedReference instanceof JetDotQualifiedExpression) {
JetDotQualifiedExpression reference = (JetDotQualifiedExpression) importedReference;
JetType type = context.getSemanticServices().getTypeInferrerServices(context.getTrace()).getTypeWithNamespaces(namespaceScope, reference.getReceiverExpression());
JetExpression selectorExpression = reference.getSelectorExpression();
if (selectorExpression != null) {
referenceExpression = (JetSimpleNameExpression) selectorExpression;
String referencedName = referenceExpression.getReferencedName();
if (type != null && referencedName != null) {
classifierDescriptor = type.getMemberScope().getClassifier(referencedName);
namespaceDescriptor = type.getMemberScope().getNamespace(referencedName);
}
}
}
else {
assert importedReference instanceof JetSimpleNameExpression;
referenceExpression = (JetSimpleNameExpression) importedReference;
String referencedName = referenceExpression.getReferencedName();
if (referencedName != null) {
classifierDescriptor = outerScope.getClassifier(referencedName);
namespaceDescriptor = outerScope.getNamespace(referencedName);
}
}
String aliasName = importDirective.getAliasName();
if (aliasName == null) {
aliasName = referenceExpression != null ? referenceExpression.getReferencedName() : null;
}
if (classifierDescriptor != null) {
context.getTrace().record(BindingContext.REFERENCE_TARGET, referenceExpression, classifierDescriptor);
if (aliasName != null) {
namespaceScope.importClassifierAlias(aliasName, classifierDescriptor);
}
}
if (namespaceDescriptor != null) {
if (classifierDescriptor == null) {
context.getTrace().record(BindingContext.REFERENCE_TARGET, referenceExpression, namespaceDescriptor);
}
if (aliasName != null) {
namespaceScope.importNamespaceAlias(aliasName, namespaceDescriptor);
}
}
}
}
}
private void createTypeConstructors() { private void createTypeConstructors() {
for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) { for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
JetClass jetClass = entry.getKey(); JetClass jetClass = entry.getKey();
@@ -13,16 +13,13 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl; import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.inference.*;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions; import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
import org.jetbrains.jet.lang.resolve.calls.inference.SolutionStatus;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import java.util.*; import java.util.*;
@@ -241,6 +238,12 @@ public class CallResolver {
@NotNull JetType expectedType, @NotNull JetType expectedType,
@NotNull final List<ResolutionTask<D>> prioritizedTasks, // high to low priority @NotNull final List<ResolutionTask<D>> prioritizedTasks, // high to low priority
@NotNull final JetReferenceExpression reference) { @NotNull final JetReferenceExpression reference) {
ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create();
trace.record(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, call.getCallElement(), debugInfo);
debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks);
TracingStrategy tracing = new TracingStrategy() { TracingStrategy tracing = new TracingStrategy() {
@Override @Override
public <D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCallImpl<D> resolvedCall) { public <D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCallImpl<D> resolvedCall) {
@@ -371,6 +374,9 @@ public class CallResolver {
OverloadResolutionResults<D> results = performResolution(temporaryTrace, scope, expectedType, task, tracing); OverloadResolutionResults<D> results = performResolution(temporaryTrace, scope, expectedType, task, tracing);
if (results.isSuccess()) { if (results.isSuccess()) {
temporaryTrace.commit(); temporaryTrace.commit();
debugInfo.set(ResolutionDebugInfo.RESULT, results.getResult());
return results.getResult(); return results.getResult();
} }
if (traceForFirstNonemptyCandidateSet == null && !task.getCandidates().isEmpty()) { if (traceForFirstNonemptyCandidateSet == null && !task.getCandidates().isEmpty()) {
@@ -381,6 +387,9 @@ public class CallResolver {
if (traceForFirstNonemptyCandidateSet != null) { if (traceForFirstNonemptyCandidateSet != null) {
traceForFirstNonemptyCandidateSet.commit(); traceForFirstNonemptyCandidateSet.commit();
if (resultsForFirstNonemptyCandidateSet.singleDescriptor()) { if (resultsForFirstNonemptyCandidateSet.singleDescriptor()) {
debugInfo.set(ResolutionDebugInfo.RESULT, resultsForFirstNonemptyCandidateSet.getResult());
return resultsForFirstNonemptyCandidateSet.getResult(); return resultsForFirstNonemptyCandidateSet.getResult();
} }
} }
@@ -420,7 +429,10 @@ public class CallResolver {
if (!candidate.getTypeParameters().isEmpty()) { if (!candidate.getTypeParameters().isEmpty()) {
// Type argument inference // Type argument inference
ConstraintSystem constraintSystem = new ConstraintSystemImpl(); ResolutionDebugInfo.Data debugInfo = trace.get(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, task.getCall().getCallElement());
ConstraintSystem constraintSystem = new ConstraintSystemImpl(new DebugConstraintResolutionListener(debugInfo));
for (TypeParameterDescriptor typeParameterDescriptor : candidate.getTypeParameters()) { for (TypeParameterDescriptor typeParameterDescriptor : candidate.getTypeParameters()) {
constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO
} }
@@ -0,0 +1,115 @@
package org.jetbrains.jet.lang.resolve.calls;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.util.slicedmap.*;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* @author abreslav
*/
public class ResolutionDebugInfo {
public static final WritableSlice<One, List<? extends ResolutionTask<? extends CallableDescriptor>>> TASKS = Slices.createSimpleSlice();
public static final WritableSlice<One, ResolvedCall<? extends CallableDescriptor>> RESULT = Slices.createSimpleSlice();
public static final WritableSlice<One, StringBuilder> ERRORS = Slices.createSimpleSlice();
public static final WritableSlice<One, StringBuilder> LOG = Slices.createSimpleSlice();
public static final WritableSlice<One, Map<TypeParameterDescriptor, ConstraintSystemImpl.TypeValue>> BOUNDS_FOR_UNKNOWNS = Slices.createSimpleSlice();
public static final WritableSlice<One, Map<JetType, ConstraintSystemImpl.TypeValue>> BOUNDS_FOR_KNOWNS = Slices.createSimpleSlice();
public static final WritableSlice<One, ConstraintSystemSolution> SOLUTION = Slices.createSimpleSlice();
public static final WritableSlice<One, Collection<TypeParameterDescriptor>> UNKNOWNS = Slices.createSimpleSlice();
static {
BasicWritableSlice.initSliceDebugNames(ResolutionDebugInfo.class);
}
public static boolean RESOLUTION_DEBUG_INFO_ENABLED = false;
public static boolean isResolutionDebugEnabled() {
Application application = ApplicationManager.getApplication();
return (RESOLUTION_DEBUG_INFO_ENABLED || application.isInternal()) && !application.isUnitTestMode();
}
public static final Data NO_DEBUG_INFO = new AbstractData() {
@Override
public String toString() {
return "NO_DEBUG_INFO";
}
@Override
public <K, V> V getByKey(ReadOnlySlice<K, V> slice, K key) {
return SlicedMap.DO_NOTHING.get(slice, key);
}
@Override
public <K, V> void putByKey(WritableSlice<K, V> slice, K key, V value) {
}
};
public static final WritableSlice<PsiElement, Data> RESOLUTION_DEBUG_INFO = new BasicWritableSlice<PsiElement, Data>(Slices.ONLY_REWRITE_TO_EQUAL) {
@Override
public boolean check(PsiElement key, Data value) {
return isResolutionDebugEnabled();
}
@Override
public Data computeValue(SlicedMap map, PsiElement key, Data value, boolean valueNotFound) {
if (valueNotFound) return NO_DEBUG_INFO;
return super.computeValue(map, key, value, valueNotFound);
}
};
public static Data create() {
return isResolutionDebugEnabled() ? new DataImpl() : NO_DEBUG_INFO;
}
public enum One { KEY }
public interface Data {
<K, V> V getByKey(ReadOnlySlice<K, V> slice, K key);
<K, V> void putByKey(WritableSlice<K, V> slice, K key, V value);
<V> void set(WritableSlice<One, ? super V> slice, V value);
<V> V get(ReadOnlySlice<One, V> slice);
}
private static abstract class AbstractData implements Data {
@Override
public <V> void set(WritableSlice<One, ? super V> slice, V value) {
putByKey(slice, One.KEY, value);
}
@Override
public <V> V get(ReadOnlySlice<One, V> slice) {
return getByKey(slice, One.KEY);
}
}
private static class DataImpl extends AbstractData {
private final MutableSlicedMap map = SlicedMapImpl.create();
@Override
public <K, V> V getByKey(ReadOnlySlice<K, V> slice, K key) {
return map.get(slice, key);
}
@Override
public <K, V> void putByKey(WritableSlice<K, V> slice, K key, V value) {
map.put(slice, key, value);
}
}
public static void println(Object message) {
if (isResolutionDebugEnabled()) {
System.out.println(message);
}
}
}
@@ -0,0 +1,19 @@
package org.jetbrains.jet.lang.resolve.calls.inference;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Set;
/**
* @author abreslav
*/
public interface ConstraintResolutionListener {
void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, ConstraintSystemImpl.TypeValue typeValue);
void constraintsForKnownType(JetType type, ConstraintSystemImpl.TypeValue typeValue);
void done(ConstraintSystemSolution solution, Set<TypeParameterDescriptor> typeParameterDescriptors);
void log(Object message);
void error(Object message);
}
@@ -44,7 +44,6 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}); });
} }
private static class LoopInTypeVariableConstraintsException extends RuntimeException { private static class LoopInTypeVariableConstraintsException extends RuntimeException {
public LoopInTypeVariableConstraintsException() {} public LoopInTypeVariableConstraintsException() {}
} }
@@ -80,6 +79,8 @@ public class ConstraintSystemImpl implements ConstraintSystem {
public abstract boolean equate(TypeValue other); public abstract boolean equate(TypeValue other);
} }
//==========================================================================================================================================================
private class UnknownType extends TypeValue { private class UnknownType extends TypeValue {
private final TypeParameterDescriptor typeParameterDescriptor; private final TypeParameterDescriptor typeParameterDescriptor;
@@ -142,7 +143,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
} }
} }
println("minimal solution from lowerbounds for " + this + " is " + commonSupertype); listener.log("minimal solution from lowerbounds for " + this + " is " + commonSupertype);
value = new KnownType(commonSupertype); value = new KnownType(commonSupertype);
} }
else { else {
@@ -238,16 +239,18 @@ public class ConstraintSystemImpl implements ConstraintSystem {
private static final class TypeConstraintBuilderAdapter implements TypingConstraints { private static final class TypeConstraintBuilderAdapter implements TypingConstraints {
private final TypingConstraints delegate; private final TypingConstraints delegate;
private final ConstraintResolutionListener listener;
private TypeConstraintBuilderAdapter(TypingConstraints delegate) { private TypeConstraintBuilderAdapter(TypingConstraints delegate, ConstraintResolutionListener listener) {
this.delegate = delegate; this.delegate = delegate;
this.listener = listener;
} }
@Override @Override
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) { public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) {
boolean result = delegate.assertEqualTypes(a, b, typeCheckingProcedure); boolean result = delegate.assertEqualTypes(a, b, typeCheckingProcedure);
if (!result) { if (!result) {
println("-- Failed to equate " + a + " and " + b); listener.error("-- Failed to equate " + a + " and " + b);
} }
return result; return result;
} }
@@ -256,7 +259,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) { public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
boolean result = delegate.assertEqualTypeConstructors(a, b); boolean result = delegate.assertEqualTypeConstructors(a, b);
if (!result) { if (!result) {
println("-- Type constructors are not equal: " + a + " and " + b); listener.error("-- Type constructors are not equal: " + a + " and " + b);
} }
return result; return result;
} }
@@ -265,7 +268,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) { public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) {
boolean result = delegate.assertSubtype(subtype, supertype, typeCheckingProcedure); boolean result = delegate.assertSubtype(subtype, supertype, typeCheckingProcedure);
if (!result) { if (!result) {
println("-- " + subtype + " can't be a subtype of " + supertype); listener.error("-- " + subtype + " can't be a subtype of " + supertype);
} }
return result; return result;
} }
@@ -274,60 +277,67 @@ public class ConstraintSystemImpl implements ConstraintSystem {
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) { public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
boolean result = delegate.noCorrespondingSupertype(subtype, supertype); boolean result = delegate.noCorrespondingSupertype(subtype, supertype);
if (!result) { if (!result) {
println("-- " + subtype + " has no supertype corresponding to " + supertype); listener.error("-- " + subtype + " has no supertype corresponding to " + supertype);
} }
return result; return result;
} }
} }
private final TypeCheckingProcedure constraintExpander = new TypeCheckingProcedure(new TypeConstraintBuilderAdapter(new TypingConstraints() {
@Override
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) {
TypeValue aValue = getTypeValueFor(a);
TypeValue bValue = getTypeValueFor(b);
return aValue.equate(bValue); private final TypeCheckingProcedure constraintExpander;
} private final ConstraintResolutionListener listener;
@Override public ConstraintSystemImpl(ConstraintResolutionListener listener) {
public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) { this.listener = listener;
return a.equals(b) this.constraintExpander = createConstraintExpander();
|| unknownTypes.containsKey(a.getDeclarationDescriptor()) }
|| unknownTypes.containsKey(b.getDeclarationDescriptor());
}
@Override private TypeCheckingProcedure createConstraintExpander() {
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) { return new TypeCheckingProcedure(new TypeConstraintBuilderAdapter(new TypingConstraints() {
TypeValue subtypeValue = getTypeValueFor(subtype); @Override
TypeValue supertypeValue = getTypeValueFor(supertype); public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) {
TypeValue aValue = getTypeValueFor(a);
TypeValue bValue = getTypeValueFor(b);
if (someUnknown(subtypeValue, supertypeValue)) { return aValue.equate(bValue);
addSubtypingConstraintOnTypeValues(subtypeValue, supertypeValue);
} }
return true;
}
@Override @Override
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) { public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
// If some of the types is an unknown, the constraint must be generated, and we should carry on return a.equals(b)
// otherwise there can be no solution, and we should fail || unknownTypes.containsKey(a.getDeclarationDescriptor())
TypeValue subTypeValue = getTypeValueFor(subtype); || unknownTypes.containsKey(b.getDeclarationDescriptor());
TypeValue superTypeValue = getTypeValueFor(supertype);
boolean someUnknown = someUnknown(subTypeValue, superTypeValue);
if (someUnknown) {
addSubtypingConstraintOnTypeValues(subTypeValue, superTypeValue);
} }
return someUnknown;
}
private boolean someUnknown(TypeValue subtypeValue, TypeValue supertypeValue) { @Override
return subtypeValue instanceof UnknownType || supertypeValue instanceof UnknownType; public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) {
} TypeValue subtypeValue = getTypeValueFor(subtype);
TypeValue supertypeValue = getTypeValueFor(supertype);
})) if (someUnknown(subtypeValue, supertypeValue)) {
; addSubtypingConstraintOnTypeValues(subtypeValue, supertypeValue);
}
return true;
}
public ConstraintSystemImpl() {} @Override
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
// If some of the types is an unknown, the constraint must be generated, and we should carry on
// otherwise there can be no solution, and we should fail
TypeValue subTypeValue = getTypeValueFor(subtype);
TypeValue superTypeValue = getTypeValueFor(supertype);
boolean someUnknown = someUnknown(subTypeValue, superTypeValue);
if (someUnknown) {
addSubtypingConstraintOnTypeValues(subTypeValue, superTypeValue);
}
return someUnknown;
}
private boolean someUnknown(TypeValue subtypeValue, TypeValue supertypeValue) {
return subtypeValue instanceof UnknownType || supertypeValue instanceof UnknownType;
}
}, listener));
}
@NotNull @NotNull
private TypeValue getTypeValueFor(@NotNull JetType type) { private TypeValue getTypeValueFor(@NotNull JetType type) {
@@ -368,7 +378,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
} }
private void mergeUnknowns(@NotNull UnknownType a, @NotNull UnknownType b) { private void mergeUnknowns(@NotNull UnknownType a, @NotNull UnknownType b) {
System.err.println("!!!mergeUnknowns() is not implemented!!!"); listener.error("!!!mergeUnknowns() is not implemented!!!");
} }
@Override @Override
@@ -379,7 +389,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
} }
private void addSubtypingConstraintOnTypeValues(TypeValue typeValueForLower, TypeValue typeValueForUpper) { private void addSubtypingConstraintOnTypeValues(TypeValue typeValueForLower, TypeValue typeValueForUpper) {
println(typeValueForLower + " :< " + typeValueForUpper); listener.log("Constraint added: " + typeValueForLower + " :< " + typeValueForUpper);
if (typeValueForLower != typeValueForUpper) { if (typeValueForLower != typeValueForUpper) {
typeValueForLower.addUpperBound(typeValueForUpper); typeValueForLower.addUpperBound(typeValueForUpper);
typeValueForUpper.addLowerBound(typeValueForLower); typeValueForUpper.addLowerBound(typeValueForLower);
@@ -424,13 +434,11 @@ public class ConstraintSystemImpl implements ConstraintSystem {
} }
for (UnknownType unknownType : unknownTypes.values()) { for (UnknownType unknownType : unknownTypes.values()) {
println("Constraints for " + unknownType.getTypeParameterDescriptor()); listener.constraintsForUnknown(unknownType.getTypeParameterDescriptor(), unknownType);
printTypeValue(unknownType);
} }
for (KnownType knownType : knownTypes.values()) { for (KnownType knownType : knownTypes.values()) {
println("Constraints for " + knownType.getType()); listener.constraintsForKnownType(knownType.getType(), knownType);
printTypeValue(knownType);
} }
// Find inconsistencies // Find inconsistencies
@@ -447,22 +455,11 @@ public class ConstraintSystemImpl implements ConstraintSystem {
// we have set some of them from equality constraints with known types // we have set some of them from equality constraints with known types
// and thus the bounds may be violated if some of the constraints conflict // and thus the bounds may be violated if some of the constraints conflict
println("===================================="); listener.done(solution, unknownTypes.keySet());
println("");
println("");
return solution; return solution;
} }
private void printTypeValue(TypeValue typeValue) {
for (TypeValue bound : typeValue.getUpperBounds()) {
println(" :< " + bound);
}
for (TypeValue bound : typeValue.getLowerBounds()) {
println(" :> " + bound);
}
}
private void check(TypeValue typeValue, Solution solution) { private void check(TypeValue typeValue, Solution solution) {
try { try {
KnownType resultingValue = typeValue.getValue(); KnownType resultingValue = typeValue.getValue();
@@ -471,33 +468,20 @@ public class ConstraintSystemImpl implements ConstraintSystem {
JetType boundingType = solution.getSubstitutor().substitute(upperBound.getValue().getType(), Variance.INVARIANT); JetType boundingType = solution.getSubstitutor().substitute(upperBound.getValue().getType(), Variance.INVARIANT);
if (!typeChecker.isSubtypeOf(type, boundingType)) { // TODO if (!typeChecker.isSubtypeOf(type, boundingType)) { // TODO
solution.registerError("Constraint violation: " + type + " is not a subtype of " + boundingType); solution.registerError("Constraint violation: " + type + " is not a subtype of " + boundingType);
println("Constraint violation: " + type + " :< " + boundingType); listener.error("Constraint violation: " + type + " :< " + boundingType);
} }
} }
for (TypeValue lowerBound : typeValue.getLowerBounds()) { for (TypeValue lowerBound : typeValue.getLowerBounds()) {
JetType boundingType = solution.getSubstitutor().substitute(lowerBound.getValue().getType(), Variance.INVARIANT); JetType boundingType = solution.getSubstitutor().substitute(lowerBound.getValue().getType(), Variance.INVARIANT);
if (!typeChecker.isSubtypeOf(boundingType, type)) { if (!typeChecker.isSubtypeOf(boundingType, type)) {
solution.registerError("Constraint violation: " + boundingType + " is not a subtype of " + type); solution.registerError("Constraint violation: " + boundingType + " is not a subtype of " + type);
println("Constraint violation: " + boundingType + " :< " + type); listener.error("Constraint violation: " + boundingType + " :< " + type);
} }
} }
} }
catch (LoopInTypeVariableConstraintsException e) { catch (LoopInTypeVariableConstraintsException e) {
println("-------------------------------------------------------------------"); listener.error("Loop detected");
for (Map.Entry<TypeParameterDescriptor, UnknownType> entry : unknownTypes.entrySet()) {
println("Unknown: " + entry.getKey());
UnknownType unknownType = entry.getValue();
println("Lower bounds: ");
for (TypeValue lowerBound : unknownType.getLowerBounds()) {
println(" " + lowerBound);
}
println("Upper bounds: ");
for (TypeValue lowerBound : unknownType.getUpperBounds()) {
println(" " + lowerBound);
}
}
solution.registerError("[TODO] Loop in constraints"); solution.registerError("[TODO] Loop in constraints");
// e.printStackTrace();
} }
} }
@@ -544,9 +528,14 @@ public class ConstraintSystemImpl implements ConstraintSystem {
DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor(); DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor();
if (declarationDescriptor instanceof TypeParameterDescriptor) { if (declarationDescriptor instanceof TypeParameterDescriptor) {
TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor; TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor;
if (!unknownTypes.containsKey(descriptor)) return null; if (!unknownTypes.containsKey(descriptor)) return null;
println(descriptor + " |-> " + getValue(descriptor));
return new TypeProjection(getValue(descriptor)); TypeProjection typeProjection = new TypeProjection(getValue(descriptor));
listener.log(descriptor + " |-> " + typeProjection);
return typeProjection;
} }
return null; return null;
} }
@@ -588,7 +577,4 @@ public class ConstraintSystemImpl implements ConstraintSystem {
} }
private static void println(String message) {
// System.out.println(message);
}
} }
@@ -0,0 +1,75 @@
package org.jetbrains.jet.lang.resolve.calls.inference;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Map;
import java.util.Set;
import static org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo.*;
/**
* @author abreslav
*/
public class DebugConstraintResolutionListener implements ConstraintResolutionListener {
private final ResolutionDebugInfo.Data debugInfo;
public DebugConstraintResolutionListener(@NotNull ResolutionDebugInfo.Data debugInfo) {
this.debugInfo = debugInfo;
}
@Override
public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, ConstraintSystemImpl.TypeValue typeValue) {
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
Map<TypeParameterDescriptor, ConstraintSystemImpl.TypeValue> map = debugInfo.get(BOUNDS_FOR_UNKNOWNS);
if (map == null) {
map = Maps.newLinkedHashMap();
debugInfo.set(BOUNDS_FOR_UNKNOWNS, map);
}
map.put(typeParameterDescriptor, typeValue);
}
@Override
public void constraintsForKnownType(JetType type, ConstraintSystemImpl.TypeValue typeValue) {
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
Map<JetType,ConstraintSystemImpl.TypeValue> map = debugInfo.get(BOUNDS_FOR_KNOWNS);
if (map == null) {
map = Maps.newLinkedHashMap();
debugInfo.set(BOUNDS_FOR_KNOWNS, map);
}
map.put(type, typeValue);
}
@Override
public void done(ConstraintSystemSolution solution, Set<TypeParameterDescriptor> typeParameterDescriptors) {
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
debugInfo.set(SOLUTION, solution);
debugInfo.set(UNKNOWNS, typeParameterDescriptors);
}
@Override
public void log(Object message) {
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
StringBuilder stringBuilder = debugInfo.get(LOG);
if (stringBuilder == null) {
stringBuilder = new StringBuilder();
debugInfo.set(LOG, stringBuilder);
}
stringBuilder.append(message).append("\n");
}
@Override
public void error(Object message) {
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
StringBuilder stringBuilder = debugInfo.get(ERRORS);
if (stringBuilder == null) {
stringBuilder = new StringBuilder();
debugInfo.set(ERRORS, stringBuilder);
}
stringBuilder.append(message).append("\n");
}
}
@@ -0,0 +1,55 @@
package org.jetbrains.jet.lang.resolve.calls.inference;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Set;
/**
* @author abreslav
*/
public class PrintingConstraintResolutionListener implements ConstraintResolutionListener {
@Override
public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, ConstraintSystemImpl.TypeValue typeValue) {
println("Constraints for " + typeParameterDescriptor);
printTypeValue(typeValue);
}
@Override
public void constraintsForKnownType(JetType type, ConstraintSystemImpl.TypeValue typeValue) {
println("Constraints for " + type);
printTypeValue(typeValue);
}
@Override
public void done(ConstraintSystemSolution solution, Set<TypeParameterDescriptor> typeParameterDescriptors) {
println("==================================================");
println("");
println("");
}
@Override
public void log(Object message) {
println(message);
}
@Override
public void error(Object message) {
println(message);
}
private void printTypeValue(ConstraintSystemImpl.TypeValue typeValue) {
for (ConstraintSystemImpl.TypeValue bound : typeValue.getUpperBounds()) {
println(" :< " + bound);
}
for (ConstraintSystemImpl.TypeValue bound : typeValue.getLowerBounds()) {
println(" :> " + bound);
}
}
private static void println(Object message) {
ResolutionDebugInfo.println(message);
}
}
@@ -199,6 +199,10 @@ public class WriteThroughScope extends WritableScopeWithImports {
allDescriptors = Lists.newArrayList(); allDescriptors = Lists.newArrayList();
allDescriptors.addAll(writableWorker.getAllDescriptors()); allDescriptors.addAll(writableWorker.getAllDescriptors());
allDescriptors.addAll(getWorkerScope().getAllDescriptors()); allDescriptors.addAll(getWorkerScope().getAllDescriptors());
for (JetScope imported : getImports()) {
allDescriptors.addAll(imported.getAllDescriptors());
}
} }
return allDescriptors; return allDescriptors;
} }
@@ -1,12 +1,37 @@
package org.jetbrains.jet.util.slicedmap; package org.jetbrains.jet.util.slicedmap;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
/** /**
* @author abreslav * @author abreslav
*/ */
public interface SlicedMap extends Iterable<Map.Entry<SlicedMapKey<?, ?>, ?>> { public interface SlicedMap extends Iterable<Map.Entry<SlicedMapKey<?, ?>, ?>> {
SlicedMap DO_NOTHING = new SlicedMap() {
@Override
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
return slice.computeValue(this, key, null, true);
}
@Override
public <K, V> boolean containsKey(ReadOnlySlice<K, V> slice, K key) {
return false;
}
@Override
public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
return Collections.emptySet();
}
@Override
public Iterator<Map.Entry<SlicedMapKey<?, ?>, ?>> iterator() {
return Collections.<Map.Entry<SlicedMapKey<?, ?>, ?>>emptySet().iterator();
}
};
<K, V> V get(ReadOnlySlice<K, V> slice, K key); <K, V> V get(ReadOnlySlice<K, V> slice, K key);
<K, V> boolean containsKey(ReadOnlySlice<K, V> slice, K key); <K, V> boolean containsKey(ReadOnlySlice<K, V> slice, K key);
@@ -0,0 +1,8 @@
class A() {
class B(val i: Int) {
}
fun test() = Array<B> (10, { B(it) })
}
fun box() = if(A().test()[5].i == 5) "OK" else "fail"
@@ -41,12 +41,48 @@ fun test4() : Int {
} }
} }
fun test5() : Int {
var x = 0
System.out?.println("test 5")
while(true) {
System.out?.println(x)
try {
if(x < 10)
x++
else
break
}
finally {
x++
}
}
return x
}
fun test6() : Int {
var x = 0
System.out?.println("test 6")
while(x < 10) {
System.out?.println(x)
try {
x++
continue
}
finally {
x++
}
}
return x
}
fun box() : String { fun box() : String {
if(test1()) return "test1 failed" if(test1()) return "test1 failed"
if(test2()) return "test2 failed" if(test2()) return "test2 failed"
if(test3() != 2) return "test3 failed" if(test3() != 2) return "test3 failed"
System.out?.println(test4()) System.out?.println(test4())
if(test4() != 3) return "test4 failed" if(test4() != 3) return "test4 failed"
if(test5() != 11) return "test5 failed"
if(test6() != 10) return "test6 failed"
return "OK" return "OK"
} }
@@ -0,0 +1,9 @@
namespace org2
enum class Test {
A
B
C
}
fun box() = Test.A.toString()
@@ -0,0 +1,11 @@
namespace w_range
fun box() : String {
var i = 0
when (i) {
1 => i--
else => { i = 2 }
}
System.out?.println(i)
return "OK"
}
@@ -0,0 +1,25 @@
namespace demo2
fun print(o : Any?) {}
fun test(i : Int) {
var monthString : String? = "<empty>"
when (i) {
1 => {
print(1)
print(2)
print(3)
print(4)
print(5)
}
else => {
monthString = "Invalid month"
}
}
print(monthString)
}
fun box() : String {
for (i in 1..12) test(i)
return "OK"
}
@@ -0,0 +1,7 @@
class GenericArray {
public static void ggff() {
jet.typeinfo.TypeInfo noise = null;
String[] s = namespace.ffgg(noise, new String[0]);
}
}
@@ -0,0 +1 @@
fun <P> ffgg(a: Array<P>) = a
@@ -0,0 +1,6 @@
class Hello {
public static void xx() {
String s = namespace.f();
}
}
@@ -0,0 +1 @@
fun f() = "hello"
@@ -0,0 +1,6 @@
class Int {
{
int r = namespace.lll(1);
}
}
@@ -0,0 +1 @@
fun lll(a: Int) = a
@@ -0,0 +1,6 @@
class IntArray {
{
int[] r = namespace.doNothing(new int[0]);
}
}
@@ -0,0 +1 @@
fun doNothing(array: IntArray) = array
@@ -0,0 +1,6 @@
class IntWithDefault {
{
int r = namespace.www(1);
}
}
@@ -0,0 +1 @@
fun www(p: Int = 1) = p
@@ -0,0 +1,11 @@
import java.util.List;
import java.util.ArrayList;
class ListOfInt {
public static void hhh() {
List<Integer> list = new ArrayList<Integer>();
List<Integer> r = namespace.ggg(list);
}
}
@@ -0,0 +1,3 @@
import java.util.List
fun ggg(list: List<Int>) = list
@@ -0,0 +1,9 @@
import java.util.List;
import java.util.ArrayList;
class ListString {
public static void gg() {
List<String> list = new ArrayList<String>();
namespace.ff(list);
}
}
@@ -0,0 +1,3 @@
import java.util.List
fun ff(p: List<String>) = 1
@@ -0,0 +1,12 @@
import java.util.List;
import java.util.ArrayList;
class ListOfT {
public static void check() {
jet.typeinfo.TypeInfo nobodyCaresAboutTypeinfo = null;
List<String> list = new ArrayList<String>();
List<String> r = namespace.listOfT(nobodyCaresAboutTypeinfo, list);
}
}
@@ -0,0 +1,3 @@
import java.util.List
fun <P> listOfT(list: List<P>) = list
@@ -0,0 +1,13 @@
import java.util.Map;
import java.util.HashMap;
import java.math.BigDecimal;
class MapOfKString {
public static void gfgdgfg() {
jet.typeinfo.TypeInfo useless = null;
Map<BigDecimal, String> map = new HashMap<BigDecimal, String>();
Map<BigDecimal, String> r = namespace.fff(useless, map);
}
}
@@ -0,0 +1,3 @@
import java.util.Map
fun <K> fff(map: Map<K, String>) = map
@@ -0,0 +1,11 @@
import java.util.Map;
import java.util.HashMap;
import java.math.BigDecimal;
class MapOfKString {
public static void gfgdgfg() {
Map<String, Integer> map = new HashMap<String, Integer>();
Map<String, Integer> r = namespace.fff(map);
}
}
@@ -0,0 +1,3 @@
import java.util.Map
fun fff(map: Map<String, Int?>) = map
@@ -0,0 +1,5 @@
class Void {
{
namespace.f();
}
}
@@ -0,0 +1 @@
fun f() { }
@@ -0,0 +1,9 @@
// KT-557 Wrong type inference near sure extension function
fun Array<String>.length() : Int {
return 0;
}
fun test(array : Array<String?>?) {
array<!UNNECESSARY_SAFE_CALL!>?.<!>sure<Array<String?>>()<!UNSAFE_CALL!>.<!>length()
}
@@ -0,0 +1,9 @@
// +JDK
//KT-750 Type inference failed: Constraint violation
fun main(args : Array<String>) {
var i : Int? = Integer.valueOf(100)
var s : Int? = Integer.valueOf(100)
val o = i .sure() + s.sure()
System.out?.println(o)
}
@@ -0,0 +1,4 @@
//KT-762 Wrong highlighting in imports (No errors reported on unresolved imports)
import <!UNRESOLVED_REFERENCE!>aaa<!> // must be an error
fun main(args : Array<String>) {}
@@ -0,0 +1,3 @@
namespace test
fun ff(): String = ""
@@ -0,0 +1,3 @@
namespace test
fun ff(): String? = ""
@@ -0,0 +1,120 @@
package org.jetbrains.jet;
import com.intellij.lang.LanguageASTFactory;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.impl.PsiFileFactoryImpl;
import com.intellij.psi.impl.source.tree.JavaASTFactory;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.testFramework.UsefulTestCase;
import junit.framework.Test;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.codegen.ClassBuilderFactory;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.compiler.CompileEnvironment;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.plugin.JetLanguage;
import org.junit.Assert;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
/**
* @author Stepan Koltsov
*/
public class CompileJavaAgainstKotlinTest extends UsefulTestCase {
private final File ktFile;
private final File javaFile;
private JetCoreEnvironment jetCoreEnvironment;
private File tmpdir;
public CompileJavaAgainstKotlinTest(File ktFile) {
this.ktFile = ktFile;
Assert.assertTrue(ktFile.getName().endsWith(".kt"));
this.javaFile = new File(ktFile.getPath().replaceFirst("\\.kt", ".java"));
}
@Override
public String getName() {
return ktFile.getName();
}
@Override
protected void setUp() throws Exception {
super.setUp();
tmpdir = new File("tmp/" + this.getClass().getSimpleName() + "." + this.getName());
JetTestUtils.recreateDirectory(tmpdir);
}
@Override
public void tearDown() throws Exception {
Disposer.dispose(myTestRootDisposable);
}
@Override
protected void runTest() throws Throwable {
jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable);
LanguageASTFactory.INSTANCE.addExplicitExtension(JavaLanguage.INSTANCE, new JavaASTFactory());
String text = FileUtil.loadFile(ktFile);
LightVirtualFile virtualFile = new LightVirtualFile(ktFile.getName(), JetLanguage.INSTANCE, text);
virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET);
JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false);
GenerationState state = new GenerationState(jetCoreEnvironment.getProject(), ClassBuilderFactory.BINARIES);
AnalyzingUtils.checkForSyntacticErrors(psiFile);
state.compile(psiFile);
ClassFileFactory classFileFactory = state.getFactory();
CompileEnvironment.writeToOutputDirectory(classFileFactory, tmpdir.getPath());
Disposer.dispose(myTestRootDisposable);
JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = javaCompiler.getStandardFileManager(null, Locale.ENGLISH, Charset.forName("utf-8"));
try {
Iterable<? extends JavaFileObject> javaFileObjectsFromFiles = fileManager.getJavaFileObjectsFromFiles(Collections.singleton(javaFile));
List<String> options = Arrays.asList(
"-classpath", tmpdir.getPath() + System.getProperty("path.separator") + "out/production/stdlib",
"-d", tmpdir.getPath()
);
JavaCompiler.CompilationTask task = javaCompiler.getTask(null, fileManager, null, options, null, javaFileObjectsFromFiles);
Assert.assertTrue(task.call());
} finally {
fileManager.close();
}
}
public static Test suite() {
return JetTestCaseBuilder.suiteForDirectory(JetTestCaseBuilder.getTestDataPathBase(), "/compileJavaAgainstKotlin", true, new JetTestCaseBuilder.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) {
return new CompileJavaAgainstKotlinTest(file);
}
});
}
}
@@ -53,10 +53,7 @@ public abstract class JetLiteFixture extends UsefulTestCase {
} }
protected void createEnvironmentWithMockJdk() { protected void createEnvironmentWithMockJdk() {
myEnvironment = new JetCoreEnvironment(getTestRootDisposable()); myEnvironment = JetTestUtils.createEnvironmentWithMockJdk(getTestRootDisposable());
final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar");
myEnvironment.addToClasspath(rtJar);
myEnvironment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar"));
} }
protected void createEnvironmentWithFullJdk() { protected void createEnvironmentWithFullJdk() {
@@ -1,5 +1,6 @@
package org.jetbrains.jet; package org.jetbrains.jet;
import com.intellij.openapi.Disposable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.Diagnostic;
@@ -10,8 +11,11 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import org.jetbrains.jet.util.slicedmap.ReadOnlySlice; import org.jetbrains.jet.util.slicedmap.ReadOnlySlice;
import org.jetbrains.jet.util.slicedmap.SlicedMap;
import org.jetbrains.jet.util.slicedmap.WritableSlice; import org.jetbrains.jet.util.slicedmap.WritableSlice;
import java.io.File;
import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@@ -55,7 +59,7 @@ public class JetTestUtils {
@Override @Override
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) { public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
if (slice == BindingContext.PROCESSED) return (V) Boolean.FALSE; if (slice == BindingContext.PROCESSED) return (V) Boolean.FALSE;
return null; return SlicedMap.DO_NOTHING.get(slice, key);
} }
@NotNull @NotNull
@@ -127,4 +131,42 @@ public class JetTestUtils {
public static BindingContext analyzeNamespace(@NotNull JetNamespace namespace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { public static BindingContext analyzeNamespace(@NotNull JetNamespace namespace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
return AnalyzerFacade.analyzeOneNamespaceWithJavaIntegration(namespace, flowDataTraceFactory); return AnalyzerFacade.analyzeOneNamespaceWithJavaIntegration(namespace, flowDataTraceFactory);
} }
public static JetCoreEnvironment createEnvironmentWithMockJdk(Disposable disposable) {
JetCoreEnvironment environment = new JetCoreEnvironment(disposable);
final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar");
environment.addToClasspath(rtJar);
environment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar"));
return environment;
}
public static void mkdirs(File file) throws IOException {
if (file.isDirectory()) {
return;
}
if (!file.mkdirs()) {
throw new IOException();
}
}
public static void rmrf(File file) {
if (file != null) {
File[] children = file.listFiles();
if (children != null) {
for (File child : children) {
rmrf(child);
}
}
file.delete();
}
}
public static void recreateDirectory(File file) throws IOException {
rmrf(file);
mkdirs(file);
}
} }
@@ -1,6 +1,5 @@
package org.jetbrains.jet; package org.jetbrains.jet;
import com.intellij.lang.ASTFactory;
import com.intellij.lang.LanguageASTFactory; import com.intellij.lang.LanguageASTFactory;
import com.intellij.lang.java.JavaLanguage; import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.Disposable; import com.intellij.openapi.Disposable;
@@ -35,9 +34,7 @@ import org.jetbrains.jet.plugin.JetLanguage;
import org.junit.Assert; import org.junit.Assert;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Set; import java.util.Set;
/** /**
@@ -65,8 +62,7 @@ public class ReadClassDataTest extends UsefulTestCase {
protected void setUp() throws Exception { protected void setUp() throws Exception {
super.setUp(); super.setUp();
tmpdir = new File("tmp/" + this.getClass().getSimpleName() + "." + this.getName()); tmpdir = new File("tmp/" + this.getClass().getSimpleName() + "." + this.getName());
rmrf(tmpdir); JetTestUtils.recreateDirectory(tmpdir);
mkdirs(tmpdir);
} }
@Override @Override
@@ -74,27 +70,6 @@ public class ReadClassDataTest extends UsefulTestCase {
Disposer.dispose(myTestRootDisposable); Disposer.dispose(myTestRootDisposable);
} }
private void mkdirs(File file) throws IOException {
if (file.isDirectory()) {
return;
}
if (!file.mkdirs()) {
throw new IOException();
}
}
private void rmrf(File file) {
if (file != null) {
File[] children = file.listFiles();
if (children != null) {
for (File child : children) {
rmrf(child);
}
}
file.delete();
}
}
private void createMockCoreEnvironment() { private void createMockCoreEnvironment() {
jetCoreEnvironment = new JetCoreEnvironment(myTestRootDisposable); jetCoreEnvironment = new JetCoreEnvironment(myTestRootDisposable);
@@ -105,16 +80,14 @@ public class ReadClassDataTest extends UsefulTestCase {
@Override @Override
public void runTest() throws Exception { public void runTest() throws Exception {
if (true) return; jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable);
createMockCoreEnvironment();
LanguageASTFactory.INSTANCE.addExplicitExtension(JavaLanguage.INSTANCE, new JavaASTFactory()); LanguageASTFactory.INSTANCE.addExplicitExtension(JavaLanguage.INSTANCE, new JavaASTFactory());
String text = FileUtil.loadFile(testFile); String text = FileUtil.loadFile(testFile);
LightVirtualFile virtualFile = new LightVirtualFile("Hello.kt", JetLanguage.INSTANCE, text); LightVirtualFile virtualFile = new LightVirtualFile(testFile.getName(), JetLanguage.INSTANCE, text);
virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET);
JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false);
@@ -131,11 +104,10 @@ public class ReadClassDataTest extends UsefulTestCase {
Assert.assertEquals("test", namespaceFromSource.getName()); Assert.assertEquals("test", namespaceFromSource.getName());
Disposer.dispose(myTestRootDisposable); Disposer.dispose(myTestRootDisposable);
jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable);
createMockCoreEnvironment();
jetCoreEnvironment.addToClasspath(tmpdir); jetCoreEnvironment.addToClasspath(tmpdir);
JetSemanticServices jetSemanticServices = JetSemanticServices.createSemanticServices(jetCoreEnvironment.getProject()); JetSemanticServices jetSemanticServices = JetSemanticServices.createSemanticServices(jetCoreEnvironment.getProject());
@@ -184,7 +156,8 @@ public class ReadClassDataTest extends UsefulTestCase {
for (int i = 0; i < a.getValueParameters().size(); ++i) { for (int i = 0; i < a.getValueParameters().size(); ++i) {
compareAnything(ValueParameterDescriptor.class, a.getValueParameters().get(i), b.getValueParameters().get(i)); compareAnything(ValueParameterDescriptor.class, a.getValueParameters().get(i), b.getValueParameters().get(i));
} }
System.out.println("function " + a.getName()); Assert.assertEquals(a.getReturnType(), b.getReturnType());
System.out.println("fun " + a.getName() + "(...): " + a.getReturnType());
} }
private <T> void compareAnything(Class<T> clazz, T a, T b) { private <T> void compareAnything(Class<T> clazz, T a, T b) {
@@ -286,4 +286,9 @@ public class ArrayGenTest extends CodegenTestCase {
// System.out.println(generateToText()); // System.out.println(generateToText());
blackBox(); blackBox();
} }
public void testNonNullArray() throws Exception {
blackBoxFile("classes/nonnullarray.jet");
System.out.println(generateToText());
}
} }
@@ -1,5 +1,7 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.psi.JetNamespace;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
@@ -216,6 +218,10 @@ public class ClassGenTest extends CodegenTestCase {
blackBoxFile("regressions/kt500.jet"); blackBoxFile("regressions/kt500.jet");
} }
public void testKt694 () throws Exception {
// blackBoxFile("regressions/kt694.jet");
}
public void testKt285 () throws Exception { public void testKt285 () throws Exception {
// blackBoxFile("regressions/kt285.jet"); // blackBoxFile("regressions/kt285.jet");
} }
@@ -221,6 +221,16 @@ public class ControlStructuresTest extends CodegenTestCase {
blackBoxFile("regressions/kt434.jet"); blackBoxFile("regressions/kt434.jet");
} }
public void testKt769() throws Exception {
blackBoxFile("regressions/kt769.jet");
// System.out.println(generateToText());
}
public void testKt773() throws Exception {
blackBoxFile("regressions/kt773.jet");
// System.out.println(generateToText());
}
public void testQuicksort() throws Exception { public void testQuicksort() throws Exception {
blackBoxFile("controlStructures/quicksort.jet"); blackBoxFile("controlStructures/quicksort.jet");
// System.out.println(generateToText()); // System.out.println(generateToText());
+43
View File
@@ -0,0 +1,43 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.ReentrantLock;
public class LockPerf {
public static void main(String[] args) {
int processors = Runtime.getRuntime().availableProcessors();
for (int threadNum = 1; threadNum <= 1024; threadNum = threadNum < 2 * processors ? threadNum + 1 : threadNum * 2) {
final AtomicInteger counter = new AtomicInteger();
final CountDownLatch cdl = new CountDownLatch(threadNum);
final ReentrantLock lock = new ReentrantLock();
long start = System.currentTimeMillis();
for (int i = 0; i < threadNum; ++i) {
new Thread(new Runnable() {
public void run() {
for (;;) {
lock.lock();
try {
if (counter.get() == 100000000) {
cdl.countDown();
break;
} else {
counter.incrementAndGet();
}
} finally {
lock.unlock();
}
}
}
}).start();
}
try {
cdl.await();
} catch (InterruptedException e) {//
}
System.out.println(threadNum + " " + (System.currentTimeMillis() - start));
}
}
}
+55
View File
@@ -0,0 +1,55 @@
namespace lockperformance
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.ReentrantLock;
fun thread(f: fun ()) {
val thread = Thread(
object: Runnable {
override fun run() {
f()
}
}
)
thread.start()
}
fun main(args: Array<String>) {
val processors = Runtime.getRuntime().sure().availableProcessors()
var threadNum = 1
while(threadNum <= 1024) {
val counter = AtomicInteger()
val cdl = CountDownLatch(threadNum)
val lock = ReentrantLock()
val start = System.currentTimeMillis()
for(i in 0..threadNum-1) {
thread {
while(true) {
lock.lock()
try {
if (counter.get() == 100000000) {
cdl.countDown();
break;
} else {
counter.incrementAndGet();
}
}
finally {
lock.unlock()
}
}
}
}
cdl.await()
System.out?.println(threadNum.toString() + " " + (System.currentTimeMillis() - start));
if(threadNum < 2 * processors)
threadNum = threadNum + 1
else
threadNum = threadNum * 2
}
}
+169
View File
@@ -0,0 +1,169 @@
/*
The Computer Language Benchmarks Game
http://shootout.alioth.debian.org/
Based on C# entry by Isaac Gouy
contributed by Jarkko Miettinen
Parallel by The Anh Tran
*/
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.concurrent.CyclicBarrier;
public class SpectralNorm
{
private static final NumberFormat formatter = new DecimalFormat ("#.000000000");
public static void main (String[] args)
{
int n = 5500;
if (args.length > 0) n = Integer.parseInt (args[0]);
final long millis = System.currentTimeMillis();
System.out.println (formatter.format (spectralnormGame (n)) );
long total = System.currentTimeMillis() - millis;
System.out.println("[SpectralNorm-" + System.getProperty("project.name")+ " Benchmark Result: " + total + "]");
}
private static final double spectralnormGame (int n)
{
// create unit vector
double[] u = new double[n];
double[] v = new double[n];
double[] tmp = new double[n];
for (int i = 0; i < n; i++)
u[i] = 1.0;
// get available processor, then set up syn object
int nthread = Runtime.getRuntime ().availableProcessors ();
Approximate.barrier = new CyclicBarrier (nthread);
int chunk = n / nthread;
Approximate[] ap = new Approximate[nthread];
for (int i = 0; i < nthread; i++)
{
int r1 = i * chunk;
int r2 = (i < (nthread -1)) ? r1 + chunk : n;
ap[i] = new Approximate (u, v, tmp, r1, r2);
}
double vBv = 0, vv = 0;
for (int i = 0; i < nthread; i++)
{
try
{
ap[i].join ();
vBv += ap[i].m_vBv;
vv += ap[i].m_vv;
}
catch (Exception e)
{
e.printStackTrace ();
}
}
return Math.sqrt (vBv/vv);
}
private static class Approximate extends Thread
{
private static CyclicBarrier barrier;
private double[] _u;
private double[] _v;
private double[] _tmp;
private int range_begin, range_end;
private double m_vBv = 0, m_vv = 0;
public Approximate (double[] u, double[] v, double[] tmp, int rbegin, int rend)
{
super ();
_u = u;
_v = v;
_tmp = tmp;
range_begin = rbegin;
range_end = rend;
start ();
}
public void run ()
{
// 20 steps of the power method
for (int i = 0; i < 10; i++)
{
MultiplyAtAv (_u, _tmp, _v);
MultiplyAtAv (_v, _tmp, _u);
}
for (int i = range_begin; i < range_end; i++)
{
m_vBv += _u[i] * _v[i];
m_vv += _v[i] * _v[i];
}
}
/* return element i,j of infinite matrix A */
private final static double eval_A (int i, int j)
{
int div = ( ((i+j) * (i+j+1) >>> 1) +i+1 );
return 1.0 / div;
}
/* multiply vector v by matrix A, each thread evaluate its range only */
private final void MultiplyAv (final double[] v, double[] Av)
{
for (int i = range_begin; i < range_end; i++)
{
double sum = 0;
for (int j = 0; j < v.length; j++)
sum += eval_A (i, j) * v[j];
Av[i] = sum;
}
}
/* multiply vector v by matrix A transposed */
private final void MultiplyAtv (final double[] v, double[] Atv)
{
for (int i = range_begin; i < range_end; i++)
{
double sum = 0;
for (int j = 0; j < v.length; j++)
sum += eval_A (j, i) * v[j];
Atv[i] = sum;
}
}
/* multiply vector v by matrix A and then by matrix A transposed */
private final void MultiplyAtAv (final double[] v, double[] tmp, double[] AtAv)
{
try
{
MultiplyAv (v, tmp);
// all thread must syn at completion
barrier.await ();
MultiplyAtv (tmp, AtAv);
// all thread must syn at completion
barrier.await ();
}
catch (Exception e)
{
e.printStackTrace ();
}
}
}
}
+128
View File
@@ -0,0 +1,128 @@
namespace spectralnorm
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.concurrent.CyclicBarrier;
val formatter = DecimalFormat ("#.000000000");
fun main (args : Array<String>) {
var n = 5500
if (args.size > 0)
n = Integer.parseInt (args[0]);
val millis = System.currentTimeMillis()
System.out?.println (formatter.format (spectralnormGame (n)) )
val total = System.currentTimeMillis() - millis;
System.out?.println("[SpectralNorm-" + System.getProperty("project.name")+ " Benchmark Result: " + total + "]");
}
fun spectralnormGame(n: Int) : Double {
val u = DoubleArray(n)
val v = DoubleArray(n)
val tmp = DoubleArray(n)
for(i in u.indices) {
u[i] = 1.0
}
val nthread = Runtime.getRuntime ().sure().availableProcessors ();
barrier = CyclicBarrier (nthread);
val chunk = n / nthread
val ap = Array<Approximate>(nthread,{
val r1 = it * chunk;
val r2 = if(it < (nthread -1)) r1 + chunk else nthread;
Approximate (u, v, tmp, r1, r2)
})
var vBv = 0.dbl
var vv = 0.dbl;
for (i in 0..nthread-1) {
try {
ap[i].join ();
vBv += ap[i].m_vBv;
vv += ap[i].m_vv;
}
catch (e: Exception )
{
e.printStackTrace ();
}
}
return Math.sqrt (vBv/vv);
}
fun eval_A (i: Int, j: Int) = 1.0 / ( ((i+j) * (i+j+1) shr 1) +i+1 )
var barrier : CyclicBarrier? = null
class Approximate(val u: DoubleArray, val v: DoubleArray, val _tmp: DoubleArray, val rbegin: Int, val rend: Int) : Thread() {
class object {
}
var m_vBv = 0.0
var m_vv = 0.0
{
start()
}
override fun run () {
for(i in 0..10) {
MultiplyAtAv (u, _tmp, v);
MultiplyAtAv (v, _tmp, u);
}
for(i in rbegin..rend) {
m_vBv += u[i] * v[i];
m_vv += v[i] * v[i];
}
}
/* multiply vector v by matrix A, each thread evaluate its range only */
fun MultiplyAv (v: DoubleArray, Av: DoubleArray)
{
for (i in rbegin..rend)
{
var sum = 0.0;
for (j in v.indices)
sum += eval_A (i, j) * v[j];
Av[i] = sum;
}
}
/* multiply vector v by matrix A transposed */
fun MultiplyAtv (v: DoubleArray, Atv: DoubleArray)
{
for (i in rbegin..rend)
{
var sum = 0.dbl
for (j in v.indices)
sum += eval_A (j, i) * v[j];
Atv[i] = sum;
}
}
/* multiply vector v by matrix A and then by matrix A transposed */
fun MultiplyAtAv (v: DoubleArray, tmp: DoubleArray, AtAv: DoubleArray)
{
try
{
MultiplyAv (v, tmp);
// all thread must syn at completion
barrier?.await ();
MultiplyAtv (tmp, AtAv);
// all thread must syn at completion
barrier?.await ();
}
catch (e: Exception)
{
e.printStackTrace ();
}
}
}
+137
View File
@@ -0,0 +1,137 @@
/**
* The Computer Language Benchmarks Game
* http://shootout.alioth.debian.org/
*
* contributed by Fabien Le Floc'h
*
* Java implementation of thread-ring benchmark. Best performance is achieved with
* MAX_THREAD=1 as the thread-ring test is bested with only 1 os thread.
* This implementation shows using a simple thread pool solves the thread context
* switch issue.
*/
import java.util.concurrent.*;
public class ThreadRing {
private static final int MAX_NODES = 503;
private static final int MAX_THREADS = 503;
private ExecutorService executor;
private final int N;
static final CountDownLatch cdl = new CountDownLatch(1);
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
int n = 5000000;
try {
n = Integer.parseInt(args[0]);
} catch (Exception e) {}
ThreadRing ring = new ThreadRing(n);
Node node = ring.start(MAX_NODES);
node.sendMessage(new TokenMessage(1,0));
cdl.await();
long total = System.currentTimeMillis() - start;
System.out.println("[ThreadRing-" + System.getProperty("project.name")+ " Benchmark Result: " + total + "]");
}
public ThreadRing(int n) {
N = n;
}
public Node start(int n) {
Node[] nodes = spawnNodes(n);
connectNodes(n, nodes);
return nodes[0];
}
private Node[] spawnNodes(int n) {
executor = Executors.newFixedThreadPool(MAX_THREADS);
Node[] nodes = new Node[n+1];
for (int i = 0; i < n ; i++) {
nodes[i] = new Node(i+1, null);
}
return nodes;
}
public void connectNodes(int n, Node[] nodes) {
nodes[n] = nodes[0];
for (int i=0; i<n; i++) {
nodes[i].connect(nodes[i+1]);
}
}
private static class TokenMessage {
private int nodeId;
private volatile int value;
private boolean isStop;
public TokenMessage(int nodeId, int value) {
this.nodeId = nodeId;
this.value = value;
}
public TokenMessage(int nodeId, int value, boolean isStop) {
this.nodeId = nodeId;
this.value = value;
this.isStop = isStop;
}
}
private class Node implements Runnable {
private int nodeId;
private Node nextNode;
private BlockingQueue<TokenMessage> queue = new LinkedBlockingQueue<TokenMessage>();
private boolean isActive = false;
private int counter;
public Node(int id, Node nextNode) {
this.nodeId = id;
this.nextNode = nextNode;
this.counter = 0;
}
public void connect(Node node) {
this.nextNode = node;
isActive = true;
}
public void sendMessage(TokenMessage m) {
queue.add(m);
executor.execute(this);
}
public void run() {
if (isActive) {
try {
TokenMessage m = queue.take();
if (m.isStop) {
int nextValue = m.value+1;
if (nextValue == MAX_NODES) {
// System.out.println("last one");
executor.shutdown();
cdl.countDown();
} else {
m.value = nextValue;
nextNode.sendMessage(m);
}
isActive = false;
// System.out.println("ending node "+nodeId);
} else {
if (m.value == N) {
System.out.println(nodeId);
nextNode.sendMessage(new TokenMessage(nodeId, 0, true));
} else {
m.value = m.value + 1;
nextNode.sendMessage(m);
}
}
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}
}
+95
View File
@@ -0,0 +1,95 @@
namespace threadring
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
val MAX_NODES = 503
val MAX_THREADS = 503
val cdl = CountDownLatch(1)
fun main(args: Array<String>) {
val start = System.currentTimeMillis()
var n = 5000000;
try {
n = Integer.parseInt(args[0]);
} catch (e: Throwable) {
}
val ring = ThreadRing(n)
ring.sendMessage(TokenMessage(1,0,false))
cdl.await();
val total = System.currentTimeMillis() - start
System.out?.println("[ThreadRing-" + System.getProperty("project.name")+ " Benchmark Result: " + total + "]")
}
class TokenMessage(val nodeId : Int, value: Int, val isStop: Boolean) : AtomicInteger(value){
}
class ThreadRing(val N: Int) {
val executor = Executors.newFixedThreadPool(MAX_THREADS).sure()
val nodes : Array<Node> = Array<Node>(MAX_NODES+1, { Node(it+1) })
{
connectNodes()
}
fun connectNodes() {
nodes[nodes.size-1] = nodes[0]
for (i in 0..nodes.size-2) {
nodes[i].connect(nodes[i+1]);
}
}
fun sendMessage(m : TokenMessage) {
nodes[0].sendMessage(m)
}
class Node(val nodeId : Int) : Runnable {
val queue = LinkedBlockingQueue<TokenMessage>()
var isActive = false
var nextNode : Node? = null
fun sendMessage(m: TokenMessage) {
queue.add(m)
executor.execute(this)
}
fun connect(next: Node) {
nextNode = next
isActive = true
}
override fun run() {
if(isActive) {
try {
val m = queue.take()
if(m.isStop) {
val nextValue = m.get()+1
if (nextValue == MAX_NODES) {
executor.shutdown()
cdl.countDown()
} else {
m.set(nextValue)
nextNode.sure().sendMessage(m)
}
isActive = false
}
else {
if (m.get() == N) {
System.out?.println(nodeId);
nextNode.sure().sendMessage(TokenMessage(nodeId, 0, true));
} else {
m.incrementAndGet()
nextNode.sure().sendMessage(m);
}
}
}
catch(e: InterruptedException) {
e.printStackTrace()
}
}
}
}
}
@@ -4,7 +4,7 @@ import com.intellij.ide.IconProvider;
import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.Iconable;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Icons; import com.intellij.util.PlatformIcons;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
@@ -15,21 +15,21 @@ import javax.swing.*;
* @author yole * @author yole
*/ */
public class JetIconProvider extends IconProvider { public class JetIconProvider extends IconProvider {
public static final Icon ICON_FOR_OBJECT = Icons.ANONYMOUS_CLASS_ICON; public static final Icon ICON_FOR_OBJECT = PlatformIcons.ANONYMOUS_CLASS_ICON;
@Override @Override
public Icon getIcon(@NotNull PsiElement psiElement, int flags) { public Icon getIcon(@NotNull PsiElement psiElement, int flags) {
if (psiElement instanceof JetNamespace) { if (psiElement instanceof JetNamespace) {
return (flags & Iconable.ICON_FLAG_OPEN) != 0 ? Icons.PACKAGE_OPEN_ICON : Icons.PACKAGE_ICON; return (flags & Iconable.ICON_FLAG_OPEN) != 0 ? PlatformIcons.PACKAGE_OPEN_ICON : PlatformIcons.PACKAGE_ICON;
} }
if (psiElement instanceof JetNamedFunction) { if (psiElement instanceof JetNamedFunction) {
return PsiTreeUtil.getParentOfType(psiElement, JetNamedDeclaration.class) instanceof JetClass return PsiTreeUtil.getParentOfType(psiElement, JetNamedDeclaration.class) instanceof JetClass
? Icons.METHOD_ICON ? PlatformIcons.METHOD_ICON
: Icons.FUNCTION_ICON; : PlatformIcons.FUNCTION_ICON;
} }
if (psiElement instanceof JetClass) { if (psiElement instanceof JetClass) {
JetClass jetClass = (JetClass) psiElement; JetClass jetClass = (JetClass) psiElement;
Icon icon = jetClass.hasModifier(JetTokens.ENUM_KEYWORD) ? Icons.ENUM_ICON : Icons.CLASS_ICON; Icon icon = jetClass.hasModifier(JetTokens.ENUM_KEYWORD) ? PlatformIcons.ENUM_ICON : PlatformIcons.CLASS_ICON;
if (jetClass instanceof JetEnumEntry) { if (jetClass instanceof JetEnumEntry) {
JetEnumEntry enumEntry = (JetEnumEntry) jetClass; JetEnumEntry enumEntry = (JetEnumEntry) jetClass;
if (enumEntry.getPrimaryConstructorParameterList() == null) { if (enumEntry.getPrimaryConstructorParameterList() == null) {
@@ -42,13 +42,13 @@ public class JetIconProvider extends IconProvider {
if (((JetParameter) psiElement).getValOrVarNode() != null) { if (((JetParameter) psiElement).getValOrVarNode() != null) {
JetParameterList parameterList = PsiTreeUtil.getParentOfType(psiElement, JetParameterList.class); JetParameterList parameterList = PsiTreeUtil.getParentOfType(psiElement, JetParameterList.class);
if (parameterList != null && parameterList.getParent() instanceof JetClass) { if (parameterList != null && parameterList.getParent() instanceof JetClass) {
return Icons.PROPERTY_ICON; return PlatformIcons.PROPERTY_ICON;
} }
} }
return Icons.PARAMETER_ICON; return PlatformIcons.PARAMETER_ICON;
} }
if (psiElement instanceof JetProperty) { if (psiElement instanceof JetProperty) {
return Icons.PROPERTY_ICON; return PlatformIcons.PROPERTY_ICON;
} }
return null; return null;
} }
@@ -24,13 +24,23 @@ import java.util.Set;
/** /**
* @author abreslav * @author abreslav
*/ */
public class WholeProjectAnalyzerFacade { public final class WholeProjectAnalyzerFacade {
public static final Function<JetFile, Collection<JetDeclaration>> WHOLE_PROJECT_DECLARATION_PROVIDER = new Function<JetFile, Collection<JetDeclaration>>() {
/** Forbid creating */
private WholeProjectAnalyzerFacade() {}
/**
* Will collect all root-namespaces in all kotlin files in the project.
*/
public static final Function<JetFile, Collection<JetDeclaration>> WHOLE_PROJECT_DECLARATION_PROVIDER =
new Function<JetFile, Collection<JetDeclaration>>() {
@Override @Override
public Collection<JetDeclaration> fun(final JetFile rootFile) { public Collection<JetDeclaration> fun(final JetFile rootFile) {
final Project project = rootFile.getProject(); final Project project = rootFile.getProject();
final Set<JetDeclaration> namespaces = Sets.newLinkedHashSet(); final Set<JetDeclaration> namespaces = Sets.newLinkedHashSet();
ProjectRootManager rootManager = ProjectRootManager.getInstance(project); final ProjectRootManager rootManager = ProjectRootManager.getInstance(project);
if (rootManager != null && !ApplicationManager.getApplication().isUnitTestMode()) { if (rootManager != null && !ApplicationManager.getApplication().isUnitTestMode()) {
VirtualFile[] contentRoots = rootManager.getContentRoots(); VirtualFile[] contentRoots = rootManager.getContentRoots();
@@ -55,9 +65,9 @@ public class WholeProjectAnalyzerFacade {
} }
}; };
@NotNull @NotNull
public static BindingContext analyzeProjectWithCacheOnAFile(@NotNull JetFile file) { public static BindingContext analyzeProjectWithCacheOnAFile(@NotNull JetFile file) {
return AnalyzerFacade.analyzeFileWithCache(file, WHOLE_PROJECT_DECLARATION_PROVIDER); return AnalyzerFacade.analyzeFileWithCache(file, WHOLE_PROJECT_DECLARATION_PROVIDER);
} }
} }
@@ -21,27 +21,31 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore; import com.intellij.psi.util.PsiUtilCore;
import com.intellij.ui.content.ContentFactory; import com.intellij.ui.content.ContentFactory;
import com.intellij.util.Alarm; import com.intellij.util.Alarm;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetReferenceExpression; import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.ResolvedValueArgument; import org.jetbrains.jet.lang.resolve.calls.ResolvedValueArgument;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.plugin.JetFileType; import org.jetbrains.jet.plugin.JetFileType;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade; import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
import org.jetbrains.jet.plugin.internal.codewindow.BytecodeToolwindow; import org.jetbrains.jet.plugin.internal.codewindow.BytecodeToolwindow;
import org.jetbrains.jet.util.slicedmap.ReadOnlySlice;
import org.jetbrains.jet.util.slicedmap.WritableSlice;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.util.Map; import java.util.Map;
import static org.jetbrains.jet.lang.resolve.BindingContext.EXPRESSION_TYPE; import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; import static org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL;
/* /*
* @author abreslav * @author abreslav
@@ -121,19 +125,20 @@ public class ResolveToolwindow extends JPanel {
PsiElement currentElement = elementAtOffset; PsiElement currentElement = elementAtOffset;
boolean callFound = false; boolean callFound = false;
while (currentElement != null && !(currentElement instanceof PsiFile)) {
if (currentElement instanceof JetElement) {
JetElement atOffset = (JetElement) currentElement;
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(RESOLVED_CALL, (JetElement) atOffset);
if (resolvedCall != null) {
setText(renderCall(resolvedCall) + "\n===\n" + currentElement + ": " + currentElement.getText());
callFound = true;
break;
}
} PsiElement elementWithDebugInfo = findData(bindingContext, currentElement, RESOLUTION_DEBUG_INFO);
currentElement = currentElement.getParent(); if (elementWithDebugInfo != null) {
callFound = true;
setText(renderDebugInfo(elementWithDebugInfo, bindingContext.get(RESOLUTION_DEBUG_INFO, elementWithDebugInfo), null));
} }
else {
PsiElement elementWithResolvedCall = findData(bindingContext, currentElement, (WritableSlice) RESOLVED_CALL);
if (elementWithResolvedCall instanceof JetElement) {
callFound = true;
setText(renderDebugInfo(elementWithResolvedCall, null, bindingContext.get(RESOLVED_CALL, (JetElement) elementWithResolvedCall)));
}
}
if (!callFound) { if (!callFound) {
JetExpression parentExpression = (elementAtOffset instanceof JetExpression) ? (JetExpression) elementAtOffset JetExpression parentExpression = (elementAtOffset instanceof JetExpression) ? (JetExpression) elementAtOffset
@@ -153,8 +158,70 @@ public class ResolveToolwindow extends JPanel {
} }
} }
private String renderCall(ResolvedCall<? extends CallableDescriptor> resolvedCall) { @Nullable
StringBuilder builder = new StringBuilder(); private <D> PsiElement findData(BindingContext bindingContext, PsiElement currentElement, ReadOnlySlice<PsiElement, D> slice) {
while (currentElement != null && !(currentElement instanceof PsiFile)) {
if (currentElement instanceof JetElement) {
JetElement atOffset = (JetElement) currentElement;
D data = bindingContext.get(slice, atOffset);
if (data != null && data != NO_DEBUG_INFO) {
return currentElement;
}
}
currentElement = currentElement.getParent();
}
return null;
}
private String renderDebugInfo(PsiElement currentElement, @Nullable ResolutionDebugInfo.Data debugInfo, @Nullable ResolvedCall<? extends CallableDescriptor> call) {
final String bar = "\n\n===\n\n";
StringBuilder result = new StringBuilder();
if (debugInfo != null) {
StringBuilder errors = debugInfo.get(ERRORS);
if (errors != null) {
result.append("Errors: \n").append(errors).append(bar);
}
StringBuilder log = debugInfo.get(LOG);
if (log != null) {
result.append("Log: \n").append(log).append(bar);
}
Map<JetType, ConstraintSystemImpl.TypeValue> knowns = debugInfo.get(BOUNDS_FOR_KNOWNS);
renderMap(knowns, result);
Map<TypeParameterDescriptor, ConstraintSystemImpl.TypeValue> unknowns = debugInfo.get(BOUNDS_FOR_UNKNOWNS);
renderMap(unknowns, result);
result.append(bar);
call = debugInfo.get(RESULT);
}
renderCall(result, call);
result.append(currentElement + ": " + currentElement.getText());
return result.toString();
}
private <K> void renderMap(Map<K, ConstraintSystemImpl.TypeValue> map, StringBuilder builder) {
if (map == null) return;
for (Map.Entry<K, ConstraintSystemImpl.TypeValue> entry : map.entrySet()) {
K key = entry.getKey();
ConstraintSystemImpl.TypeValue typeValue = entry.getValue();
builder.append("Bounds for ").append(key).append("\n");
for (ConstraintSystemImpl.TypeValue bound : typeValue.getLowerBounds()) {
builder.append(" >: ").append(bound).append("\n");
}
for (ConstraintSystemImpl.TypeValue bound : typeValue.getUpperBounds()) {
builder.append(" <: ").append(bound).append("\n");
}
}
}
private String renderCall(StringBuilder builder, ResolvedCall<? extends CallableDescriptor> resolvedCall) {
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor(); CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
ReceiverDescriptor receiverArgument = resolvedCall.getReceiverArgument(); ReceiverDescriptor receiverArgument = resolvedCall.getReceiverArgument();
@@ -0,0 +1,9 @@
namespace Tests
import java.util.*
fun hello() {
val a = So<caret>
}
// EXIST: SortedSet, SortedMap
@@ -0,0 +1,6 @@
namespace Tests
class A : java.<caret>
// EXIST: lang, util, io
// ABSENT: fun, val, var, namespace
@@ -1,10 +1,10 @@
open class MyClass() { open class MyClass() {
} }
class A() : My<caret> { class A() {
public fun test() { public fun test() {
val a : MyC<caret> val a : MyC<caret>
} }
} }
// EXIST: MyClass // EXIST: MyClass
@@ -3,4 +3,4 @@ fun foo() {
} }
// TODO: Move all keywords to absent // TODO: Move all keywords to absent
// EXPECT: fun, val, var, namespace // EXIST: fun, val, var, namespace
@@ -1,8 +1,8 @@
<caret> <caret>
// EXPECT: namespace, as, type, class, this, super, val, var, fun, for, null, true // EXIST: namespace, as, type, class, this, super, val, var, fun, for, null, true
// EXPECT: false, is, in, throw, return, break, continue, object, if, try, else, while // EXIST: false, is, in, throw, return, break, continue, object, if, try, else, while
// EXPECT: do, when, trait, This // EXIST: do, when, trait, This
// EXPECT: import, where, by, get, set, abstract, enum, open, annotation, override, private // EXIST: import, where, by, get, set, abstract, enum, open, annotation, override, private
// EXPECT: public, internal, protected, catch, out, vararg, inline, finally, final, ref // EXIST: public, internal, protected, catch, out, vararg, inline, finally, final, ref
// ABSENT: ?in, new, extends, implements // ABSENT: ?in, new, extends, implements
@@ -23,7 +23,7 @@ public class JetBasicCompletionTest extends JetCompletionTestBase {
setName("testCompletionExecute"); setName("testCompletionExecute");
} }
public void testCompletionExecute() { public void testCompletionExecute() throws Exception {
doTest(); doTest();
} }
@@ -2,70 +2,64 @@ package org.jetbrains.jet.completion;
import com.intellij.codeInsight.completion.CodeCompletionHandlerBase; import com.intellij.codeInsight.completion.CodeCompletionHandlerBase;
import com.intellij.codeInsight.completion.CompletionType; import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.codeInsight.completion.LightCompletionTestCase;
import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupEx;
import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.testFramework.LightCodeInsightTestCase; import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.openapi.projectRoots.Sdk;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.plugin.PluginTestCaseBase;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.StringReader; import java.io.StringReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
/** /**
* @author Nikolay.Krasko * @author Nikolay.Krasko
*/ */
public abstract class JetCompletionTestBase extends LightCodeInsightTestCase { public abstract class JetCompletionTestBase extends LightCompletionTestCase {
protected void doTest() { private CompletionType type;
protected void doTest() throws Exception {
final String testName = getTestName(false); final String testName = getTestName(false);
type = (testName.startsWith("Smart")) ? CompletionType.SMART : CompletionType.BASIC;
configureByFile(testName + ".kt"); configureByFile(testName + ".kt");
CompletionType completionType = (testName.startsWith("Smart")) ? CompletionType.SMART : CompletionType.BASIC; assertContainsItems(itemsShouldExist(getFile().getText()));
new CodeCompletionHandlerBase(completionType, false, false, true).invokeCompletion(getProject(), getEditor()); assertNotContainItems(itemsShouldAbsent(getFile().getText()));
LookupEx lookup = LookupManager.getActiveLookup(getEditor());
assert lookup != null;
HashSet<String> items = new HashSet<String>(resolveLookups(lookup.getItems()));
List<String> shouldExist = itemsShouldExist(getFile().getText());
for (String shouldExistItem : shouldExist) {
assertTrue(String.format("Should contain proposal '%s'.", shouldExistItem),
items.contains(shouldExistItem));
}
List<String> shouldAbsent = itemsShouldAbsent(getFile().getText());
for (String shouldAbsentItem : shouldAbsent) {
assertTrue(String.format("Shouldn't contain proposal '%s'.", shouldAbsentItem),
!items.contains(shouldAbsentItem));
}
} }
private static List<String> resolveLookups(List<LookupElement> items) {
ArrayList<String> result = new ArrayList<String>(items.size());
for (LookupElement item : items) {
result.add(item.getLookupString());
}
return result; @Override
protected Sdk getProjectJDK() {
return PluginTestCaseBase.jdkFromIdeaHome();
}
@Override
protected void complete(final int time) {
new CodeCompletionHandlerBase(type, false, false, true).invokeCompletion(getProject(), getEditor(), time, false);
LookupImpl lookup = (LookupImpl) LookupManager.getActiveLookup(myEditor);
myItems = lookup == null ? null : lookup.getItems().toArray(LookupElement.EMPTY_ARRAY);
myPrefix = lookup == null ? null : lookup.itemPattern(lookup.getItems().get(0));
} }
@NotNull @NotNull
private static List<String> itemsShouldExist(String fileText) { private static String[] itemsShouldExist(String fileText) {
return findListWithPrefix("// EXIST:", fileText); return findListWithPrefix("// EXIST:", fileText);
} }
@NotNull @NotNull
private static List<String> itemsShouldAbsent(String fileText) { private static String[] itemsShouldAbsent(String fileText) {
return findListWithPrefix("// ABSENT:", fileText); return findListWithPrefix("// ABSENT:", fileText);
} }
@NotNull @NotNull
private static List<String> findListWithPrefix(String prefix, String fileText) { private static String[] findListWithPrefix(String prefix, String fileText) {
ArrayList<String> result = new ArrayList<String>(); ArrayList<String> result = new ArrayList<String>();
for (String line : findLinesWithPrefixRemoved(prefix, fileText)) { for (String line : findLinesWithPrefixRemoved(prefix, fileText)) {
@@ -76,7 +70,7 @@ public abstract class JetCompletionTestBase extends LightCodeInsightTestCase {
} }
} }
return result; return result.toArray(new String[result.size()]);
} }
@NotNull @NotNull
@@ -1,5 +1,6 @@
package org.jetbrains.jet.completion; package org.jetbrains.jet.completion;
import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestCaseBuilder;
@@ -25,7 +26,7 @@ public class KeywordsCompletionTest extends JetCompletionTestBase {
setName("testCompletionExecute"); setName("testCompletionExecute");
} }
public void testCompletionExecute() { public void testCompletionExecute() throws Exception {
doTest(); doTest();
} }
@@ -49,13 +50,14 @@ public class KeywordsCompletionTest extends JetCompletionTestBase {
PluginTestCaseBase.getTestDataPathBase(), "/completion/keywords/", false, PluginTestCaseBase.getTestDataPathBase(), "/completion/keywords/", false,
JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() { JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() {
@NotNull @NotNull
@Override @Override
public junit.framework.Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) {
return new KeywordsCompletionTest(dataPath, name); return new KeywordsCompletionTest(dataPath, name);
} }
}, suite); }, suite);
return suite; return suite;
} }
} }