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