Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
+30
-5
@@ -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 :
|
||||
|
||||
+43
-6
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
@@ -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);
|
||||
}
|
||||
+71
-85
@@ -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);
|
||||
}
|
||||
}
|
||||
+75
@@ -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");
|
||||
}
|
||||
}
|
||||
+55
@@ -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());
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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 ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user