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 {
private String owner;
private final Method signature;
private final JvmMethodSignature signature;
private int invokeOpcode;
private final List<Type> valueParameterTypes;
private ClassDescriptor thisClass = null;
@@ -27,7 +27,7 @@ public class CallableMethod implements Callable {
private CallableDescriptor receiverFunction = 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.signature = signature;
this.invokeOpcode = invokeOpcode;
@@ -38,7 +38,7 @@ public class CallableMethod implements Callable {
return owner;
}
public Method getSignature() {
public JvmMethodSignature getSignature() {
return signature;
}
@@ -67,7 +67,7 @@ public class CallableMethod implements Callable {
}
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) {
@@ -80,14 +80,14 @@ public class CallableMethod implements Callable {
public void invokeWithDefault(InstructionAdapter v, int mask) {
v.iconst(mask);
String desc = getSignature().getDescriptor().replace(")", "I)");
if("<init>".equals(getSignature().getName())) {
String desc = getSignature().getAsmMethod().getDescriptor().replace(")", "I)");
if("<init>".equals(getSignature().getAsmMethod().getName())) {
v.visitMethodInsn(Opcodes.INVOKESPECIAL, getOwner(), "<init>", desc);
}
else {
if(getInvokeOpcode() != Opcodes.INVOKESTATIC)
desc = desc.replace("(", "(L" + getOwner() + ";");
v.visitMethodInsn(Opcodes.INVOKESTATIC, getInvokeOpcode() == Opcodes.INVOKEINTERFACE ? getOwner() + "$$TImpl" : getOwner(), getSignature().getName() + "$default", desc);
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.psi.JetDeclarationWithBody;
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.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
@@ -54,7 +53,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
public static CallableMethod asCallableMethod(FunctionDescriptor fd) {
Method descriptor = erasedInvokeSignature(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()) {
result.setNeedsReceiver(fd);
}
@@ -63,7 +62,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
}
public Method invokeSignature(FunctionDescriptor fd) {
return state.getTypeMapper().mapSignature("invoke", fd);
return state.getTypeMapper().mapSignature("invoke", fd).getAsmMethod();
}
public GeneratedAnonymousClassDescriptor gen(JetFunctionLiteralExpression fun) {
@@ -100,7 +99,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
generateBridge(name, funDescriptor, fun, cv);
captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral());
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)
captureThis = false;
@@ -164,9 +163,9 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
Collections.<TypeParameterDescriptor>emptyList(),
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);
fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor);
fc.generateMethod(body, new JvmMethodSignature(invokeSignature(funDescriptor), null), funDescriptor);
return closureContext.outerWasUsed;
}
@@ -177,7 +176,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
if(bridge.getDescriptor().equals(delegate.getDescriptor()))
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()) {
mv.visitCode();
@@ -104,24 +104,24 @@ public abstract class CodegenContext {
return new ClassContext(descriptor, kind, this, typeMapper);
}
public CodegenContext intoAnonymousClass(@NotNull ObjectOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind) {
return new AnonymousClassContext(descriptor, kind, this, closure);
public CodegenContext intoAnonymousClass(@NotNull ObjectOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind, JetTypeMapper typeMapper) {
return new AnonymousClassContext(descriptor, kind, this, closure, typeMapper);
}
public MethodContext intoFunction(FunctionDescriptor descriptor) {
return new MethodContext(descriptor, getContextKind(), this);
}
public ConstructorContext intoConstructor(ConstructorDescriptor descriptor) {
public ConstructorContext intoConstructor(ConstructorDescriptor descriptor, JetTypeMapper typeMapper) {
if(descriptor == null) {
descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.<AnnotationDescriptor>emptyList(), true)
.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) {
return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName);
public ClosureContext intoClosure(FunctionDescriptor funDescriptor, ClassDescriptor classDescriptor, String internalClassName, ClosureCodegen closureCodegen, JetTypeMapper typeMapper) {
return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName, typeMapper);
}
public FrameMap prepareFrame(JetTypeMapper mapper) {
@@ -170,12 +170,12 @@ public abstract class CodegenContext {
return parentContext != null ? parentContext.lookupInContext(d, v, result) : null;
}
public Type enclosingClassType() {
public Type enclosingClassType(JetTypeMapper typeMapper) {
CodegenContext cur = getParentContext();
while(cur != null && !(cur.getContextDescriptor() instanceof ClassDescriptor))
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) {
@@ -290,8 +290,8 @@ public abstract class CodegenContext {
return getParentContext().lookupInContext(d, v, result);
}
public Type enclosingClassType() {
return getParentContext().enclosingClassType();
public Type enclosingClassType(JetTypeMapper typeMapper) {
return getParentContext().enclosingClassType(typeMapper);
}
@Override
@@ -305,10 +305,10 @@ public abstract class CodegenContext {
}
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);
final Type type = enclosingClassType();
final Type type = enclosingClassType(typeMapper);
outerExpression = type != null
? local1
: null;
@@ -323,7 +323,7 @@ public abstract class CodegenContext {
public ClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, JetTypeMapper typeMapper) {
super(contextType, contextKind, parentContext, null);
final Type type = enclosingClassType();
final Type type = enclosingClassType(typeMapper);
outerExpression = type != null
? StackValue.field(type, typeMapper.getFQName(contextType), "this$0", false)
: null;
@@ -341,10 +341,10 @@ public abstract class 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);
final Type type = enclosingClassType();
final Type type = enclosingClassType(typeMapper);
outerExpression = type != null
? StackValue.field(type, closure.state.getTypeMapper().mapType(contextType.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "this$0", false)
: null;
@@ -364,11 +364,11 @@ public abstract class CodegenContext {
public static class ClosureContext extends ReceiverContext {
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);
this.classDescriptor = classDescriptor;
final Type type = enclosingClassType();
final Type type = enclosingClassType(typeMapper);
outerExpression = type != null
? StackValue.field(type, internalClassName, "this$0", false)
: 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_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;
final InstructionAdapter v;
@@ -60,7 +57,29 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
private final CodegenContext context;
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,
FrameMap myMap,
@@ -225,11 +244,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override
public StackValue visitWhileExpression(JetWhileExpression expression, StackValue receiver) {
Label condition = new Label();
myContinueTargets.push(condition);
v.mark(condition);
Label end = continueLabel != null ? continueLabel : new Label();
myBreakTargets.push(end);
blockStackElements.push(new LoopBlockStackElement(end, condition));
Label savedContinueLabel = continueLabel;
continueLabel = condition;
@@ -243,8 +261,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
continueLabel = savedContinueLabel;
if(end != continueLabel)
v.mark(end);
myBreakTargets.pop();
myContinueTargets.pop();
blockStackElements.pop();
return StackValue.onStack(Type.VOID_TYPE);
}
@@ -253,10 +271,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
public StackValue visitDoWhileExpression(JetDoWhileExpression expression, StackValue receiver) {
Label condition = new Label();
v.mark(condition);
myContinueTargets.push(condition);
Label end = new Label();
myBreakTargets.push(end);
blockStackElements.push(new LoopBlockStackElement(end, condition));
gen(expression.getBody(), Type.VOID_TYPE);
@@ -265,8 +283,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.mark(end);
myBreakTargets.pop();
myContinueTargets.pop();
blockStackElements.pop();
return StackValue.onStack(Type.VOID_TYPE);
}
@@ -328,8 +345,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
Label begin = new Label();
myContinueTargets.push(begin);
myBreakTargets.push(end);
blockStackElements.push(new LoopBlockStackElement(end, begin));
v.mark(begin);
v.load(iteratorVar, asmIterType);
@@ -365,8 +381,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
//noinspection ConstantConditions
v.visitLocalVariable(loopParameter.getName(), asmParamType.getDescriptor(), null, begin, end, paramIndex);
myFrameMap.leaveTemp();
myBreakTargets.pop();
myContinueTargets.pop();
blockStackElements.pop();
}
private OwnerKind contextKind() {
@@ -398,8 +414,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
Label condition = new Label();
Label increment = new Label();
v.mark(condition);
myContinueTargets.push(increment);
myBreakTargets.push(end);
blockStackElements.push(new LoopBlockStackElement(end, increment));
generateCondition(asmParamType, end);
@@ -414,8 +430,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final int paramIndex = myFrameMap.leave(parameterDescriptor);
//noinspection ConstantConditions
v.visitLocalVariable(expression.getLoopParameter().getName(), asmParamType.getDescriptor(), null, condition, end, paramIndex);
myBreakTargets.pop();
myContinueTargets.pop();
blockStackElements.pop();
}
protected void generatePrologue() {
@@ -536,21 +552,51 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override
public StackValue visitBreakExpression(JetBreakExpression expression, StackValue receiver) {
JetSimpleNameExpression labelElement = expression.getTargetLabel();
Label label = labelElement == null ? myBreakTargets.peek() : null; // TODO:
v.goTo(label);
return StackValue.none();
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.breakLabel : null; // TODO:
v.goTo(label);
return StackValue.none();
}
else {
throw new UnsupportedOperationException();
}
}
throw new UnsupportedOperationException();
}
@Override
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);
return StackValue.none();
throw new UnsupportedOperationException();
}
private StackValue generateSingleBranchIf(StackValue condition, JetExpression expression, boolean inverse) {
@@ -763,12 +809,18 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
private void doFinallyOnReturnOrThrow() {
if(stackOfFinallyBlocks.size() > 0) {
JetTryExpression jetTryExpression = stackOfFinallyBlocks.remove(stackOfFinallyBlocks.size()-1);
//noinspection ConstantConditions
gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE);
doFinallyOnReturnOrThrow();
stackOfFinallyBlocks.add(jetTryExpression);
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;
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);
}
@@ -1034,7 +1086,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
}
if(!(containingDeclaration instanceof JavaNamespaceDescriptor) && !(containingDeclaration instanceof JavaClassDescriptor))
getter = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
getter = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION).getAsmMethod();
else
getter = null;
}
@@ -1043,10 +1095,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
setter = null;
}
else {
if(!(containingDeclaration instanceof JavaNamespaceDescriptor) && !(containingDeclaration instanceof JavaClassDescriptor))
setter = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
else
if(!(containingDeclaration instanceof JavaNamespaceDescriptor) && !(containingDeclaration instanceof JavaClassDescriptor)) {
JvmMethodSignature jvmMethodSignature = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
setter = jvmMethodSignature != null ? jvmMethodSignature.getAsmMethod() : null;
} else {
setter = null;
}
}
}
@@ -1119,7 +1173,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final CallableMethod callableMethod = (CallableMethod) callable;
invokeMethodWithArguments(callableMethod, expression, receiver);
final Type callReturnType = callableMethod.getSignature().getReturnType();
final Type callReturnType = callableMethod.getSignature().getAsmMethod().getReturnType();
return returnValueAsStackValue((FunctionDescriptor) fd, callReturnType);
}
else {
@@ -1478,7 +1532,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
pushTypeArguments(resolvedCall);
pushMethodArguments(resolvedCall, callableMethod.getValueParameterTypes());
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;
genToJVMStack(expression.getBaseExpression());
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 {
ClassDescriptor classDecl = (ClassDescriptor) constructorDescriptor.getContainingDeclaration();
receiver.put(receiver.type, v);
v.anew(type);
v.dup();
// TODO typechecker must verify that we're the outer class of the instance being created
//noinspection ConstantConditions
if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) {
if(!receiver.type.equals(Type.VOID_TYPE)) {
// 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();
if(!receiver.type.equals(Type.VOID_TYPE)) {
receiver.put(receiver.type, v);
}
CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION);
@@ -2128,7 +2169,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
else {
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> 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();
Type asmType;
Type[] argumentTypes = accessor.getSignature().getArgumentTypes();
Type[] argumentTypes = accessor.getSignature().getAsmMethod().getArgumentTypes();
int index = 0;
if(isGetter) {
Callable callable = resolveToCallable(getterDescriptor, false);
@@ -2158,7 +2199,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
index++;
}
}
asmType = accessor.getSignature().getReturnType();
asmType = accessor.getSignature().getAsmMethod().getReturnType();
}
else {
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.
*/
Label savedContinueLabel = continueLabel;
continueLabel = null;
JetFinallySection finallyBlock = expression.getFinallyBlock();
if(finallyBlock != null) {
stackOfFinallyBlocks.add(expression);
blockStackElements.push(new FinallyBlockStackElement(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();
if(finallyBlock != null) {
stackOfFinallyBlocks.remove(stackOfFinallyBlocks.size()-1);
blockStackElements.pop();
}
continueLabel = savedContinueLabel;
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) {
JetExpression expr = expression.getSubjectExpression();
final Type subjectType = expressionType(expr);
final Type resultType = expressionType(expression);
final int subjectLocal = myFrameMap.enterTemp(subjectType.getSize());
gen(expr, subjectType);
v.store(subjectLocal, subjectType);
Label end = new Label();
Label nextCondition = null;
boolean hasElse = false;
for (JetWhenEntry whenEntry : expression.getEntries()) {
if(whenEntry.isElse()) {
hasElse = true;
break;
}
}
Label nextCondition = null;
for (JetWhenEntry whenEntry : expression.getEntries()) {
if (nextCondition != null) {
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);
genToJVMStack(whenEntry.getExpression());
gen(whenEntry.getExpression(), resultType);
mark.dropTo();
v.goTo(end);
if (!whenEntry.isElse()) {
v.goTo(end);
}
}
if (!hasElse && nextCondition != null) {
v.mark(nextCondition);
@@ -2616,7 +2670,7 @@ If finally block is present, its last expression is the value of try expression.
v.mark(end);
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) {
@@ -6,13 +6,19 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.StdlibNames;
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.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
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.Set;
@@ -40,11 +46,11 @@ public class FunctionCodegen {
public void gen(JetNamedFunction f) {
final FunctionDescriptor functionDescriptor = state.getBindingContext().get(BindingContext.FUNCTION, f);
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);
}
public void generateMethod(JetDeclarationWithBody f, Method jvmMethod, FunctionDescriptor functionDescriptor) {
public void generateMethod(JetDeclarationWithBody f, JvmMethodSignature jvmMethod, FunctionDescriptor functionDescriptor) {
CodegenContext.MethodContext funContext = owner.intoFunction(functionDescriptor);
final JetExpression bodyExpression = f.getBodyExpression();
@@ -52,7 +58,7 @@ public class FunctionCodegen {
}
private void generatedMethod(JetExpression bodyExpressions,
Method jvmSignature,
JvmMethodSignature jvmSignature,
CodegenContext.MethodContext context,
FunctionDescriptor functionDescriptor, JetDeclarationWithBody fun)
{
@@ -73,45 +79,45 @@ public class FunctionCodegen {
boolean isAbstract = !isStatic && !(kind == OwnerKind.TRAIT_IMPL) && (bodyExpressions == null || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration()));
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()) {
int start = 0;
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()) {
av.visit("nullableReturnType", true);
av.visit(StdlibNames.JET_METHOD_NULLABLE_RETURN_TYPE_FIELD, true);
}
av.visitEnd();
}
if(kind == OwnerKind.TRAIT_IMPL) {
AnnotationVisitor av = mv.visitParameterAnnotation(start++, "Ljet/typeinfo/JetParameter;", true);
av.visit("value", "this$self");
AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_PARAMETER_DESCRIPTOR, true);
av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, "this$self");
av.visitEnd();
}
if(receiverParameter.exists()) {
AnnotationVisitor av = mv.visitParameterAnnotation(start++, "Ljet/typeinfo/JetParameter;", true);
av.visit("value", "this$receiver");
AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_PARAMETER_DESCRIPTOR, true);
av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, "this$receiver");
if(receiverParameter.getType().isNullable()) {
av.visit("nullable", true);
av.visit(StdlibNames.JET_PARAMETER_NULLABLE_FIELD, true);
}
av.visitEnd();
}
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
AnnotationVisitor av = mv.visitParameterAnnotation(start++, "Ljet/typeinfo/JetTypeParameter;", true);
av.visit("value", typeParameterDescriptor.getName());
AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_TYPE_PARAMETER_DESCRIPTOR, true);
av.visit(StdlibNames.JET_TYPE_PARAMETER_NAME_FIELD, typeParameterDescriptor.getName());
av.visitEnd();
}
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);
av.visit("name", parameterDescriptor.getName());
av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, parameterDescriptor.getName());
if(parameterDescriptor.hasDefaultValue()) {
av.visit("hasDefaultValue", true);
av.visit(StdlibNames.JET_PARAMETER_HAS_DEFAULT_FIELD, true);
}
if(parameterDescriptor.getOutType().isNullable()) {
av.visit("nullable", true);
av.visit(StdlibNames.JET_PARAMETER_NULLABLE_FIELD, true);
}
av.visitEnd();
}
@@ -124,9 +130,9 @@ public class FunctionCodegen {
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;
if(kind == OwnerKind.TRAIT_IMPL)
@@ -155,8 +161,8 @@ public class FunctionCodegen {
Type argType = argTypes[i];
iv.load(i + 1, argType);
}
iv.invokeinterface(dk.getOwnerClass(), jvmSignature.getName(), jvmSignature.getDescriptor());
iv.areturn(jvmSignature.getReturnType());
iv.invokeinterface(dk.getOwnerClass(), jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor());
iv.areturn(jvmSignature.getAsmMethod().getReturnType());
}
else {
for (ValueParameterDescriptor parameter : paramDescrs) {
@@ -209,11 +215,11 @@ public class FunctionCodegen {
mv.visitMaxs(0, 0);
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) {
@@ -379,7 +385,7 @@ public class FunctionCodegen {
Type type1 = state.getTypeMapper().mapType(overriddenFunction.getOriginal().getReturnType());
Type type2 = state.getTypeMapper().mapType(functionDescriptor.getReturnType());
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.
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.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);
ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration);
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) {
@@ -138,8 +138,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
FunctionDescriptor original = (FunctionDescriptor) entry.getKey();
Method method = typeMapper.mapSignature(bridge.getName(), bridge);
Method originalMethod = typeMapper.mapSignature(original.getName(), original);
Method method = typeMapper.mapSignature(bridge.getName(), bridge).getAsmMethod();
Method originalMethod = typeMapper.mapSignature(original.getName(), original).getAsmMethod();
Type[] argTypes = method.getArgumentTypes();
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 original = (PropertyDescriptor) entry.getKey();
Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION);
Method originalMethod = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION);
Method method = typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod();
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);
InstructionAdapter iv = null;
if (v.generateCode()) {
@@ -186,8 +186,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
mv.visitEnd();
}
method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION);
originalMethod = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION);
method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod();
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);
if (v.generateCode()) {
mv.visitCode();
@@ -267,7 +267,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass);
CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, typeMapper);
Method constructorMethod;
CallableMethod callableMethod;
@@ -283,11 +283,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
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 {
callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
constructorMethod = callableMethod.getSignature();
constructorMethod = callableMethod.getSignature().getAsmMethod();
}
ObjectOrClosureCodegen closure = context.closure;
@@ -471,7 +471,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
mv.visitMaxs(0, 0);
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) {
@@ -490,8 +490,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if(jetClass.isTrait()) {
int flags = Opcodes.ACC_PUBLIC; // TODO.
Method function = typeMapper.mapSignature(fun.getName(), fun);
Method functionOriginal = typeMapper.mapSignature(fun.getName(), fun.getOriginal());
Method function = typeMapper.mapSignature(fun.getName(), fun).getAsmMethod();
Method functionOriginal = typeMapper.mapSignature(fun.getName(), fun.getOriginal()).getAsmMethod();
final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null);
if (v.generateCode()) {
@@ -629,7 +629,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
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()) {
mv.visitCode();
@@ -5,6 +5,7 @@ import jet.JetObject;
import jet.typeinfo.TypeInfo;
import jet.typeinfo.TypeInfoProjection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
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.Type;
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.*;
@@ -82,7 +86,7 @@ public class JetTypeMapper {
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_DOUBLE_ITERATOR = Type.getObjectType("jet/DoubleIterator");
public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) {
this.standardLibrary = standardLibrary;
this.bindingContext = bindingContext;
@@ -151,13 +155,23 @@ public class JetTypeMapper {
}
@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 (signatureVisitor != null) {
signatureVisitor.visitBaseType('V');
}
return Type.VOID_TYPE;
}
if (jetType.equals(JetStandardClasses.getNullableNothingType())) {
if (signatureVisitor != null) {
visitAsmType(signatureVisitor, 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>>();
@@ -201,15 +215,28 @@ public class JetTypeMapper {
return name;
}
@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) {
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);
if(known != null)
return known;
if (known != null) {
return mapKnownAsmType(jetType, known, signatureVisitor, typeParameter);
}
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
if (standardLibrary.getArray().equals(descriptor)) {
@@ -217,10 +244,18 @@ public class JetTypeMapper {
throw new UnsupportedOperationException("arrays must have one type argument");
}
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());
else
} else {
return ARRAY_GENERIC_TYPE;
}
}
if (JetStandardClasses.getAny().equals(descriptor)) {
@@ -228,16 +263,64 @@ public class JetTypeMapper {
}
if (descriptor instanceof ClassDescriptor) {
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 (signatureVisitor != null) {
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) jetType.getConstructor().getDeclarationDescriptor();
signatureVisitor.visitTypeVariable(typeParameterDescriptor.getName());
}
return mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind);
}
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) {
if (type == JL_INTEGER_TYPE) {
@@ -292,6 +375,7 @@ public class JetTypeMapper {
return asmType;
}
private static final boolean DEBUG_SIGNATURE_WRITER = true;
public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, boolean superCall, OwnerKind kind) {
if(functionDescriptor == null)
@@ -299,7 +383,7 @@ public class JetTypeMapper {
final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration();
final List<Type> valueParameterTypes = new ArrayList<Type>();
Method descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, kind);
JvmMethodSignature descriptor = mapSignature(functionDescriptor.getOriginal(), true, valueParameterTypes, kind);
String owner;
int invokeOpcode;
ClassDescriptor thisClass;
@@ -326,7 +410,7 @@ public class JetTypeMapper {
? (superCall ? Opcodes.INVOKESTATIC : Opcodes.INVOKEINTERFACE)
: (superCall ? Opcodes.INVOKESPECIAL : Opcodes.INVOKEVIRTUAL);
if(isInterface && superCall) {
descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, OwnerKind.TRAIT_IMPL);
descriptor = mapSignature(functionDescriptor.getOriginal(), false, valueParameterTypes, OwnerKind.TRAIT_IMPL);
}
thisClass = (ClassDescriptor) functionParent;
}
@@ -343,7 +427,36 @@ public class JetTypeMapper {
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 JetType receiverType = !receiverTypeRef.exists() ? null : receiverTypeRef.getType();
final List<ValueParameterDescriptor> parameters = f.getValueParameters();
@@ -351,32 +464,36 @@ public class JetTypeMapper {
if(kind == OwnerKind.TRAIT_IMPL) {
ClassDescriptor containingDeclaration = (ClassDescriptor) f.getContainingDeclaration();
JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, bindingContext);
Type type = mapType(jetType);
Type type = mapType(jetType, signatureVisitor);
if(type.getInternalName().equals("java/lang/Object")) {
jetType = containingDeclaration.getDefaultType();
type = mapType(jetType);
type = mapType(jetType, signatureVisitor);
}
valueParameterTypes.add(type);
parameterTypes.add(type);
}
if (receiverType != null) {
parameterTypes.add(mapType(receiverType));
parameterTypes.add(mapType(receiverType, signatureVisitor != null ? signatureVisitor.visitParameterType() : null));
}
for (TypeParameterDescriptor parameterDescriptor : f.getTypeParameters()) {
if(parameterDescriptor.isReified()) {
parameterTypes.add(TYPE_TYPEINFO);
if (signatureVisitor != null) {
visitAsmType(signatureVisitor.visitParameterType(), TYPE_TYPEINFO);
}
}
}
for (ValueParameterDescriptor parameter : parameters) {
Type type = mapType(parameter.getOutType());
Type type = mapType(parameter.getOutType(), signatureVisitor != null ? signatureVisitor.visitParameterType() : null);
valueParameterTypes.add(type);
parameterTypes.add(type);
}
Type returnType = f instanceof ConstructorDescriptor ? Type.VOID_TYPE : mapReturnType(f.getReturnType());
return new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
Type returnType = f instanceof ConstructorDescriptor ? Type.VOID_TYPE : mapReturnType(f.getReturnType(), signatureVisitor != null ? signatureVisitor.visitReturnType() : null);
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 List<ValueParameterDescriptor> parameters = f.getValueParameters();
List<Type> parameterTypes = new ArrayList<Type>();
@@ -387,40 +504,12 @@ public class JetTypeMapper {
parameterTypes.add(mapType(parameter.getOutType()));
}
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('(');
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) {
public JvmMethodSignature mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
Type returnType = mapType(descriptor.getOutType());
String name = PropertyCodegen.getterName(descriptor.getName());
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();
if(inType == null)
return null;
@@ -468,10 +559,11 @@ public class JetTypeMapper {
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<Type> parameterTypes = new ArrayList<Type>();
ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
@@ -491,12 +583,13 @@ public class JetTypeMapper {
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) {
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();
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))
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());
MethodVisitor mv = v.newMethod(origin, flags, getterName, signature, null, null);
if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
@@ -179,7 +179,7 @@ public class PropertyCodegen {
if(isTrait && !(kind instanceof OwnerKind.DelegateKind))
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);
if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
mv.visitCode();
@@ -29,6 +29,6 @@ public class PsiMethodCall implements IntrinsicMethod {
List<JetExpression> arguments, StackValue receiver) {
final CallableMethod callableMethod = codegen.getTypeMapper().mapToCallableMethod(myMethod, false, OwnerKind.IMPLEMENTATION);
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.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.StdlibNames;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.plugin.JetFileType;
@@ -267,7 +268,7 @@ public class JavaDescriptorResolver {
return javaFacade.findClass(qualifiedName, javaSearchScope);
}
private PsiPackage findPackage(String qualifiedName) {
/*package*/ PsiPackage findPackage(String qualifiedName) {
return javaFacade.findPackage(qualifiedName);
}
@@ -354,13 +355,13 @@ public class JavaDescriptorResolver {
PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
attributes.toString();
if (annotation.getQualifiedName().equals("jet.typeinfo.JetParameter")) {
PsiLiteralExpression nameExpression = (PsiLiteralExpression) annotation.findAttributeValue("name");
if (annotation.getQualifiedName().equals(StdlibNames.JET_PARAMETER_CLASS)) {
PsiLiteralExpression nameExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_PARAMETER_NAME_FIELD);
if (nameExpression != null) {
name = (String) nameExpression.getValue();
}
PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue("nullable");
PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_PARAMETER_NULLABLE_FIELD);
if (nullableExpression != null) {
nullable = (Boolean) nullableExpression.getValue();
} else {
@@ -479,7 +480,7 @@ public class JavaDescriptorResolver {
DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor),
typeParameters,
semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptorImpl, parameters),
semanticServices.getTypeTransformer().transformToType(returnType),
semanticServices.getDescriptorResolver().makeReturnType(returnType, method),
Modality.convertFromFlags(method.hasModifierProperty(PsiModifier.ABSTRACT), !method.hasModifierProperty(PsiModifier.FINAL)),
resolveVisibilityFromPsiModifiers(method)
);
@@ -491,6 +492,30 @@ public class JavaDescriptorResolver {
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) {
//TODO report error
return modifierListOwner.hasModifierProperty(PsiModifier.PUBLIC) ? Visibility.PUBLIC :
@@ -1,10 +1,17 @@
package org.jetbrains.jet.lang.resolve.java;
import com.google.common.collect.Sets;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiPackage;
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 java.util.Collection;
import java.util.Collections;
import java.util.Set;
@@ -14,11 +21,13 @@ import java.util.Set;
public class JavaPackageScope extends JetScopeImpl {
private final JavaSemanticServices semanticServices;
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) {
this.semanticServices = semanticServices;
this.packagePrefix = packageFQN.isEmpty() ? "" : packageFQN + ".";
this.packageFQN = packageFQN;
this.containingDescriptor = containingDescriptor;
}
@@ -36,7 +45,7 @@ public class JavaPackageScope extends JetScopeImpl {
@Override
public Set<FunctionDescriptor> getFunctions(@NotNull String name) {
// TODO: what is GlobalSearchScope
PsiClass psiClass = semanticServices.getDescriptorResolver().javaFacade.findClass(packagePrefix + "namespace");
PsiClass psiClass = semanticServices.getDescriptorResolver().javaFacade.findClass(getQualifiedName("namespace"));
if (psiClass == null) {
return Collections.emptySet();
}
@@ -54,7 +63,35 @@ public class JavaPackageScope extends JetScopeImpl {
return containingDescriptor;
}
private String getQualifiedName(String name) {
return packagePrefix + name;
@NotNull
@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.WritableScopeImpl;
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.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lexer.JetTokens;
@@ -30,17 +33,19 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.*;
*/
public class TypeHierarchyResolver {
private final TopDownAnalysisContext context;
private final ImportsResolver importsResolver;
private LinkedList<MutableClassDescriptor> topologicalOrder;
public TypeHierarchyResolver(TopDownAnalysisContext context) {
this.context = context;
this.importsResolver = new ImportsResolver(context);
}
public void process(@NotNull JetScope outerScope, @NotNull NamespaceLike owner, @NotNull Collection<? extends JetDeclaration> declarations) {
collectNamespacesAndClassifiers(outerScope, outerScope, owner, declarations); // namespaceScopes, classes
processTypeImports();
importsResolver.processTypeImports();
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)
@@ -75,7 +80,6 @@ public class TypeHierarchyResolver {
WriteThroughScope namespaceScope = new WriteThroughScope(outerScope, namespaceDescriptor.getMemberScope(), new TraceBasedRedeclarationHandler(context.getTrace()));
namespaceScope.changeLockLevel(WritableScope.LockLevel.BOTH);
context.getConfiguration().addDefaultImports(context.getTrace(), namespaceScope);
context.getNamespaceScopes().put(namespace, namespaceScope);
context.getDeclaringScopes().put(namespace, outerScope);
@@ -233,82 +237,6 @@ public class TypeHierarchyResolver {
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() {
for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
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.calls.autocasts.AutoCastServiceImpl;
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.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
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 java.util.*;
@@ -241,6 +238,12 @@ public class CallResolver {
@NotNull JetType expectedType,
@NotNull final List<ResolutionTask<D>> prioritizedTasks, // high to low priority
@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() {
@Override
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);
if (results.isSuccess()) {
temporaryTrace.commit();
debugInfo.set(ResolutionDebugInfo.RESULT, results.getResult());
return results.getResult();
}
if (traceForFirstNonemptyCandidateSet == null && !task.getCandidates().isEmpty()) {
@@ -381,6 +387,9 @@ public class CallResolver {
if (traceForFirstNonemptyCandidateSet != null) {
traceForFirstNonemptyCandidateSet.commit();
if (resultsForFirstNonemptyCandidateSet.singleDescriptor()) {
debugInfo.set(ResolutionDebugInfo.RESULT, resultsForFirstNonemptyCandidateSet.getResult());
return resultsForFirstNonemptyCandidateSet.getResult();
}
}
@@ -420,7 +429,10 @@ public class CallResolver {
if (!candidate.getTypeParameters().isEmpty()) {
// 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()) {
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 {
public LoopInTypeVariableConstraintsException() {}
}
@@ -80,6 +79,8 @@ public class ConstraintSystemImpl implements ConstraintSystem {
public abstract boolean equate(TypeValue other);
}
//==========================================================================================================================================================
private class UnknownType extends TypeValue {
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);
}
else {
@@ -238,16 +239,18 @@ public class ConstraintSystemImpl implements ConstraintSystem {
private static final class TypeConstraintBuilderAdapter implements TypingConstraints {
private final TypingConstraints delegate;
private final ConstraintResolutionListener listener;
private TypeConstraintBuilderAdapter(TypingConstraints delegate) {
private TypeConstraintBuilderAdapter(TypingConstraints delegate, ConstraintResolutionListener listener) {
this.delegate = delegate;
this.listener = listener;
}
@Override
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) {
boolean result = delegate.assertEqualTypes(a, b, typeCheckingProcedure);
if (!result) {
println("-- Failed to equate " + a + " and " + b);
listener.error("-- Failed to equate " + a + " and " + b);
}
return result;
}
@@ -256,7 +259,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
boolean result = delegate.assertEqualTypeConstructors(a, b);
if (!result) {
println("-- Type constructors are not equal: " + a + " and " + b);
listener.error("-- Type constructors are not equal: " + a + " and " + b);
}
return result;
}
@@ -265,7 +268,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) {
boolean result = delegate.assertSubtype(subtype, supertype, typeCheckingProcedure);
if (!result) {
println("-- " + subtype + " can't be a subtype of " + supertype);
listener.error("-- " + subtype + " can't be a subtype of " + supertype);
}
return result;
}
@@ -274,60 +277,67 @@ public class ConstraintSystemImpl implements ConstraintSystem {
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
boolean result = delegate.noCorrespondingSupertype(subtype, supertype);
if (!result) {
println("-- " + subtype + " has no supertype corresponding to " + supertype);
listener.error("-- " + subtype + " has no supertype corresponding to " + supertype);
}
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 boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
return a.equals(b)
|| unknownTypes.containsKey(a.getDeclarationDescriptor())
|| unknownTypes.containsKey(b.getDeclarationDescriptor());
}
public ConstraintSystemImpl(ConstraintResolutionListener listener) {
this.listener = listener;
this.constraintExpander = createConstraintExpander();
}
@Override
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) {
TypeValue subtypeValue = getTypeValueFor(subtype);
TypeValue supertypeValue = getTypeValueFor(supertype);
private TypeCheckingProcedure createConstraintExpander() {
return 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);
if (someUnknown(subtypeValue, supertypeValue)) {
addSubtypingConstraintOnTypeValues(subtypeValue, supertypeValue);
return aValue.equate(bValue);
}
return true;
}
@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);
@Override
public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
return a.equals(b)
|| unknownTypes.containsKey(a.getDeclarationDescriptor())
|| unknownTypes.containsKey(b.getDeclarationDescriptor());
}
return someUnknown;
}
private boolean someUnknown(TypeValue subtypeValue, TypeValue supertypeValue) {
return subtypeValue instanceof UnknownType || supertypeValue instanceof UnknownType;
}
@Override
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
private TypeValue getTypeValueFor(@NotNull JetType type) {
@@ -368,7 +378,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
private void mergeUnknowns(@NotNull UnknownType a, @NotNull UnknownType b) {
System.err.println("!!!mergeUnknowns() is not implemented!!!");
listener.error("!!!mergeUnknowns() is not implemented!!!");
}
@Override
@@ -379,7 +389,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
private void addSubtypingConstraintOnTypeValues(TypeValue typeValueForLower, TypeValue typeValueForUpper) {
println(typeValueForLower + " :< " + typeValueForUpper);
listener.log("Constraint added: " + typeValueForLower + " :< " + typeValueForUpper);
if (typeValueForLower != typeValueForUpper) {
typeValueForLower.addUpperBound(typeValueForUpper);
typeValueForUpper.addLowerBound(typeValueForLower);
@@ -424,13 +434,11 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
for (UnknownType unknownType : unknownTypes.values()) {
println("Constraints for " + unknownType.getTypeParameterDescriptor());
printTypeValue(unknownType);
listener.constraintsForUnknown(unknownType.getTypeParameterDescriptor(), unknownType);
}
for (KnownType knownType : knownTypes.values()) {
println("Constraints for " + knownType.getType());
printTypeValue(knownType);
listener.constraintsForKnownType(knownType.getType(), knownType);
}
// Find inconsistencies
@@ -447,22 +455,11 @@ public class ConstraintSystemImpl implements ConstraintSystem {
// 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
println("====================================");
println("");
println("");
listener.done(solution, unknownTypes.keySet());
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) {
try {
KnownType resultingValue = typeValue.getValue();
@@ -471,33 +468,20 @@ public class ConstraintSystemImpl implements ConstraintSystem {
JetType boundingType = solution.getSubstitutor().substitute(upperBound.getValue().getType(), Variance.INVARIANT);
if (!typeChecker.isSubtypeOf(type, boundingType)) { // TODO
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()) {
JetType boundingType = solution.getSubstitutor().substitute(lowerBound.getValue().getType(), Variance.INVARIANT);
if (!typeChecker.isSubtypeOf(boundingType, 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) {
println("-------------------------------------------------------------------");
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);
}
}
listener.error("Loop detected");
solution.registerError("[TODO] Loop in constraints");
// e.printStackTrace();
}
}
@@ -544,9 +528,14 @@ public class ConstraintSystemImpl implements ConstraintSystem {
DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor();
if (declarationDescriptor instanceof TypeParameterDescriptor) {
TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor;
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;
}
@@ -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.addAll(writableWorker.getAllDescriptors());
allDescriptors.addAll(getWorkerScope().getAllDescriptors());
for (JetScope imported : getImports()) {
allDescriptors.addAll(imported.getAllDescriptors());
}
}
return allDescriptors;
}
@@ -1,12 +1,37 @@
package org.jetbrains.jet.util.slicedmap;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
/**
* @author abreslav
*/
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> 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 {
if(test1()) return "test1 failed"
if(test2()) return "test2 failed"
if(test3() != 2) return "test3 failed"
System.out?.println(test4())
if(test4() != 3) return "test4 failed"
if(test5() != 11) return "test5 failed"
if(test6() != 10) return "test6 failed"
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() {
myEnvironment = new JetCoreEnvironment(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"));
myEnvironment = JetTestUtils.createEnvironmentWithMockJdk(getTestRootDisposable());
}
protected void createEnvironmentWithFullJdk() {
@@ -1,5 +1,6 @@
package org.jetbrains.jet;
import com.intellij.openapi.Disposable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
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.java.AnalyzerFacade;
import org.jetbrains.jet.util.slicedmap.ReadOnlySlice;
import org.jetbrains.jet.util.slicedmap.SlicedMap;
import org.jetbrains.jet.util.slicedmap.WritableSlice;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
@@ -55,7 +59,7 @@ public class JetTestUtils {
@Override
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
if (slice == BindingContext.PROCESSED) return (V) Boolean.FALSE;
return null;
return SlicedMap.DO_NOTHING.get(slice, key);
}
@NotNull
@@ -127,4 +131,42 @@ public class JetTestUtils {
public static BindingContext analyzeNamespace(@NotNull JetNamespace namespace, @NotNull JetControlFlowDataTraceFactory 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;
import com.intellij.lang.ASTFactory;
import com.intellij.lang.LanguageASTFactory;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.Disposable;
@@ -35,9 +34,7 @@ import org.jetbrains.jet.plugin.JetLanguage;
import org.junit.Assert;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Set;
/**
@@ -65,8 +62,7 @@ public class ReadClassDataTest extends UsefulTestCase {
protected void setUp() throws Exception {
super.setUp();
tmpdir = new File("tmp/" + this.getClass().getSimpleName() + "." + this.getName());
rmrf(tmpdir);
mkdirs(tmpdir);
JetTestUtils.recreateDirectory(tmpdir);
}
@Override
@@ -74,27 +70,6 @@ public class ReadClassDataTest extends UsefulTestCase {
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() {
jetCoreEnvironment = new JetCoreEnvironment(myTestRootDisposable);
@@ -105,16 +80,14 @@ public class ReadClassDataTest extends UsefulTestCase {
@Override
public void runTest() throws Exception {
if (true) return;
createMockCoreEnvironment();
jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable);
LanguageASTFactory.INSTANCE.addExplicitExtension(JavaLanguage.INSTANCE, new JavaASTFactory());
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);
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());
Disposer.dispose(myTestRootDisposable);
createMockCoreEnvironment();
jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable);
jetCoreEnvironment.addToClasspath(tmpdir);
JetSemanticServices jetSemanticServices = JetSemanticServices.createSemanticServices(jetCoreEnvironment.getProject());
@@ -184,7 +156,8 @@ public class ReadClassDataTest extends UsefulTestCase {
for (int i = 0; i < a.getValueParameters().size(); ++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) {
@@ -286,4 +286,9 @@ public class ArrayGenTest extends CodegenTestCase {
// System.out.println(generateToText());
blackBox();
}
public void testNonNullArray() throws Exception {
blackBoxFile("classes/nonnullarray.jet");
System.out.println(generateToText());
}
}
@@ -1,5 +1,7 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.psi.JetNamespace;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@@ -216,6 +218,10 @@ public class ClassGenTest extends CodegenTestCase {
blackBoxFile("regressions/kt500.jet");
}
public void testKt694 () throws Exception {
// blackBoxFile("regressions/kt694.jet");
}
public void testKt285 () throws Exception {
// blackBoxFile("regressions/kt285.jet");
}
@@ -221,6 +221,16 @@ public class ControlStructuresTest extends CodegenTestCase {
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 {
blackBoxFile("controlStructures/quicksort.jet");
// 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.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Icons;
import com.intellij.util.PlatformIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lexer.JetTokens;
@@ -15,21 +15,21 @@ import javax.swing.*;
* @author yole
*/
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
public Icon getIcon(@NotNull PsiElement psiElement, int flags) {
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) {
return PsiTreeUtil.getParentOfType(psiElement, JetNamedDeclaration.class) instanceof JetClass
? Icons.METHOD_ICON
: Icons.FUNCTION_ICON;
? PlatformIcons.METHOD_ICON
: PlatformIcons.FUNCTION_ICON;
}
if (psiElement instanceof JetClass) {
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) {
JetEnumEntry enumEntry = (JetEnumEntry) jetClass;
if (enumEntry.getPrimaryConstructorParameterList() == null) {
@@ -42,13 +42,13 @@ public class JetIconProvider extends IconProvider {
if (((JetParameter) psiElement).getValOrVarNode() != null) {
JetParameterList parameterList = PsiTreeUtil.getParentOfType(psiElement, JetParameterList.class);
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) {
return Icons.PROPERTY_ICON;
return PlatformIcons.PROPERTY_ICON;
}
return null;
}
@@ -24,13 +24,23 @@ import java.util.Set;
/**
* @author abreslav
*/
public class WholeProjectAnalyzerFacade {
public static final Function<JetFile, Collection<JetDeclaration>> WHOLE_PROJECT_DECLARATION_PROVIDER = new Function<JetFile, Collection<JetDeclaration>>() {
public final class WholeProjectAnalyzerFacade {
/** 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
public Collection<JetDeclaration> fun(final JetFile rootFile) {
final Project project = rootFile.getProject();
final Set<JetDeclaration> namespaces = Sets.newLinkedHashSet();
ProjectRootManager rootManager = ProjectRootManager.getInstance(project);
final ProjectRootManager rootManager = ProjectRootManager.getInstance(project);
if (rootManager != null && !ApplicationManager.getApplication().isUnitTestMode()) {
VirtualFile[] contentRoots = rootManager.getContentRoots();
@@ -55,9 +65,9 @@ public class WholeProjectAnalyzerFacade {
}
};
@NotNull
public static BindingContext analyzeProjectWithCacheOnAFile(@NotNull JetFile file) {
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.ui.content.ContentFactory;
import com.intellij.util.Alarm;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
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.ResolvedValueArgument;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.plugin.JetFileType;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
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 java.awt.*;
import java.util.Map;
import static org.jetbrains.jet.lang.resolve.BindingContext.EXPRESSION_TYPE;
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo.*;
/*
* @author abreslav
@@ -121,19 +125,20 @@ public class ResolveToolwindow extends JPanel {
PsiElement currentElement = elementAtOffset;
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;
}
}
currentElement = currentElement.getParent();
PsiElement elementWithDebugInfo = findData(bindingContext, currentElement, RESOLUTION_DEBUG_INFO);
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) {
JetExpression parentExpression = (elementAtOffset instanceof JetExpression) ? (JetExpression) elementAtOffset
@@ -153,8 +158,70 @@ public class ResolveToolwindow extends JPanel {
}
}
private String renderCall(ResolvedCall<? extends CallableDescriptor> resolvedCall) {
StringBuilder builder = new StringBuilder();
@Nullable
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();
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() {
}
class A() : My<caret> {
class A() {
public fun test() {
val a : MyC<caret>
}
}
// EXIST: MyClass
// EXIST: MyClass
@@ -3,4 +3,4 @@ fun foo() {
}
// TODO: Move all keywords to absent
// EXPECT: fun, val, var, namespace
// EXIST: fun, val, var, namespace
@@ -1,8 +1,8 @@
<caret>
// EXPECT: 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
// EXPECT: do, when, trait, This
// EXPECT: import, where, by, get, set, abstract, enum, open, annotation, override, private
// EXPECT: public, internal, protected, catch, out, vararg, inline, finally, final, ref
// EXIST: namespace, as, type, class, this, super, val, var, fun, for, null, true
// EXIST: false, is, in, throw, return, break, continue, object, if, try, else, while
// EXIST: do, when, trait, This
// EXIST: import, where, by, get, set, abstract, enum, open, annotation, override, private
// EXIST: public, internal, protected, catch, out, vararg, inline, finally, final, ref
// ABSENT: ?in, new, extends, implements
@@ -23,7 +23,7 @@ public class JetBasicCompletionTest extends JetCompletionTestBase {
setName("testCompletionExecute");
}
public void testCompletionExecute() {
public void testCompletionExecute() throws Exception {
doTest();
}
@@ -2,70 +2,64 @@ package org.jetbrains.jet.completion;
import com.intellij.codeInsight.completion.CodeCompletionHandlerBase;
import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.codeInsight.completion.LightCompletionTestCase;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupEx;
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.jet.plugin.PluginTestCaseBase;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
/**
* @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);
type = (testName.startsWith("Smart")) ? CompletionType.SMART : CompletionType.BASIC;
configureByFile(testName + ".kt");
CompletionType completionType = (testName.startsWith("Smart")) ? CompletionType.SMART : CompletionType.BASIC;
new CodeCompletionHandlerBase(completionType, false, false, true).invokeCompletion(getProject(), getEditor());
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));
}
assertContainsItems(itemsShouldExist(getFile().getText()));
assertNotContainItems(itemsShouldAbsent(getFile().getText()));
}
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
private static List<String> itemsShouldExist(String fileText) {
private static String[] itemsShouldExist(String fileText) {
return findListWithPrefix("// EXIST:", fileText);
}
@NotNull
private static List<String> itemsShouldAbsent(String fileText) {
private static String[] itemsShouldAbsent(String fileText) {
return findListWithPrefix("// ABSENT:", fileText);
}
@NotNull
private static List<String> findListWithPrefix(String prefix, String fileText) {
private static String[] findListWithPrefix(String prefix, String fileText) {
ArrayList<String> result = new ArrayList<String>();
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
@@ -1,5 +1,6 @@
package org.jetbrains.jet.completion;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBuilder;
@@ -25,7 +26,7 @@ public class KeywordsCompletionTest extends JetCompletionTestBase {
setName("testCompletionExecute");
}
public void testCompletionExecute() {
public void testCompletionExecute() throws Exception {
doTest();
}
@@ -49,13 +50,14 @@ public class KeywordsCompletionTest extends JetCompletionTestBase {
PluginTestCaseBase.getTestDataPathBase(), "/completion/keywords/", false,
JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() {
@NotNull
@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);
}
}, suite);
return suite;
}
}
}