diff --git a/.gitignore b/.gitignore
index 1af2e47cf73..852cf881b6e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@ out
.idea/codeStyleSettings.xml
.idea/workspace.xml
tmp
+*TestMy.java
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 463eb8bb67f..9c559c5bba1 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -12,6 +12,7 @@
+
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java
index 59d472f16d7..83d535a52a1 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java
@@ -126,9 +126,7 @@ public abstract class ClassBodyCodegen {
}
mv.visitInsn(Opcodes.RETURN);
- mv.visitMaxs(0, 0);
-
- mv.visitEnd();
+ FunctionCodegen.endVisit(v, "static initializer", myClass);
}
}
}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java
index feced45f382..38e58aa2846 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java
@@ -147,8 +147,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
mv.visitLabel(ret);
mv.visitInsn(ARETURN);
- mv.visitMaxs(0,0);
- mv.visitEnd();
+ FunctionCodegen.endVisit(mv, "$getInstance", fun);
}
}
@@ -205,8 +204,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
iv.areturn(JetTypeMapper.TYPE_OBJECT);
- mv.visitMaxs(0, 0);
- mv.visitEnd();
+ FunctionCodegen.endVisit(mv, "bridge", fun);
}
}
@@ -286,8 +284,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
iv.visitInsn(RETURN);
- mv.visitMaxs(0, 0);
- mv.visitEnd();
+ FunctionCodegen.endVisit(iv, "constructor", fun);
}
return constructor;
}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CompilationException.java b/compiler/backend/src/org/jetbrains/jet/codegen/CompilationException.java
new file mode 100644
index 00000000000..84f336f74a5
--- /dev/null
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/CompilationException.java
@@ -0,0 +1,20 @@
+package org.jetbrains.jet.codegen;
+
+import com.intellij.psi.PsiElement;
+import org.jetbrains.jet.lang.psi.JetElement;
+
+/**
+* @author alex.tkachman
+*/
+public class CompilationException extends RuntimeException {
+ private PsiElement element;
+
+ CompilationException(String message, Throwable cause, PsiElement element) {
+ super(message, cause);
+ this.element = element;
+ }
+
+ public PsiElement getElement() {
+ return element;
+ }
+}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java
index 39101c75e48..8dafa6b2690 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java
@@ -130,7 +130,15 @@ public class ExpressionCodegen extends JetVisitor {
public StackValue genQualified(StackValue receiver, JetElement selector) {
markLineNumber(selector);
- return selector.accept(this, receiver);
+ try {
+ return selector.accept(this, receiver);
+ }
+ catch(CompilationException e) {
+ throw e;
+ }
+ catch (Throwable error) {
+ throw new CompilationException(error.getMessage(), error, selector);
+ }
}
public StackValue gen(JetElement expr) {
@@ -204,7 +212,7 @@ public class ExpressionCodegen extends JetVisitor {
JetExpression elseExpression = expression.getElse();
if (thenExpression == null && elseExpression == null) {
- throw new CompilationException();
+ throw new CompilationException("Both brunches of if/else are null", null, expression);
}
if (isEmptyExpression(thenExpression)) {
@@ -225,6 +233,9 @@ public class ExpressionCodegen extends JetVisitor {
condition.condJump(elseLabel, true, v); // == 0, i.e. false
Label end = continueLabel == null ? new Label() : continueLabel;
+
+ if(continueLabel != null)
+ asmType = Type.VOID_TYPE;
gen(thenExpression, asmType);
@@ -1126,7 +1137,7 @@ public class ExpressionCodegen extends JetVisitor {
ResolvedCall extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, callee);
if(resolvedCall == null) {
- throw new CompilationException("Cannot resolve: " + callee.getText());
+ throw new CompilationException("Cannot resolve: " + callee.getText(), null, expression);
}
receiver = StackValue.receiver(resolvedCall, receiver, this, null);
@@ -1403,7 +1414,7 @@ public class ExpressionCodegen extends JetVisitor {
return mask;
}
- private int pushMethodArguments(JetCallElement expression, List valueParameterTypes) {
+ public int pushMethodArguments(JetCallElement expression, List valueParameterTypes) {
ResolvedCall extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
if(resolvedCall != null) {
return pushMethodArguments(resolvedCall, valueParameterTypes);
@@ -2074,7 +2085,7 @@ public class ExpressionCodegen extends JetVisitor {
ResolvedCall extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, callee);
if(resolvedCall == null) {
assert callee != null;
- throw new CompilationException("Cannot resolve: " + callee.getText());
+ throw new CompilationException("Cannot resolve: " + callee.getText(), null, expression);
}
FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor();
@@ -2098,7 +2109,7 @@ public class ExpressionCodegen extends JetVisitor {
}
else {
if (args.size() != 1) {
- throw new CompilationException("primitive array constructor requires one argument");
+ throw new CompilationException("primitive array constructor requires one argument", null, expression);
}
}
@@ -2784,15 +2795,6 @@ If finally block is present, its last expression is the value of try expression.
v.athrow();
}
- private static class CompilationException extends RuntimeException {
- private CompilationException() {
- }
-
- private CompilationException(String message) {
- super(message);
- }
- }
-
@Override
public String toString() {
return context.getContextDescriptor().toString();
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java
index befdaf21a7e..c8c9f3dee79 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java
@@ -110,6 +110,7 @@ public class FunctionCodegen {
if(receiverParameter.getType().isNullable()) {
av.visit(StdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD, true);
}
+ av.visit(StdlibNames.JET_VALUE_PARAMETER_RECEIVER_FIELD, true);
av.visitEnd();
}
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
@@ -223,7 +224,7 @@ public class FunctionCodegen {
k += type.getSize();
}
- mv.visitMaxs(0, 0);
+ endVisit(mv, null, fun);
mv.visitEnd();
generateBridgeIfNeeded(owner, state, v, jvmSignature.getAsmMethod(), functionDescriptor, kind);
@@ -233,6 +234,16 @@ public class FunctionCodegen {
generateDefaultIfNeeded(context, state, v, jvmSignature.getAsmMethod(), functionDescriptor, kind);
}
+ public static void endVisit(MethodVisitor mv, String description, PsiElement method) {
+ try {
+ mv.visitMaxs(0, 0);
+ }
+ catch (Throwable t) {
+ throw new CompilationException("wrong code generated" + (description != null ? " for " + description : "") + t.getClass().getName() + " " + t.getMessage(), t, method);
+ }
+ mv.visitEnd();
+ }
+
static void generateBridgeIfNeeded(CodegenContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
Set extends FunctionDescriptor> overriddenFunctions = functionDescriptor.getOverriddenDescriptors();
if(kind != OwnerKind.TRAIT_IMPL) {
@@ -390,7 +401,7 @@ public class FunctionCodegen {
iv.areturn(jvmSignature.getReturnType());
- mv.visitMaxs(0, 0);
+ endVisit(mv, "default method", state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, functionDescriptor));
mv.visitEnd();
}
}
@@ -426,7 +437,7 @@ public class FunctionCodegen {
if(jvmSignature.getReturnType() == Type.VOID_TYPE)
iv.aconst(null);
iv.areturn(overriden.getReturnType());
- mv.visitMaxs(0, 0);
+ endVisit(mv, "bridge method", state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, functionDescriptor));
mv.visitEnd();
}
}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
index 77c65e1c4d4..852b12ac22e 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
@@ -198,8 +198,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.areturn(method.getReturnType());
- mv.visitMaxs(0,0);
- mv.visitEnd();
+ FunctionCodegen.endVisit(iv, "accessor", null);
}
}
else if(entry.getValue() instanceof PropertyDescriptor) {
@@ -222,8 +221,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.areturn(method.getReturnType());
- mv.visitMaxs(0,0);
- mv.visitEnd();
+ FunctionCodegen.endVisit(iv, "accessor", null);
}
method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod();
@@ -248,8 +246,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
iv.areturn(method.getReturnType());
- mv.visitMaxs(0,0);
- mv.visitEnd();
+ FunctionCodegen.endVisit(iv, "accessor", null);
}
}
else {
@@ -465,8 +462,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
outer.visitVarInsn(Opcodes.ALOAD, 0);
outer.visitFieldInsn(Opcodes.GETFIELD, classname, "this$0", outerType.getDescriptor());
outer.visitInsn(Opcodes.ARETURN);
- outer.visitMaxs(0, 0);
- outer.visitEnd();
+ FunctionCodegen.endVisit(outer, "getOuterObject", myClass);
}
if (CodegenUtil.requireTypeInfoConstructorArg(descriptor.getDefaultType()) && kind == OwnerKind.IMPLEMENTATION) {
@@ -518,8 +514,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateTraitMethods(codegen);
mv.visitInsn(Opcodes.RETURN);
- mv.visitMaxs(0, 0);
- mv.visitEnd();
+ FunctionCodegen.endVisit(mv, "constructor", myClass);
FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod, constructorDescriptor, OwnerKind.IMPLEMENTATION);
}
@@ -572,8 +567,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.checkcast(function.getReturnType());
}
iv.areturn(function.getReturnType());
- mv.visitMaxs(0, 0);
- mv.visitEnd();
+ FunctionCodegen.endVisit(iv, "trait method", bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, fun));
}
FunctionCodegen.generateBridgeIfNeeded(context, state, v, function, fun, kind);
@@ -708,8 +702,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
mv.visitInsn(Opcodes.RETURN);
- mv.visitMaxs(0, 0);
- mv.visitEnd();
+ FunctionCodegen.endVisit(mv, "constructor", null);
}
}
@@ -821,8 +814,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
iv.areturn(JetTypeMapper.TYPE_TYPEINFO);
- mv.visitMaxs(0, 0);
- mv.visitEnd();
+ FunctionCodegen.endVisit(iv, "getTypeInfo", myClass);
}
mv = v.newMethod(myClass, Opcodes.ACC_PROTECTED | Opcodes.ACC_FINAL, "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V", null, null);
@@ -834,8 +826,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.load(1, JetTypeMapper.TYPE_OBJECT);
iv.putfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
mv.visitInsn(Opcodes.RETURN);
- mv.visitMaxs(0, 0);
- mv.visitEnd();
+ FunctionCodegen.endVisit(iv, "$setTypeInfo", myClass);
}
}
}
@@ -853,8 +844,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
String owner = typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
v.getstatic(owner, "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
v.areturn(JetTypeMapper.TYPE_TYPEINFO);
- mv.visitMaxs(0, 0);
- mv.visitEnd();
+ FunctionCodegen.endVisit(v, "getTypeInfo", myClass);
}
}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java
index 0272124ec9b..ef2cef70364 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java
@@ -66,7 +66,6 @@ public class JetTypeMapper {
private final HashMap knowTypeNames = new HashMap();
private final HashMap knowTypes = new HashMap();
- public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1");
public static final Type TYPE_ITERATOR = Type.getObjectType("jet/Iterator");
public static final Type TYPE_INT_RANGE = Type.getObjectType("jet/IntRange");
public static final Type TYPE_SHARED_VAR = Type.getObjectType("jet/runtime/SharedVar$Object");
@@ -86,6 +85,8 @@ public class JetTypeMapper {
public static final Type TYPE_LONG_ITERATOR = Type.getObjectType("jet/LongIterator");
public static final Type TYPE_FLOAT_ITERATOR = Type.getObjectType("jet/FloatIterator");
public static final Type TYPE_DOUBLE_ITERATOR = Type.getObjectType("jet/DoubleIterator");
+ public static final Type TYPE_FUNCTION0 = Type.getObjectType("jet/Function0");
+ public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1");
public JetStandardLibrary getStandardLibrary() {
return standardLibrary;
@@ -557,7 +558,10 @@ public class JetTypeMapper {
}
}
- // "extends Object" seems to be not optional according to ClassFileFormat-Java5.pdf
+ // "extends Object" is optional according to ClassFileFormat-Java5.pdf
+ // but javac complaints to signature:
+ // Ljava/lang/Object;
+ // TODO: avoid writing java/lang/Object if interface list is not empty
}
signatureVisitor.writeClassBoundEnd();
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java
index 5e8b92a7849..78a768791e1 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java
@@ -62,8 +62,11 @@ public class NamespaceCodegen {
else if (declaration instanceof JetNamedFunction) {
try {
functionCodegen.gen((JetNamedFunction) declaration);
- } catch (Exception e) {
- throw new RuntimeException("Failed to generate function " + declaration.getName(), e);
+ } catch (CompilationException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ throw new CompilationException("Failed to generate function " + declaration.getName(), e, declaration);
}
}
else if (declaration instanceof JetClassOrObject) {
@@ -107,7 +110,7 @@ public class NamespaceCodegen {
}
mv.visitInsn(RETURN);
- mv.visitMaxs(0, 0);
+ FunctionCodegen.endVisit(mv, "static initializer for namespace", namespace);
mv.visitEnd();
}
}
@@ -134,8 +137,7 @@ public class NamespaceCodegen {
v.visitFieldInsn(PUTSTATIC, jvmClassName, fieldName, "Ljet/typeinfo/TypeInfo;");
v.visitLabel(end);
v.visitInsn(ARETURN);
- v.visitMaxs(0, 0);
- v.visitEnd();
+ FunctionCodegen.endVisit(v, "type info method", namespace);
}
}
}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java
index dc05e02b32d..2267922aeb7 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java
@@ -154,8 +154,7 @@ public class PropertyCodegen {
type.getDescriptor());
}
iv.areturn(type);
- mv.visitMaxs(0, 0);
- mv.visitEnd();
+ FunctionCodegen.endVisit(mv, "getter", origin);
}
}
@@ -207,7 +206,7 @@ public class PropertyCodegen {
}
iv.visitInsn(Opcodes.RETURN);
- mv.visitMaxs(0, 0);
+ FunctionCodegen.endVisit(mv, "setter", origin);
mv.visitEnd();
}
}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java
index 79374780086..893d9ce47b3 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java
@@ -20,6 +20,7 @@ import java.util.*;
/**
* @author yole
+ * @author alex.tkachman
*/
public class IntrinsicMethods {
private static final IntrinsicMethod UNARY_MINUS = new UnaryMinus();
@@ -89,6 +90,7 @@ public class IntrinsicMethods {
declareOverload(myStdLib.getLibraryScope().getFunctions("plus"), 1, new StringPlus());
declareOverload(myStdLib.getLibraryScope().getFunctions("Array"), 1, new NewArray());
declareOverload(myStdLib.getLibraryScope().getFunctions("sure"), 0, new Sure());
+ declareOverload(myStdLib.getLibraryScope().getFunctions("synchronized"), 1, new StupidSync());
declareIntrinsicFunction("ByteIterator", "next", 0, ITERATOR_NEXT);
declareIntrinsicFunction("ShortIterator", "next", 0, ITERATOR_NEXT);
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StupidSync.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StupidSync.java
new file mode 100644
index 00000000000..1e83272f26e
--- /dev/null
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StupidSync.java
@@ -0,0 +1,26 @@
+package org.jetbrains.jet.codegen.intrinsics;
+
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jet.codegen.ExpressionCodegen;
+import org.jetbrains.jet.codegen.JetTypeMapper;
+import org.jetbrains.jet.codegen.StackValue;
+import org.jetbrains.jet.lang.psi.JetCallExpression;
+import org.jetbrains.jet.lang.psi.JetExpression;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.InstructionAdapter;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class StupidSync implements IntrinsicMethod {
+ @Override
+ public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, @Nullable PsiElement element, @Nullable List arguments, StackValue receiver) {
+ receiver.put(receiver.type, v);
+ codegen.pushMethodArguments((JetCallExpression)element, Arrays.asList(JetTypeMapper.TYPE_FUNCTION0));
+ v.invokestatic("jet/runtime/Intrinsics", "stupidSync", "(Ljava/lang/Object;Ljet/Function0;)Ljava/lang/Object;");
+ StackValue.onStack(JetTypeMapper.TYPE_OBJECT).put(expectedType, v);
+ return StackValue.onStack(expectedType);
+ }
+}
diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java
index 88689127062..6948e7ac5fe 100644
--- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java
+++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java
@@ -9,6 +9,7 @@ import com.intellij.psi.*;
import com.intellij.psi.search.DelegatingGlobalSearchScope;
import com.intellij.psi.search.GlobalSearchScope;
import jet.typeinfo.TypeInfoVariance;
+import org.eclipse.jdt.internal.core.JavaModelManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
@@ -56,9 +57,38 @@ public class JavaDescriptorResolver {
return visitor.visitDeclarationDescriptor(this, data);
}
};
+
+ private enum TypeParameterDescriptorOrigin {
+ JAVA,
+ KOTLIN,
+ }
+
+ private static class TypeParameterDescriptorInitialization {
+ private final TypeParameterDescriptorOrigin origin;
+ private final TypeParameterDescriptor descriptor;
+ @Nullable
+ private final List upperBoundsForKotlin;
+ @Nullable
+ private final List lowerBoundsForKotlin;
+
+ private TypeParameterDescriptorInitialization(TypeParameterDescriptor descriptor) {
+ this.origin = TypeParameterDescriptorOrigin.JAVA;
+ this.descriptor = descriptor;
+ this.upperBoundsForKotlin = null;
+ this.lowerBoundsForKotlin = null;
+ }
+
+ private TypeParameterDescriptorInitialization(TypeParameterDescriptor descriptor,
+ List upperBoundsForKotlin, List lowerBoundsForKotlin) {
+ this.origin = TypeParameterDescriptorOrigin.KOTLIN;
+ this.descriptor = descriptor;
+ this.upperBoundsForKotlin = upperBoundsForKotlin;
+ this.lowerBoundsForKotlin = lowerBoundsForKotlin;
+ }
+ }
protected final Map classDescriptorCache = Maps.newHashMap();
- protected final Map typeParameterDescriptorCache = Maps.newHashMap();
+ protected final Map typeParameterDescriptorCache = Maps.newHashMap();
protected final Map methodDescriptorCache = Maps.newHashMap();
protected final Map fieldDescriptorCache = Maps.newHashMap();
protected final Map namespaceDescriptorCache = Maps.newHashMap();
@@ -145,11 +175,8 @@ public class JavaDescriptorResolver {
classDescriptorCache.put(psiClass.getQualifiedName(), classDescriptor);
classDescriptor.setUnsubstitutedMemberScope(new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, false));
- // TODO: initialize
- if (psiClass.getModifierList().findAnnotation(StdlibNames.JET_CLASS.getFqName()) == null) {
- // UGLY HACK (Andrey Breslav is not sure what did he mean)
- initializeTypeParameters(psiClass);
- }
+ // UGLY HACK (Andrey Breslav is not sure what did he mean)
+ initializeTypeParameters(psiClass);
supertypes.addAll(getSupertypes(psiClass));
if (psiClass.isInterface()) {
@@ -188,7 +215,11 @@ public class JavaDescriptorResolver {
classDescriptor,
Collections.emptyList(), // TODO
false);
- constructorDescriptor.initialize(typeParameters, resolveParameterDescriptors(constructorDescriptor, constructor.getParameterList().getParameters()), Modality.FINAL,
+ ValueParameterDescriptors valueParameterDescriptors = resolveParameterDescriptors(constructorDescriptor, constructor.getParameterList().getParameters());
+ if (valueParameterDescriptors.receiverType != null) {
+ throw new IllegalStateException();
+ }
+ constructorDescriptor.initialize(typeParameters, valueParameterDescriptors.descriptors, Modality.FINAL,
resolveVisibilityFromPsiModifiers(constructor));
constructorDescriptor.setReturnType(classDescriptor.getDefaultType());
classDescriptor.addConstructor(constructorDescriptor);
@@ -208,7 +239,7 @@ public class JavaDescriptorResolver {
if (attributeValue != null) {
String typeParametersString = (String) attributeValue.getValue();
if (typeParametersString != null) {
- return resolveClassTypeParametersFromJetSignature(typeParametersString, classDescriptor);
+ return resolveClassTypeParametersFromJetSignature(typeParametersString, psiClass, classDescriptor);
}
}
}
@@ -216,49 +247,107 @@ public class JavaDescriptorResolver {
return makeUninitializedTypeParameters(classDescriptor, psiClass.getTypeParameters());
}
+ @NotNull
+ private PsiTypeParameter getPsiTypeParameterByName(PsiTypeParameterListOwner clazz, String name) {
+ for (PsiTypeParameter typeParameter : clazz.getTypeParameters()) {
+ if (typeParameter.getName().equals(name)) {
+ return typeParameter;
+ }
+ }
+ throw new IllegalStateException("PsiTypeParameter '" + name + "' is not found");
+ }
+
+
+ // cache
+ protected ClassDescriptor javaLangObject;
+
+ @NotNull
+ private ClassDescriptor getJavaLangObject() {
+ if (javaLangObject == null) {
+ javaLangObject = resolveClass("java.lang.Object");
+ }
+ return javaLangObject;
+ }
+
+ private boolean isJavaLangObject(JetType type) {
+ return type.getConstructor().getDeclarationDescriptor() == getJavaLangObject();
+ }
+
+
+ private abstract class JetSignatureTypeParameterVisitor extends JetSignatureExceptionsAdapter {
+
+ private final DeclarationDescriptor containingDeclaration;
+ private final PsiTypeParameterListOwner psiOwner;
+ private final String name;
+ private final TypeInfoVariance variance;
+
+ protected JetSignatureTypeParameterVisitor(DeclarationDescriptor containingDeclaration, PsiTypeParameterListOwner psiOwner,
+ String name, TypeInfoVariance variance)
+ {
+ this.containingDeclaration = containingDeclaration;
+ this.psiOwner = psiOwner;
+ this.name = name;
+ this.variance = variance;
+ }
+
+ int index = 0;
+
+ List upperBounds = new ArrayList();
+ List lowerBounds = new ArrayList();
+
+ @Override
+ public JetSignatureVisitor visitClassBound() {
+ return new JetTypeJetSignatureReader(JavaDescriptorResolver.this, semanticServices.getJetSemanticServices().getStandardLibrary()) {
+ @Override
+ protected void done(@NotNull JetType jetType) {
+ if (isJavaLangObject(jetType)) {
+ return;
+ }
+ upperBounds.add(jetType);
+ }
+ };
+ }
+
+ @Override
+ public JetSignatureVisitor visitInterfaceBound() {
+ return new JetTypeJetSignatureReader(JavaDescriptorResolver.this, semanticServices.getJetSemanticServices().getStandardLibrary()) {
+ @Override
+ protected void done(@NotNull JetType jetType) {
+ upperBounds.add(jetType);
+ }
+ };
+ }
+
+ @Override
+ public void visitFormalTypeParameterEnd() {
+ TypeParameterDescriptor typeParameter = TypeParameterDescriptor.createForFurtherModification(
+ containingDeclaration,
+ Collections.emptyList(), // TODO: wrong
+ true, // TODO: wrong
+ JetSignatureUtils.translateVariance(variance),
+ name,
+ ++index);
+ PsiTypeParameter psiTypeParameter = getPsiTypeParameterByName(psiOwner, name);
+ typeParameterDescriptorCache.put(psiTypeParameter, new TypeParameterDescriptorInitialization(typeParameter, upperBounds, lowerBounds));
+ done(typeParameter);
+ }
+
+ protected abstract void done(TypeParameterDescriptor typeParameterDescriptor);
+ }
+
/**
* @see #resolveMethodTypeParametersFromJetSignature(String, FunctionDescriptor)
*/
- private List resolveClassTypeParametersFromJetSignature(String jetSignature, final JavaClassDescriptor classDescriptor) {
+ private List resolveClassTypeParametersFromJetSignature(String jetSignature, final PsiClass clazz, final JavaClassDescriptor classDescriptor) {
final List r = new ArrayList();
new JetSignatureReader(jetSignature).accept(new JetSignatureExceptionsAdapter() {
@Override
public JetSignatureVisitor visitFormalTypeParameter(final String name, final TypeInfoVariance variance) {
- return new JetSignatureExceptionsAdapter() {
- int index = 0;
-
+ return new JetSignatureTypeParameterVisitor(classDescriptor, clazz, name, variance) {
@Override
- public JetSignatureVisitor visitClassBound() {
- return new JetTypeJetSignatureReader(JavaDescriptorResolver.this, semanticServices.getJetSemanticServices().getStandardLibrary()) {
- @Override
- protected void done(@NotNull JetType jetType) {
- // TODO
- }
- };
+ protected void done(TypeParameterDescriptor typeParameterDescriptor) {
+ r.add(typeParameterDescriptor);
}
-
- @Override
- public JetSignatureVisitor visitInterfaceBound() {
- return new JetTypeJetSignatureReader(JavaDescriptorResolver.this, semanticServices.getJetSemanticServices().getStandardLibrary()) {
- @Override
- protected void done(@NotNull JetType jetType) {
- // TODO
- }
- };
- }
-
- @Override
- public void visitFormalTypeParameterEnd() {
- TypeParameterDescriptor typeParameter = TypeParameterDescriptor.createForFurtherModification(
- classDescriptor,
- Collections.emptyList(), // TODO: wrong
- true, // TODO: wrong
- JetSignatureUtils.translateVariance(variance),
- name,
- ++index);
- r.add(typeParameter);
- }
-
};
}
@@ -308,34 +397,49 @@ public class JavaDescriptorResolver {
psiTypeParameter.getName(),
psiTypeParameter.getIndex()
);
- typeParameterDescriptorCache.put(psiTypeParameter, typeParameterDescriptor);
+ typeParameterDescriptorCache.put(psiTypeParameter, new TypeParameterDescriptorInitialization(typeParameterDescriptor));
return typeParameterDescriptor;
}
- private void initializeTypeParameter(PsiTypeParameter typeParameter, TypeParameterDescriptor typeParameterDescriptor) {
- PsiClassType[] referencedTypes = typeParameter.getExtendsList().getReferencedTypes();
- if (referencedTypes.length == 0){
- typeParameterDescriptor.addUpperBound(JetStandardClasses.getNullableAnyType());
- }
- else if (referencedTypes.length == 1) {
- typeParameterDescriptor.addUpperBound(semanticServices.getTypeTransformer().transformToType(referencedTypes[0]));
- }
- else {
- for (PsiClassType referencedType : referencedTypes) {
- typeParameterDescriptor.addUpperBound(semanticServices.getTypeTransformer().transformToType(referencedType));
+ private void initializeTypeParameter(PsiTypeParameter typeParameter, TypeParameterDescriptorInitialization typeParameterDescriptorInitialization) {
+ TypeParameterDescriptor typeParameterDescriptor = typeParameterDescriptorInitialization.descriptor;
+ if (typeParameterDescriptorInitialization.origin == TypeParameterDescriptorOrigin.KOTLIN) {
+ List> upperBounds = typeParameterDescriptorInitialization.upperBoundsForKotlin;
+ if (upperBounds.size() == 0){
+ typeParameterDescriptor.addUpperBound(JetStandardClasses.getNullableAnyType());
+ } else {
+ for (JetType upperBound : typeParameterDescriptorInitialization.upperBoundsForKotlin) {
+ typeParameterDescriptor.addUpperBound(upperBound);
+ }
+ }
+
+ // TODO: lower bounds
+ } else {
+ PsiClassType[] referencedTypes = typeParameter.getExtendsList().getReferencedTypes();
+ if (referencedTypes.length == 0){
+ typeParameterDescriptor.addUpperBound(JetStandardClasses.getNullableAnyType());
+ }
+ else if (referencedTypes.length == 1) {
+ typeParameterDescriptor.addUpperBound(semanticServices.getTypeTransformer().transformToType(referencedTypes[0]));
+ }
+ else {
+ for (PsiClassType referencedType : referencedTypes) {
+ typeParameterDescriptor.addUpperBound(semanticServices.getTypeTransformer().transformToType(referencedType));
+ }
}
}
+ typeParameterDescriptor.setInitialized();
}
private void initializeTypeParameters(PsiTypeParameterListOwner typeParameterListOwner) {
for (PsiTypeParameter psiTypeParameter : typeParameterListOwner.getTypeParameters()) {
- initializeTypeParameter(psiTypeParameter, resolveTypeParameter(psiTypeParameter));
+ initializeTypeParameter(psiTypeParameter, resolveTypeParameterInitialization(psiTypeParameter));
}
}
@NotNull
- private TypeParameterDescriptor resolveTypeParameter(@NotNull DeclarationDescriptor containingDeclaration, @NotNull PsiTypeParameter psiTypeParameter) {
- TypeParameterDescriptor typeParameterDescriptor = typeParameterDescriptorCache.get(psiTypeParameter);
+ private TypeParameterDescriptorInitialization resolveTypeParameter(@NotNull DeclarationDescriptor containingDeclaration, @NotNull PsiTypeParameter psiTypeParameter) {
+ TypeParameterDescriptorInitialization typeParameterDescriptor = typeParameterDescriptorCache.get(psiTypeParameter);
assert typeParameterDescriptor != null : psiTypeParameter.getText();
return typeParameterDescriptor;
}
@@ -423,21 +527,71 @@ public class JavaDescriptorResolver {
semanticServices.getTrace().record(BindingContext.NAMESPACE, psiClass, namespaceDescriptor);
return namespaceDescriptor;
}
+
+ private static class ValueParameterDescriptors {
+ private final JetType receiverType;
+ private final List descriptors;
- public List resolveParameterDescriptors(DeclarationDescriptor containingDeclaration, PsiParameter[] parameters) {
- List result = new ArrayList();
- for (int i = 0, parametersLength = parameters.length; i < parametersLength; i++) {
- PsiParameter parameter = parameters[i];
- ValueParameterDescriptor valueParameterDescriptor = resolveParameterDescriptor(containingDeclaration, i, parameter);
- if (valueParameterDescriptor != null) {
- result.add(valueParameterDescriptor);
- }
+ private ValueParameterDescriptors(@Nullable JetType receiverType, List descriptors) {
+ this.receiverType = receiverType;
+ this.descriptors = descriptors;
}
- return result;
}
- @Nullable
- private ValueParameterDescriptor resolveParameterDescriptor(DeclarationDescriptor containingDeclaration, int i, PsiParameter parameter) {
+ public ValueParameterDescriptors resolveParameterDescriptors(DeclarationDescriptor containingDeclaration, PsiParameter[] parameters) {
+ List result = new ArrayList();
+ JetType receiverType = null;
+ for (int i = 0, parametersLength = parameters.length; i < parametersLength; i++) {
+ PsiParameter parameter = parameters[i];
+ JvmMethodParameterMeaning meaning = resolveParameterDescriptor(containingDeclaration, i, parameter);
+ if (meaning.kind == JvmMethodParameterKind.TYPE_INFO) {
+ // TODO
+ } else if (meaning.kind == JvmMethodParameterKind.REGULAR) {
+ result.add(meaning.valueParameterDescriptor);
+ } else if (meaning.kind == JvmMethodParameterKind.RECEIVER) {
+ if (receiverType != null) {
+ throw new IllegalStateException("more then one receiver");
+ }
+ receiverType = meaning.receiverType;
+ }
+ }
+ return new ValueParameterDescriptors(receiverType, result);
+ }
+
+ private enum JvmMethodParameterKind {
+ REGULAR,
+ RECEIVER,
+ TYPE_INFO,
+ }
+
+ private static class JvmMethodParameterMeaning {
+ private final JvmMethodParameterKind kind;
+ private final JetType receiverType;
+ private final ValueParameterDescriptor valueParameterDescriptor;
+ private final Object typeInfo;
+
+ private JvmMethodParameterMeaning(JvmMethodParameterKind kind, JetType receiverType, ValueParameterDescriptor valueParameterDescriptor, Object typeInfo) {
+ this.kind = kind;
+ this.receiverType = receiverType;
+ this.valueParameterDescriptor = valueParameterDescriptor;
+ this.typeInfo = typeInfo;
+ }
+
+ public static JvmMethodParameterMeaning receiver(@NotNull JetType receiverType) {
+ return new JvmMethodParameterMeaning(JvmMethodParameterKind.RECEIVER, receiverType, null, null);
+ }
+
+ public static JvmMethodParameterMeaning regular(@NotNull ValueParameterDescriptor valueParameterDescriptor) {
+ return new JvmMethodParameterMeaning(JvmMethodParameterKind.REGULAR, null, valueParameterDescriptor, null);
+ }
+
+ public static JvmMethodParameterMeaning typeInfo(@NotNull Object typeInfo) {
+ return new JvmMethodParameterMeaning(JvmMethodParameterKind.TYPE_INFO, null, null, typeInfo);
+ }
+ }
+
+ @NotNull
+ private JvmMethodParameterMeaning resolveParameterDescriptor(DeclarationDescriptor containingDeclaration, int i, PsiParameter parameter) {
PsiType psiType = parameter.getType();
JetType varargElementType;
@@ -453,13 +607,11 @@ public class JavaDescriptorResolver {
boolean nullable = true;
String typeFromAnnotation = null;
+ boolean receiver = false;
+
// TODO: must be very slow, make it lazy?
String name = parameter.getName() != null ? parameter.getName() : "p" + i;
for (PsiAnnotation annotation : parameter.getModifierList().getAnnotations()) {
- // TODO: softcode annotation name
-
- PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
- attributes.toString();
if (annotation.getQualifiedName().equals(StdlibNames.JET_VALUE_PARAMETER.getFqName())) {
PsiLiteralExpression nameExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_VALUE_PARAMETER_NAME_FIELD);
@@ -480,8 +632,16 @@ public class JavaDescriptorResolver {
if (signatureExpression != null) {
typeFromAnnotation = (String) signatureExpression.getValue();
}
+
+
+ PsiLiteralExpression receiverExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_VALUE_PARAMETER_RECEIVER_FIELD);
+ if (receiverExpression != null) {
+ receiver = true;
+ }
+
+
} else if (annotation.getQualifiedName().equals(StdlibNames.JET_TYPE_PARAMETER.getFqName())) {
- return null;
+ return JvmMethodParameterMeaning.typeInfo(new Object());
}
}
@@ -491,16 +651,20 @@ public class JavaDescriptorResolver {
} else {
outType = semanticServices.getTypeTransformer().transformToType(psiType);
}
- return new ValueParameterDescriptorImpl(
- containingDeclaration,
- i,
- Collections.emptyList(), // TODO
- name,
- null, // TODO : review
- changeNullable ? TypeUtils.makeNullableAsSpecified(outType, nullable) : outType,
- false,
- varargElementType
- );
+ if (receiver) {
+ return JvmMethodParameterMeaning.receiver(outType);
+ } else {
+ return JvmMethodParameterMeaning.regular(new ValueParameterDescriptorImpl(
+ containingDeclaration,
+ i,
+ Collections.emptyList(), // TODO
+ name,
+ null, // TODO : review
+ changeNullable ? TypeUtils.makeNullableAsSpecified(outType, nullable) : outType,
+ false,
+ varargElementType
+ ));
+ }
}
public VariableDescriptor resolveFieldToVariableDescriptor(DeclarationDescriptor containingDeclaration, PsiField field) {
@@ -592,12 +756,13 @@ public class JavaDescriptorResolver {
);
methodDescriptorCache.put(method, functionDescriptorImpl);
List typeParameters = resolveMethodTypeParameters(method, functionDescriptorImpl);
+ ValueParameterDescriptors valueParameterDescriptors = resolveParameterDescriptors(functionDescriptorImpl, parameters);
functionDescriptorImpl.initialize(
- null,
+ valueParameterDescriptors.receiverType,
DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor),
typeParameters,
- semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptorImpl, parameters),
- semanticServices.getDescriptorResolver().makeReturnType(returnType, method),
+ valueParameterDescriptors.descriptors,
+ makeReturnType(returnType, method),
Modality.convertFromFlags(method.hasModifierProperty(PsiModifier.ABSTRACT), !method.hasModifierProperty(PsiModifier.FINAL)),
resolveVisibilityFromPsiModifiers(method)
);
@@ -616,7 +781,9 @@ public class JavaDescriptorResolver {
if (attributeValue != null) {
String typeParametersString = (String) attributeValue.getValue();
if (typeParametersString != null) {
- return resolveMethodTypeParametersFromJetSignature(typeParametersString, functionDescriptorImpl);
+ List r = resolveMethodTypeParametersFromJetSignature(typeParametersString, method, functionDescriptorImpl);
+ initializeTypeParameters(method);
+ return r;
}
}
}
@@ -628,49 +795,21 @@ public class JavaDescriptorResolver {
}
/**
- * @see #resolveClassTypeParametersFromJetSignature(String, JavaClassDescriptor)
+ * @see #resolveClassTypeParametersFromJetSignature(String, com.intellij.psi.PsiClass, JavaClassDescriptor)
*/
- private List resolveMethodTypeParametersFromJetSignature(String jetSignature, final FunctionDescriptor functionDescriptor) {
+ private List resolveMethodTypeParametersFromJetSignature(String jetSignature, final PsiMethod method, final FunctionDescriptor functionDescriptor) {
final List r = new ArrayList();
new JetSignatureReader(jetSignature).acceptFormalTypeParametersOnly(new JetSignatureExceptionsAdapter() {
@Override
public JetSignatureVisitor visitFormalTypeParameter(final String name, final TypeInfoVariance variance) {
-
- return new JetSignatureExceptionsAdapter() {
- int index = 0;
-
+
+ return new JetSignatureTypeParameterVisitor(functionDescriptor, method, name, variance) {
@Override
- public JetSignatureVisitor visitClassBound() {
- return new JetTypeJetSignatureReader(JavaDescriptorResolver.this, semanticServices.getJetSemanticServices().getStandardLibrary()) {
- @Override
- protected void done(@NotNull JetType jetType) {
- // TODO
- }
- };
- }
-
- @Override
- public JetSignatureVisitor visitInterfaceBound() {
- return new JetTypeJetSignatureReader(JavaDescriptorResolver.this, semanticServices.getJetSemanticServices().getStandardLibrary()) {
- @Override
- protected void done(@NotNull JetType jetType) {
- // TODO
- }
- };
- }
-
- @Override
- public void visitFormalTypeParameterEnd() {
- TypeParameterDescriptor typeParameter = TypeParameterDescriptor.createForFurtherModification(
- functionDescriptor,
- Collections.emptyList(), // TODO: wrong
- true, // TODO: wrong
- JetSignatureUtils.translateVariance(variance),
- name,
- ++index);
- r.add(typeParameter);
+ protected void done(TypeParameterDescriptor typeParameterDescriptor) {
+ r.add(typeParameterDescriptor);
}
};
+
}
});
return r;
@@ -719,7 +858,8 @@ public class JavaDescriptorResolver {
(modifierListOwner.hasModifierProperty(PsiModifier.PROTECTED) ? Visibility.PROTECTED : Visibility.INTERNAL));
}
- public TypeParameterDescriptor resolveTypeParameter(PsiTypeParameter typeParameter) {
+ @NotNull
+ private TypeParameterDescriptorInitialization resolveTypeParameterInitialization(PsiTypeParameter typeParameter) {
PsiTypeParameterListOwner owner = typeParameter.getOwner();
if (owner instanceof PsiClass) {
PsiClass psiClass = (PsiClass) owner;
@@ -744,4 +884,8 @@ public class JavaDescriptorResolver {
}
throw new IllegalStateException("Unknown parent type: " + owner);
}
+
+ public TypeParameterDescriptor resolveTypeParameter(PsiTypeParameter typeParameter) {
+ return resolveTypeParameterInitialization(typeParameter).descriptor;
+ }
}
diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/StdlibNames.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/StdlibNames.java
index dd071b38631..285ffe54b3c 100644
--- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/StdlibNames.java
+++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/StdlibNames.java
@@ -13,6 +13,7 @@ public class StdlibNames {
public static final String JET_VALUE_PARAMETER_HAS_DEFAULT_VALUE_FIELD = "hasDefaultValue";
public static final String JET_VALUE_PARAMETER_NULLABLE_FIELD = "nullable";
public static final String JET_VALUE_PARAMETER_TYPE_FIELD = "type";
+ public static final String JET_VALUE_PARAMETER_RECEIVER_FIELD = "receiver";
public static final JvmClassName JET_TYPE_PARAMETER = new JvmClassName("jet.typeinfo.JetTypeParameter");
diff --git a/compiler/frontend/src/jet/Library.jet b/compiler/frontend/src/jet/Library.jet
index 580d1dd1a2b..c54b0d2c49e 100644
--- a/compiler/frontend/src/jet/Library.jet
+++ b/compiler/frontend/src/jet/Library.jet
@@ -34,6 +34,8 @@ namespace io {
fun readLine() : String?
}
+fun Any.synchronized(block : fun() : R) : R
+
fun Any?.identityEquals(other : Any?) : Boolean // = this === other
// Can't write a body due to a bootstrapping problem (see JET-74)
@@ -103,6 +105,38 @@ trait Iterable {
fun iterator() : Iterator
}
+trait ByteIterable : Iterable {
+ override fun iterator() : ByteIterator
+}
+
+trait ShortIterable : Iterable {
+ override fun iterator() : ShortIterator
+}
+
+trait IntIterable : Iterable {
+ override fun iterator() : IntIterator
+}
+
+trait LongIterable : Iterable {
+ override fun iterator() : LongIterator
+}
+
+trait FloatIterable : Iterable {
+ override fun iterator() : FloatIterator
+}
+
+trait DoubleIterable : Iterable {
+ override fun iterator() : DoubleIterator
+}
+
+trait BooleanIterable : Iterable {
+ override fun iterator() : BooleanIterator
+}
+
+trait CharIterable : Iterable {
+ override fun iterator() : CharIterator
+}
+
fun Array(val size : Int) : Array
class Array(val size : Int, init : fun(Int) : T) {
@@ -230,7 +264,7 @@ trait Range> {
fun contains(item : T) : Boolean
}
-class IntRange(val start : Int, size : Int, reversed : Boolean = false) : Range, Iterable {
+class IntRange(val start : Int, size : Int, reversed : Boolean = false) : Range, IntIterable {
fun iterator () : Iterator
fun contains (elem: Int) : Boolean
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java
index 1edf93c8743..bbd1e6899b9 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java
@@ -28,6 +28,7 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
int index) {
TypeParameterDescriptor typeParameterDescriptor = createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index);
typeParameterDescriptor.addUpperBound(JetStandardClasses.getDefaultBound());
+ typeParameterDescriptor.setInitialized();
return typeParameterDescriptor;
}
@@ -52,6 +53,8 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
private final boolean reified;
+ private boolean initialized = false;
+
private TypeParameterDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List annotations,
@@ -74,25 +77,61 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
upperBounds);
}
+ public void setInitialized() {
+ if (initialized) {
+ throw new IllegalStateException();
+ }
+ initialized = true;
+ }
+
+ private void checkInitialized() {
+ if (!initialized) {
+ throw new IllegalStateException();
+ }
+ }
+
+ private void checkUninitialized() {
+ if (initialized) {
+ throw new IllegalStateException();
+ }
+ }
+
public boolean isReified() {
+ checkInitialized();
return reified;
}
public Variance getVariance() {
+ checkInitialized();
return variance;
}
public void addUpperBound(@NotNull JetType bound) {
+ checkUninitialized();
+ doAddUpperBound(bound);
+ }
+
+ private void doAddUpperBound(JetType bound) {
upperBounds.add(bound); // TODO : Duplicates?
}
+ public void addDefaultUpperBound() {
+ checkUninitialized();
+
+ if (upperBounds.isEmpty()) {
+ doAddUpperBound(JetStandardClasses.getDefaultBound());
+ }
+ }
+
@NotNull
public Set getUpperBounds() {
+ checkInitialized();
return upperBounds;
}
@NotNull
public JetType getUpperBoundsAsType() {
+ checkInitialized();
if (upperBoundsAsType == null) {
assert upperBounds != null : "Upper bound list is null in " + getName();
assert upperBounds.size() > 0 : "Upper bound list is empty in " + getName();
@@ -106,11 +145,13 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
@NotNull
public Set getLowerBounds() {
+ //checkInitialized();
return Collections.singleton(JetStandardClasses.getNothingType());
}
@NotNull
public JetType getLowerBoundsAsType() {
+ checkInitialized();
return JetStandardClasses.getNothingType();
}
@@ -118,6 +159,7 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
@NotNull
@Override
public TypeConstructor getTypeConstructor() {
+ //checkInitialized();
return typeConstructor;
}
@@ -135,12 +177,14 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
@Override
public R accept(DeclarationDescriptorVisitor visitor, D data) {
+ checkInitialized();
return visitor.visitTypeParameterDescriptor(this, data);
}
@NotNull
@Override
public JetType getDefaultType() {
+ //checkInitialized();
if (defaultType == null) {
defaultType = new JetTypeImpl(
Collections.emptyList(),
@@ -159,6 +203,7 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
@Override
public JetType getClassObjectType() {
+ checkInitialized();
if (classObjectUpperBounds.isEmpty()) return null;
if (classObjectBoundsAsType == null) {
@@ -176,15 +221,19 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
}
public void addClassObjectBound(@NotNull JetType bound) {
+ checkUninitialized();
classObjectUpperBounds.add(bound); // TODO : Duplicates?
}
public int getIndex() {
+ checkInitialized();
return index;
}
@NotNull
public TypeParameterDescriptor copy(@NotNull DeclarationDescriptor newOwner) {
- return new TypeParameterDescriptor(newOwner, Lists.newArrayList(getAnnotations()), reified, variance, getName(), index);
+ TypeParameterDescriptor copy = new TypeParameterDescriptor(newOwner, Lists.newArrayList(getAnnotations()), reified, variance, getName(), index);
+ copy.initialized = this.initialized;
+ return copy;
}
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java
index c5df77d3682..740ff3ed692 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java
@@ -381,9 +381,9 @@ public class DescriptorResolver {
}
for (TypeParameterDescriptor parameter : parameters) {
- if (parameter.getUpperBounds().isEmpty()) {
- parameter.addUpperBound(JetStandardClasses.getDefaultBound());
- }
+ parameter.addDefaultUpperBound();
+
+ parameter.setInitialized();
if (JetStandardClasses.isNothing(parameter.getUpperBoundsAsType())) {
PsiElement nameIdentifier = typeParameters.get(parameter.getIndex()).getNameIdentifier();
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java
index 2401d6328e4..11d84cc5851 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java
@@ -19,6 +19,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
+import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.*;
@@ -348,7 +349,7 @@ public class CallResolver {
if (callElement instanceof JetBinaryExpression) {
JetBinaryExpression binaryExpression = (JetBinaryExpression) callElement;
JetSimpleNameExpression operationReference = binaryExpression.getOperationReference();
- String operationString = operationReference.getReferencedNameElementType() == JetTokens.IDENTIFIER ? operationReference.getText() : OperatorConventions.getNameForOperationSymbol(operationReference.getReferencedNameElementType());
+ String operationString = operationReference.getReferencedNameElementType() == JetTokens.IDENTIFIER ? operationReference.getText() : OperatorConventions.getNameForOperationSymbol((JetToken) operationReference.getReferencedNameElementType());
JetExpression right = binaryExpression.getRight();
if (right != null) {
trace.report(UNSAFE_INFIX_CALL.on(reference, binaryExpression.getLeft().getText(), operationString, right.getText()));
@@ -510,15 +511,6 @@ public class CallResolver {
}
else {
tracing.typeInferenceFailed(temporaryTrace, solution.getStatus());
-// // Substitute DONT_CARE types to make further type checking as tolerant as possible
-// D candidateWithDontCares = (D) candidate.substitute(TypeSubstitutor.makeConstantSubstitutor(candidate.getTypeParameters(), DONT_CARE));
-// if (candidateWithDontCares == null) {
-// candidateWithDontCares = (D) candidate.substitute(TypeSubstitutor.makeConstantSubstitutor(candidate.getTypeParameters(), Variance.INVARIANT, DONT_CARE));
-// }
-// if (!ErrorUtils.isErrorType(candidateWithDontCares.getReturnType())) {
-// // Returning an error type provokes overload resolution ambiguities that mask errors
-// candidateCall.setResultingDescriptor(candidateWithDontCares);
-// }
candidateCall.setStatus(OTHER_ERROR.combine(checkAllValueArguments(scope, tracing, task, candidateCall)));
}
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemWithPriorities.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemWithPriorities.java
index 3da752a9950..270e5804ff3 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemWithPriorities.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemWithPriorities.java
@@ -259,7 +259,7 @@ public class ConstraintSystemWithPriorities implements ConstraintSystem {
assert constraintQueue.isEmpty() || unsolvedUnknowns.isEmpty() : constraintQueue + " " + unsolvedUnknowns;
- for (TypeValue unknown : unsolvedUnknowns) {
+ for (TypeValue unknown : Sets.newLinkedHashSet(unsolvedUnknowns)) {
if (!computeValueFor(unknown)) {
listener.error("Not enough data to compute value for ", unknown);
solution.registerError("Not enough data to compute value for " + unknown + ". Please, specify type arguments explicitly");
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/DescriptorSubstitutor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/DescriptorSubstitutor.java
index b31f101c402..7101dfda584 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/types/DescriptorSubstitutor.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/DescriptorSubstitutor.java
@@ -44,6 +44,7 @@ public class DescriptorSubstitutor {
descriptor.getVariance(),
descriptor.getName(),
descriptor.getIndex());
+ substituted.setInitialized();
mutableSubstitution.put(descriptor.getTypeConstructor(), new TypeProjection(substituted.getDefaultType()));
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/OperatorConventions.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/OperatorConventions.java
index 570d75fb38b..2aea399ef4e 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/OperatorConventions.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/OperatorConventions.java
@@ -1,10 +1,11 @@
package org.jetbrains.jet.lang.types.expressions;
+import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
-import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.jet.lexer.JetTokens;
/**
@@ -12,6 +13,10 @@ import org.jetbrains.jet.lexer.JetTokens;
*/
public class OperatorConventions {
+ public static final String EQUALS = "equals";
+ public static final String COMPARE_TO = "compareTo";
+ public static final String CONTAINS = "contains";
+
private OperatorConventions() {}
public static final ImmutableSet NUMBER_CONVERSIONS = ImmutableSet.of(
@@ -23,7 +28,7 @@ public class OperatorConventions {
"int"
);
- public static final ImmutableMap UNARY_OPERATION_NAMES = ImmutableMap.builder()
+ public static final ImmutableBiMap UNARY_OPERATION_NAMES = ImmutableBiMap.builder()
.put(JetTokens.PLUSPLUS, "inc")
.put(JetTokens.MINUSMINUS, "dec")
.put(JetTokens.PLUS, "plus")
@@ -31,7 +36,7 @@ public class OperatorConventions {
.put(JetTokens.EXCL, "not")
.build();
- public static final ImmutableMap BINARY_OPERATION_NAMES = ImmutableMap.builder()
+ public static final ImmutableBiMap BINARY_OPERATION_NAMES = ImmutableBiMap.builder()
.put(JetTokens.MUL, "times")
.put(JetTokens.PLUS, "plus")
.put(JetTokens.MINUS, "minus")
@@ -41,11 +46,22 @@ public class OperatorConventions {
.put(JetTokens.RANGE, "rangeTo")
.build();
- public static final ImmutableSet COMPARISON_OPERATIONS = ImmutableSet.of(JetTokens.LT, JetTokens.GT, JetTokens.LTEQ, JetTokens.GTEQ);
- public static final ImmutableSet EQUALS_OPERATIONS = ImmutableSet.of(JetTokens.EQEQ, JetTokens.EXCLEQ);
+ public static final ImmutableSet NOT_OVERLOADABLE =
+ ImmutableSet.of(JetTokens.ANDAND, JetTokens.OROR, JetTokens.ELVIS);
+
+ public static final ImmutableSet INCREMENT_OPERATIONS =
+ ImmutableSet.of(JetTokens.PLUSPLUS, JetTokens.MINUSMINUS);
- public static final ImmutableSet IN_OPERATIONS = ImmutableSet.of(JetTokens.IN_KEYWORD, JetTokens.NOT_IN);
- public static final ImmutableMap ASSIGNMENT_OPERATIONS = ImmutableMap.builder()
+ public static final ImmutableSet COMPARISON_OPERATIONS =
+ ImmutableSet.of(JetTokens.LT, JetTokens.GT, JetTokens.LTEQ, JetTokens.GTEQ);
+
+ public static final ImmutableSet EQUALS_OPERATIONS =
+ ImmutableSet.of(JetTokens.EQEQ, JetTokens.EXCLEQ);
+
+ public static final ImmutableSet IN_OPERATIONS =
+ ImmutableSet.of(JetTokens.IN_KEYWORD, JetTokens.NOT_IN);
+
+ public static final ImmutableBiMap ASSIGNMENT_OPERATIONS = ImmutableBiMap.builder()
.put(JetTokens.MULTEQ, "timesAssign")
.put(JetTokens.DIVEQ, "divAssign")
.put(JetTokens.PERCEQ, "modAssign")
@@ -53,7 +69,7 @@ public class OperatorConventions {
.put(JetTokens.MINUSEQ, "minusAssign")
.build();
- public static final ImmutableMap ASSIGNMENT_OPERATION_COUNTERPARTS = ImmutableMap.builder()
+ public static final ImmutableMap ASSIGNMENT_OPERATION_COUNTERPARTS = ImmutableMap.builder()
.put(JetTokens.MULTEQ, JetTokens.MUL)
.put(JetTokens.DIVEQ, JetTokens.DIV)
.put(JetTokens.PERCEQ, JetTokens.PERC)
@@ -62,17 +78,16 @@ public class OperatorConventions {
.build();
@Nullable
- public static String getNameForOperationSymbol(@NotNull IElementType token) {
+ public static String getNameForOperationSymbol(@NotNull JetToken token) {
String name = UNARY_OPERATION_NAMES.get(token);
if (name != null) return name;
name = BINARY_OPERATION_NAMES.get(token);
if (name != null) return name;
name = ASSIGNMENT_OPERATIONS.get(token);
if (name != null) return name;
- if (COMPARISON_OPERATIONS.contains(token)) return "compareTo";
- if (EQUALS_OPERATIONS.contains(token)) return "equals";
- if (IN_OPERATIONS.contains(token)) return "contains";
+ if (COMPARISON_OPERATIONS.contains(token)) return COMPARE_TO;
+ if (EQUALS_OPERATIONS.contains(token)) return EQUALS;
+ if (IN_OPERATIONS.contains(token)) return CONTAINS;
return null;
- }
-
+ }
}
diff --git a/compiler/testData/codegen/controlStructures/ifInWhile.jet b/compiler/testData/codegen/controlStructures/ifInWhile.jet
new file mode 100644
index 00000000000..834c71f2b6f
--- /dev/null
+++ b/compiler/testData/codegen/controlStructures/ifInWhile.jet
@@ -0,0 +1,14 @@
+import java.lang.Runtime
+
+fun box() : String {
+ val processors = Runtime.getRuntime().sure().availableProcessors()
+ var threadNum = 1
+ while(threadNum <= 1024) {
+ System.out?.println(threadNum)
+ if(threadNum < 2 * processors)
+ threadNum += 1
+ else
+ threadNum *= 2
+ }
+ return "OK"
+}
diff --git a/compiler/testData/codegen/controlStructures/sync.jet b/compiler/testData/codegen/controlStructures/sync.jet
new file mode 100644
index 00000000000..408db40ca36
--- /dev/null
+++ b/compiler/testData/codegen/controlStructures/sync.jet
@@ -0,0 +1,33 @@
+import java.util.concurrent.*
+import java.util.concurrent.atomic.*
+
+fun thread(block: fun():Unit ) {
+ val thread = object: Thread() {
+ override fun run() {
+ block()
+ }
+ }
+ thread.start()
+}
+
+fun box() : String {
+ val ref = AtomicInteger()
+ val cdl = CountDownLatch(11)
+ for(i in 0..10) {
+ thread {
+ var current = 0
+ do {
+ current = ref.synchronized {
+ val v = ref.get() + 1
+ if(v < 100)
+ ref.set(v+1)
+ v
+ }
+ }
+ while(current < 100)
+ cdl.countDown()
+ }
+ }
+ cdl.await()
+ return if(ref.get() == 100) "OK" else ref.get().toString()
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/regressions/kt511.jet b/compiler/testData/codegen/regressions/kt511.jet
new file mode 100644
index 00000000000..a9bc915346c
--- /dev/null
+++ b/compiler/testData/codegen/regressions/kt511.jet
@@ -0,0 +1,16 @@
+namespace one_extends_base
+
+open class Base(name : T?) {
+ var myName : T?
+ {
+ $myName = name
+ }
+}
+open class One(name : T?, second : K?) : Base(name) {
+ var mySecond : K?
+ {
+ $mySecond = second
+ }
+}
+
+fun box() = if(One("ola", 0).myName == "ola") "OK" else "fail"
diff --git a/compiler/testData/codegen/regressions/kt772.jet b/compiler/testData/codegen/regressions/kt772.jet
new file mode 100644
index 00000000000..6cad8d6ae03
--- /dev/null
+++ b/compiler/testData/codegen/regressions/kt772.jet
@@ -0,0 +1,25 @@
+namespace demo2
+
+fun print(o : Any?) {}
+
+fun test(i : Int) {
+ var monthString : String? = ""
+ 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"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/regressions/kt779.jet b/compiler/testData/codegen/regressions/kt779.jet
new file mode 100644
index 00000000000..12aa290eb67
--- /dev/null
+++ b/compiler/testData/codegen/regressions/kt779.jet
@@ -0,0 +1,3 @@
+val Array.length : Int get() = this.size
+
+fun box() = if(Array(10, {1}).length == 10) "OK" else "fail"
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/tests/regressions/kt860.jet b/compiler/testData/diagnostics/tests/regressions/kt860.jet
new file mode 100644
index 00000000000..d8acf4fad50
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/regressions/kt860.jet
@@ -0,0 +1,14 @@
+// KT-860 ConcurrentModificationException in frontend
+// +JDK
+
+namespace std.util
+
+import java.util.*
+
+fun > Iterator.to(container: U) : U {
+ while(hasNext)
+ container.add(next())
+ return container
+}
+
+inline fun Iterator.toArrayList() = to(ArrayList())
diff --git a/compiler/testData/readClass/class/ClassParamUpperClassBound.kt b/compiler/testData/readClass/class/ClassParamUpperClassBound.kt
new file mode 100644
index 00000000000..4867fac53bc
--- /dev/null
+++ b/compiler/testData/readClass/class/ClassParamUpperClassBound.kt
@@ -0,0 +1,3 @@
+namespace test
+
+class Clock
diff --git a/compiler/testData/readClass/class/ClassParamUpperClassInterfaceBound.kt b/compiler/testData/readClass/class/ClassParamUpperClassInterfaceBound.kt
new file mode 100644
index 00000000000..992a24af91b
--- /dev/null
+++ b/compiler/testData/readClass/class/ClassParamUpperClassInterfaceBound.kt
@@ -0,0 +1,3 @@
+namespace test
+
+class Clock where A : java.lang.Number, A : java.lang.CharSequence
diff --git a/compiler/testData/readClass/class/ClassParamUpperInterfaceBound.kt b/compiler/testData/readClass/class/ClassParamUpperInterfaceBound.kt
new file mode 100644
index 00000000000..8f05d69017f
--- /dev/null
+++ b/compiler/testData/readClass/class/ClassParamUpperInterfaceBound.kt
@@ -0,0 +1,3 @@
+namespace test
+
+class Clock
diff --git a/compiler/testData/readClass/class/ClassParamUpperInterfaceClassBound.kt b/compiler/testData/readClass/class/ClassParamUpperInterfaceClassBound.kt
new file mode 100644
index 00000000000..8e8170d48c5
--- /dev/null
+++ b/compiler/testData/readClass/class/ClassParamUpperInterfaceClassBound.kt
@@ -0,0 +1,3 @@
+namespace test
+
+class Clock where A : java.lang.CharSequence, A : java.lang.Number
diff --git a/compiler/testData/readClass/class/Trait.kt b/compiler/testData/readClass/class/Trait.kt
new file mode 100644
index 00000000000..b984afa34b0
--- /dev/null
+++ b/compiler/testData/readClass/class/Trait.kt
@@ -0,0 +1,3 @@
+namespace test
+
+trait Trtrtr
diff --git a/compiler/testData/readClass/fun/ExtFun.kt b/compiler/testData/readClass/fun/ExtFun.kt
new file mode 100644
index 00000000000..f894ea8a631
--- /dev/null
+++ b/compiler/testData/readClass/fun/ExtFun.kt
@@ -0,0 +1,3 @@
+namespace test
+
+fun Int.shuffle() = 1
diff --git a/compiler/testData/readClass/fun/FunParamUpperClassBound.kt b/compiler/testData/readClass/fun/FunParamUpperClassBound.kt
new file mode 100644
index 00000000000..3a4c68fed8f
--- /dev/null
+++ b/compiler/testData/readClass/fun/FunParamUpperClassBound.kt
@@ -0,0 +1,3 @@
+namespace test
+
+fun uno() = 1
diff --git a/compiler/testData/readClass/fun/FunParamUpperClassInterfaceBound.kt b/compiler/testData/readClass/fun/FunParamUpperClassInterfaceBound.kt
new file mode 100644
index 00000000000..678d5a2967a
--- /dev/null
+++ b/compiler/testData/readClass/fun/FunParamUpperClassInterfaceBound.kt
@@ -0,0 +1,3 @@
+namespace test
+
+fun tres() where A : java.lang.Number, A : java.lang.CharSequence = 1
diff --git a/compiler/testData/readClass/fun/FunParamUpperInterfaceBound.kt b/compiler/testData/readClass/fun/FunParamUpperInterfaceBound.kt
new file mode 100644
index 00000000000..00a6e0432cb
--- /dev/null
+++ b/compiler/testData/readClass/fun/FunParamUpperInterfaceBound.kt
@@ -0,0 +1,3 @@
+namespace test
+
+fun dos() = 1
diff --git a/compiler/testData/readClass/fun/FunParamUpperInterfaceClassBound.kt b/compiler/testData/readClass/fun/FunParamUpperInterfaceClassBound.kt
new file mode 100644
index 00000000000..6effa87aba9
--- /dev/null
+++ b/compiler/testData/readClass/fun/FunParamUpperInterfaceClassBound.kt
@@ -0,0 +1,3 @@
+namespace test
+
+fun cuatro() where A : java.lang.CharSequence, A : java.lang.Number = 1
diff --git a/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java b/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java
index 3121cfc8315..8bb9e576bc6 100644
--- a/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java
+++ b/compiler/tests/org/jetbrains/jet/CompileJavaAgainstKotlinTest.java
@@ -1,13 +1,10 @@
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;
@@ -70,8 +67,6 @@ public class CompileJavaAgainstKotlinTest extends UsefulTestCase {
protected void runTest() throws Throwable {
jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable);
- LanguageASTFactory.INSTANCE.addExplicitExtension(JavaLanguage.INSTANCE, new JavaASTFactory());
-
String text = FileUtil.loadFile(ktFile);
diff --git a/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java b/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java
index 83e7f8d13c4..04458738032 100644
--- a/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java
+++ b/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java
@@ -1,14 +1,11 @@
package org.jetbrains.jet;
-import com.intellij.lang.LanguageASTFactory;
-import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.Disposable;
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;
@@ -18,15 +15,7 @@ import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.compiler.CompileEnvironment;
import org.jetbrains.jet.lang.JetSemanticServices;
-import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
-import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
-import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
-import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorImpl;
-import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
-import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
-import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
-import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
-import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
+import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -34,8 +23,8 @@ import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
+import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
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.Variance;
import org.jetbrains.jet.plugin.JetLanguage;
@@ -44,6 +33,7 @@ import org.junit.Assert;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -92,9 +82,6 @@ public class ReadClassDataTest extends UsefulTestCase {
public void runTest() throws Exception {
jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable);
- LanguageASTFactory.INSTANCE.addExplicitExtension(JavaLanguage.INSTANCE, new JavaASTFactory());
-
-
String text = FileUtil.loadFile(testFile);
LightVirtualFile virtualFile = new LightVirtualFile(testFile.getName(), JetLanguage.INSTANCE, text);
@@ -159,7 +146,8 @@ public class ReadClassDataTest extends UsefulTestCase {
private String serializeContent(ClassDescriptor klass) {
StringBuilder sb = new StringBuilder();
- sb.append("class ");
+ serialize(klass.getKind(), sb);
+ sb.append(" ");
serialize(klass, sb);
@@ -174,9 +162,6 @@ public class ReadClassDataTest extends UsefulTestCase {
sb.append(" {\n");
- if (false) {
- // TODO: for some reason I don't understand scope of ClassDescriptor came from source is empty
-
List typeArguments = new ArrayList();
for (TypeParameterDescriptor param : klass.getTypeConstructor().getParameters()) {
typeArguments.add(new TypeProjection(Variance.INVARIANT, param.getDefaultType()));
@@ -184,15 +169,37 @@ public class ReadClassDataTest extends UsefulTestCase {
JetScope memberScope = klass.getMemberScope(typeArguments);
for (DeclarationDescriptor member : memberScope.getAllDescriptors()) {
+ // TODO
+ if (member.getName().equals("equals") || member.getName().equals("hashCode")
+ || member.getName().equals("wait") || member.getName().equals("notify") || member.getName().equals("notifyAll")
+ || member.getName().equals("toString") || member.getName().equals("getClass")
+ || member.getName().equals("clone") || member.getName().equals("finalize")
+ || member.getName().equals("getTypeInfo") || member.getName().equals("$setTypeInfo") || member.getName().equals("$typeInfo")
+ )
+ {
+ continue;
+ }
+ sb.append(" ");
serialize(member, sb);
sb.append("\n");
}
- }
-
sb.append("}\n");
return sb.toString();
}
+
+ private void serialize(ClassKind kind, StringBuilder sb) {
+ switch (kind) {
+ case CLASS:
+ sb.append("class");
+ break;
+ case TRAIT:
+ sb.append("trait");
+ break;
+ default:
+ throw new IllegalStateException();
+ }
+ }
private void compareFunctions(@NotNull FunctionDescriptor a, @NotNull FunctionDescriptor b) {
@@ -220,6 +227,12 @@ public class ReadClassDataTest extends UsefulTestCase {
serializeCommaSeparated(fun.getTypeParameters(), sb);
sb.append(">");
}
+
+ if (fun.getReceiverParameter().exists()) {
+ serialize(fun.getReceiverParameter(), sb);
+ sb.append(".");
+ }
+
sb.append(fun.getName());
sb.append("(");
serializeCommaSeparated(fun.getValueParameters(), sb);
@@ -227,6 +240,21 @@ public class ReadClassDataTest extends UsefulTestCase {
serialize(fun.getReturnType(), sb);
}
+ private void serialize(ExtensionReceiver extensionReceiver, StringBuilder sb) {
+ serialize(extensionReceiver.getType(), sb);
+ }
+
+ private void serialize(PropertyDescriptor prop, StringBuilder sb) {
+ if (prop.isVar()) {
+ sb.append("var ");
+ } else {
+ sb.append("val ");
+ }
+ sb.append(prop.getName());
+ sb.append(": ");
+ serialize(prop.getOutType(), sb);
+ }
+
private void serialize(ValueParameterDescriptor valueParameter, StringBuilder sb) {
sb.append(valueParameter.getName());
sb.append(": ");
@@ -274,16 +302,20 @@ public class ReadClassDataTest extends UsefulTestCase {
}
private void serializeCommaSeparated(List> list, StringBuilder sb) {
+ serializeSeparated(list, sb, ", ");
+ }
+
+ private void serializeSeparated(List> list, StringBuilder sb, String sep) {
boolean first = true;
for (Object o : list) {
if (!first) {
- sb.append(", ");
+ sb.append(sep);
}
serialize(o, sb);
first = false;
}
}
-
+
private Method getMethodToSerialize(Object o) {
// TODO: cache
for (Method method : ReadClassDataTest.class.getDeclaredMethods()) {
@@ -311,6 +343,10 @@ public class ReadClassDataTest extends UsefulTestCase {
Method method = getMethodToSerialize(o);
invoke(method, this, o, sb);
}
+
+ private void serialize(String s, StringBuilder sb) {
+ sb.append(s);
+ }
private void serialize(ModuleDescriptor module, StringBuilder sb) {
// nop
@@ -331,11 +367,20 @@ public class ReadClassDataTest extends UsefulTestCase {
sb.append(".");
sb.append(ns.getName());
}
-
+
private void serialize(TypeParameterDescriptor param, StringBuilder sb) {
serialize(param.getVariance(), sb);
sb.append(param.getName());
- // TODO: serialize bounds
+ if (!param.getUpperBounds().isEmpty()) {
+ sb.append(" : ");
+ List list = new ArrayList();
+ for (JetType upper : param.getUpperBounds()) {
+ list.add(serialize(upper));
+ }
+ Collections.sort(list);
+ serializeSeparated(list, sb, " & "); // TODO: use where
+ }
+ // TODO: lower bounds
}
diff --git a/compiler/tests/org/jetbrains/jet/codegen/ArrayGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ArrayGenTest.java
index 5de65ac38f6..f14c34e279d 100644
--- a/compiler/tests/org/jetbrains/jet/codegen/ArrayGenTest.java
+++ b/compiler/tests/org/jetbrains/jet/codegen/ArrayGenTest.java
@@ -12,6 +12,11 @@ public class ArrayGenTest extends CodegenTestCase {
// System.out.println(generateToText());
}
+ public void testKt779 () throws Exception {
+ blackBoxFile("regressions/kt779.jet");
+// System.out.println(generateToText());
+ }
+
public void testCreateMultiInt () throws Exception {
loadText("fun foo() = Array> (5, { Array(it, {239}) })");
Method foo = generateFunction();
diff --git a/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java b/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java
index b6f0f1b3ad5..2869aa145b4 100644
--- a/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java
+++ b/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java
@@ -231,8 +231,25 @@ public class ControlStructuresTest extends CodegenTestCase {
// System.out.println(generateToText());
}
+ public void testKt772() throws Exception {
+ blackBoxFile("regressions/kt772.jet");
+// System.out.println(generateToText());
+ }
+
public void testQuicksort() throws Exception {
blackBoxFile("controlStructures/quicksort.jet");
+// System.out.println(generateToText());
+ }
+
+ public void testSynchronized() throws Exception {
+ createEnvironmentWithFullJdk();
+ blackBoxFile("controlStructures/sync.jet");
+// System.out.println(generateToText());
+ }
+
+ public void testIfInWhile() throws Exception {
+ createEnvironmentWithFullJdk();
+ blackBoxFile("controlStructures/ifInWhile.jet");
// System.out.println(generateToText());
}
}
diff --git a/compiler/tests/org/jetbrains/jet/codegen/TypeInfoTest.java b/compiler/tests/org/jetbrains/jet/codegen/TypeInfoTest.java
index b2396c96af6..3949cf9b8c6 100644
--- a/compiler/tests/org/jetbrains/jet/codegen/TypeInfoTest.java
+++ b/compiler/tests/org/jetbrains/jet/codegen/TypeInfoTest.java
@@ -138,6 +138,11 @@ public class TypeInfoTest extends CodegenTestCase {
// System.out.println(generateToText());
}
+ public void testKt511() throws Exception {
+ blackBoxFile("regressions/kt511.jet");
+// System.out.println(generateToText());
+ }
+
public void testInner() throws Exception {
blackBoxFile("typeInfo/inner.jet");
System.out.println(generateToText());
diff --git a/examples/src/benchmarks/LockPerf.kt b/examples/src/benchmarks/LockPerf.kt
index c7a61eda5ed..2937c59dfd1 100644
--- a/examples/src/benchmarks/LockPerf.kt
+++ b/examples/src/benchmarks/LockPerf.kt
@@ -1,20 +1,13 @@
namespace lockperformance
+import std.io.*
+import std.util.*
+import std.concurrent.*
+
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 Int.latch(op: fun CountDownLatch.() : T) : T {
val cdl = CountDownLatch(this)
val res = cdl.op()
@@ -22,41 +15,37 @@ fun Int.latch(op: fun CountDownLatch.() : T) : T {
return res
}
-fun Int.times(action: fun Int.()) {
- for(i in 0..this-1)
- action()
-}
-
fun main(args: Array) {
val processors = Runtime.getRuntime().sure().availableProcessors()
var threadNum = 1
while(threadNum <= 1024) {
val counter = AtomicInteger()
- val start = System.currentTimeMillis()
- threadNum.latch{
- val lock = ReentrantLock()
- threadNum.times {
- thread {
- while(true) {
- lock.lock()
- try {
- if (counter.get() == 100000000) {
- countDown();
- break;
- } else {
- counter.incrementAndGet();
+ val duration = measureTimeMillis {
+ threadNum.latch{
+ val lock = ReentrantLock()
+ for(i in 0..threadNum-1) {
+ thread {
+ while(true) {
+ lock.lock()
+ try {
+ if (counter.get() == 100000000) {
+ countDown();
+ break;
+ } else {
+ counter.incrementAndGet();
+ }
+ }
+ finally {
+ lock.unlock()
}
- }
- finally {
- lock.unlock()
}
}
}
}
}
- System.out?.println(threadNum.toString() + " " + (System.currentTimeMillis() - start));
+ println(threadNum.toString() + " " + duration)
if(threadNum < 2 * processors)
threadNum = threadNum + 1
diff --git a/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java b/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java
index 21dea6ed517..766868d3fc8 100644
--- a/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java
+++ b/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java
@@ -16,10 +16,7 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.util.Chunk;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.jet.codegen.ClassBuilderFactory;
-import org.jetbrains.jet.codegen.ClassFileFactory;
-import org.jetbrains.jet.codegen.CompilationErrorHandler;
-import org.jetbrains.jet.codegen.GenerationState;
+import org.jetbrains.jet.codegen.*;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.JetFile;
@@ -102,7 +99,12 @@ public class JetCompiler implements TranslatingCompiler {
generationState.compileCorrectNamespaces(bindingContext, namespaces, new CompilationErrorHandler() {
@Override
public void reportException(Throwable exception, String fileUrl) {
- compileContext.addMessage(CompilerMessageCategory.WARNING, exception.getClass().getCanonicalName() + ": " + exception.getMessage(), fileUrl, 0, 0);
+ if(exception instanceof CompilationException) {
+ report((CompilationException) exception, compileContext);
+ }
+ else {
+ compileContext.addMessage(CompilerMessageCategory.ERROR, exception.getClass().getCanonicalName() + ": " + exception.getMessage(), fileUrl, 0, 0);
+ }
}
});
///////////
@@ -175,6 +177,29 @@ public class JetCompiler implements TranslatingCompiler {
}
}
+ private void report(CompilationException diagnostic, CompileContext compileContext) {
+ PsiFile psiFile = diagnostic.getElement().getContainingFile();
+ TextRange textRange = diagnostic.getElement().getTextRange();
+ Document document = psiFile.getViewProvider().getDocument();
+ int line;
+ int col;
+ if (document != null) {
+ line = document.getLineNumber(textRange.getStartOffset());
+ col = textRange.getStartOffset() - document.getLineStartOffset(line) + 1;
+ }
+ else {
+ line = -1;
+ col = -1;
+ }
+ VirtualFile virtualFile = psiFile.getVirtualFile();
+ if (virtualFile == null) {
+ compileContext.addMessage(ERROR, "[Internal Error] No virtual file for PsiFile. Diagnostic: " + diagnostic.getMessage(), "", -1, -1);
+ }
+ else {
+ compileContext.addMessage(ERROR, diagnostic.getMessage(), virtualFile.getUrl(), line + 1, col);
+ }
+ }
+
// private static class ModuleCompileState {
// private final GenerationState state;
// private final CompileContext compileContext;
diff --git a/idea/src/org/jetbrains/jet/plugin/compiler/WholeProjectAnalyzerFacade.java b/idea/src/org/jetbrains/jet/plugin/compiler/WholeProjectAnalyzerFacade.java
index ec99fa7d3df..b858df279df 100644
--- a/idea/src/org/jetbrains/jet/plugin/compiler/WholeProjectAnalyzerFacade.java
+++ b/idea/src/org/jetbrains/jet/plugin/compiler/WholeProjectAnalyzerFacade.java
@@ -1,7 +1,6 @@
package org.jetbrains.jet.plugin.compiler;
import com.google.common.collect.Sets;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.ex.CompilerPathsEx;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
@@ -41,7 +40,7 @@ public final class WholeProjectAnalyzerFacade {
final Set namespaces = Sets.newLinkedHashSet();
final ProjectRootManager rootManager = ProjectRootManager.getInstance(project);
- if (rootManager != null && !ApplicationManager.getApplication().isUnitTestMode()) {
+ if (rootManager != null /* && !ApplicationManager.getApplication().isUnitTestMode() */) {
VirtualFile[] contentRoots = rootManager.getContentRoots();
CompilerPathsEx.visitFiles(contentRoots, new CompilerPathsEx.FileVisitor() {
@@ -57,7 +56,6 @@ public final class WholeProjectAnalyzerFacade {
}
}
});
-
}
namespaces.add(rootFile.getRootNamespace());
diff --git a/idea/testData/quickfix/autoImports/afterKotlinImport.kt b/idea/testData/quickfix/autoImports/afterKotlinImport.kt
new file mode 100644
index 00000000000..e6c19003945
--- /dev/null
+++ b/idea/testData/quickfix/autoImports/afterKotlinImport.kt
@@ -0,0 +1,7 @@
+// "Import Class" "true"
+
+import TestData.TestSample
+
+fun test() {
+ val a = TestSample
+}
\ No newline at end of file
diff --git a/idea/testData/quickfix/autoImports/beforeKotlinImport.Data.Sample.kt b/idea/testData/quickfix/autoImports/beforeKotlinImport.Data.Sample.kt
new file mode 100644
index 00000000000..24ab2e94d15
--- /dev/null
+++ b/idea/testData/quickfix/autoImports/beforeKotlinImport.Data.Sample.kt
@@ -0,0 +1,3 @@
+namespace TestData
+
+class TestSample() {}
\ No newline at end of file
diff --git a/idea/testData/quickfix/autoImports/beforeKotlinImport.Main.kt b/idea/testData/quickfix/autoImports/beforeKotlinImport.Main.kt
new file mode 100644
index 00000000000..9136601298a
--- /dev/null
+++ b/idea/testData/quickfix/autoImports/beforeKotlinImport.Main.kt
@@ -0,0 +1,5 @@
+// "Import Class" "true"
+
+fun test() {
+ val a = TestSample
+}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/JetPsiCheckerMultifileTest.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/JetPsiCheckerMultifileTest.java
new file mode 100644
index 00000000000..9a2714ca055
--- /dev/null
+++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/JetPsiCheckerMultifileTest.java
@@ -0,0 +1,226 @@
+package org.jetbrains.jet.plugin.quickfix;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase;
+import com.intellij.codeInsight.daemon.impl.HighlightInfo;
+import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInsight.intention.impl.ShowIntentionActionsHandler;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.util.Pair;
+import com.intellij.rt.execution.junit.FileComparisonFailure;
+import com.intellij.util.ui.UIUtil;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jet.JetTestCaseBuilder;
+import org.jetbrains.jet.plugin.PluginTestCaseBase;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.*;
+
+/**
+ * @author Nikolay Krasko
+ */
+public class JetPsiCheckerMultifileTest extends DaemonAnalyzerTestCase {
+
+ public final static String MAIN_SUBSTRING = ".Main";
+ public final static String DATA_SUBSTRING = ".Data";
+
+ private final String dataPath;
+ private final String name;
+
+ public JetPsiCheckerMultifileTest(String dataPath, String name) {
+ this.dataPath = dataPath;
+ this.name = name;
+
+ setName("testRun");
+ }
+
+ protected static boolean shouldBeAvailableAfterExecution() {
+ return false;
+ }
+
+ public void testRun() throws Exception {
+ configureByFiles(null, getFileNames(getTestFiles()).toArray(new String[1]));
+ doTest();
+ }
+
+ public void doTest() {
+ CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
+ @Override
+ public void run() {
+ try {
+ final Pair pair = LightQuickFixTestCase.parseActionHint(getFile(), loadFile(getFile().getName()));
+ final String text = pair.getFirst();
+
+ final boolean actionShouldBeAvailable = pair.getSecond();
+
+ doAction(text, actionShouldBeAvailable, getTestDataPath());
+ }
+ catch (FileComparisonFailure e){
+ throw e;
+ }
+ catch (Throwable e) {
+ e.printStackTrace();
+ fail(getTestName(true));
+ }
+ }
+ }, "", "");
+ }
+
+ @SuppressWarnings({"HardCodedStringLiteral"})
+ public void doAction(final String text, final boolean actionShouldBeAvailable, final String testFullPath)
+ throws Exception {
+ IntentionAction action = LightQuickFixTestCase.findActionWithText(getAvailableActions(), text);
+ if (action == null) {
+ if (actionShouldBeAvailable) {
+ List actions = getAvailableActions();
+ List texts = new ArrayList();
+ for (IntentionAction intentionAction : actions) {
+ texts.add(intentionAction.getText());
+ }
+ Collection infos = doHighlighting();
+ fail("Action with text '" + text + "' is not available in test " + testFullPath + "\n" +
+ "Available actions (" + texts.size() + "): " + texts + "\n" +
+ actions + "\n" +
+ "Infos:" + infos);
+ }
+ }
+ else {
+ if (!actionShouldBeAvailable) {
+ fail("Action '" + text + "' is available (but must not) in test " + testFullPath);
+ }
+
+ ShowIntentionActionsHandler.chooseActionAndInvoke(getFile(), getEditor(), action, action.getText());
+
+ UIUtil.dispatchAllInvocationEvents();
+
+ if (!shouldBeAvailableAfterExecution()) {
+ final IntentionAction afterAction = LightQuickFixTestCase.findActionWithText(getAvailableActions(), text);
+
+ if (afterAction != null) {
+ fail("Action '" + text + "' is still available after its invocation in test " + testFullPath);
+ }
+ }
+
+ checkResultByFile(name.replace("before", "after").replace(MAIN_SUBSTRING, "") + ".kt");
+ }
+ }
+
+ protected List getTestFiles() {
+ File dir = new File(getTestDataPath());
+
+ assertTrue("Main file should contain .Main. substring", name.contains(MAIN_SUBSTRING));
+ final String testPrefix = name.replace(MAIN_SUBSTRING, "");
+
+ // Files of single test
+ FilenameFilter resultFilter = new FilenameFilter() {
+ @Override
+ public boolean accept(File file, String s) {
+ return s.contains(testPrefix) && !s.contains("after");
+ }
+ };
+
+ List allTestFiles = Arrays.asList(dir.listFiles(resultFilter));
+
+ final Collection mainFiles = Collections2.filter(allTestFiles, new Predicate() {
+ @Override
+ public boolean apply(@Nullable File file) {
+ return file != null && file.getName().contains(MAIN_SUBSTRING);
+ }
+ });
+
+ assertTrue("No main file for test", mainFiles.size() > 0);
+ assertTrue("Too many main files for the test", mainFiles.size() <= 1);
+
+ final Collection dataFiles = Collections2.filter(allTestFiles, new Predicate() {
+ @Override
+ public boolean apply(@Nullable File file) {
+ return file != null && file.getName().contains(DATA_SUBSTRING);
+ }
+ });
+
+ final ArrayList fileResult = new ArrayList(allTestFiles);
+ fileResult.addAll(dataFiles);
+
+ return fileResult;
+ }
+
+ protected static List getFileNames(List files) {
+ return Lists.newArrayList(Collections2.transform(files, new Function() {
+ @Override
+ public String apply(File file) {
+ return file.getName();
+ }
+ }));
+ }
+
+ protected List getAvailableActions() {
+ doHighlighting();
+ return LightQuickFixTestCase.getAvailableActions(getEditor(), getFile());
+ }
+
+ @Override
+ public String getName() {
+ return "test" + name.replaceFirst(name.substring(0, 1), name.substring(0, 1).toUpperCase());
+ }
+
+ @Override
+ protected String getTestDataPath() {
+ return PluginTestCaseBase.getTestDataPathBase() + "/quickfix/" + dataPath + "/";
+ }
+
+ @Override
+ protected Sdk getTestProjectJdk() {
+ return PluginTestCaseBase.jdkFromIdeaHome();
+ }
+
+ public static boolean isMultiFileName(String fileName) {
+ return fileName.contains(MAIN_SUBSTRING) || fileName.contains(DATA_SUBSTRING);
+ }
+
+ public static boolean isMainFile(String fileName) {
+ return fileName.contains(MAIN_SUBSTRING);
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+
+ FilenameFilter multifileFileNameFilter = new FilenameFilter() {
+ @Override
+ public boolean accept(File file, String s) {
+ return s.startsWith("before") && JetPsiCheckerMultifileTest.isMainFile(s);
+ }
+ };
+
+ JetTestCaseBuilder.NamedTestFactory multiFileNamedTestFactory = new JetTestCaseBuilder.NamedTestFactory() {
+ @NotNull
+ @Override
+ public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) {
+ return new JetPsiCheckerMultifileTest(dataPath, name);
+ }
+ };
+
+ File dir = new File(getTestDataPathBase());
+ List subDirs = Arrays.asList(dir.list());
+ Collections.sort(subDirs);
+ for (String subDirName : subDirs) {
+ final TestSuite multiFileTestSuite = JetTestCaseBuilder.suiteForDirectory(getTestDataPathBase(), subDirName, true, multifileFileNameFilter, multiFileNamedTestFactory);
+ if (multiFileTestSuite.countTestCases() != 0) {
+ suite.addTest(multiFileTestSuite);
+ }
+ }
+ return suite;
+ }
+
+ public static String getTestDataPathBase() {
+ return JetTestCaseBuilder.getHomeDirectory() + "/idea/testData/quickfix/";
+ }
+}
diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/JetQuickFixTest.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/JetQuickFixTest.java
index 62faeb23d10..044378f134d 100644
--- a/idea/tests/org/jetbrains/jet/plugin/quickfix/JetQuickFixTest.java
+++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/JetQuickFixTest.java
@@ -43,26 +43,30 @@ public class JetQuickFixTest extends LightQuickFixTestCase {
public static Test suite() {
//setFilter(); //to launch only part of tests
TestSuite suite = new TestSuite();
- FilenameFilter fileNameFilter = new FilenameFilter() {
+
+ FilenameFilter singleFileNameFilter = new FilenameFilter() {
@Override
public boolean accept(File file, String s) {
- if (s.startsWith("before")) return true;
- return false;
+ return s.startsWith("before") && !JetPsiCheckerMultifileTest.isMultiFileName(s);
}
};
- JetTestCaseBuilder.NamedTestFactory namedTestFactory = new JetTestCaseBuilder.NamedTestFactory() {
+
+ JetTestCaseBuilder.NamedTestFactory singleFileNamedTestFactory = new JetTestCaseBuilder.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) {
return new JetQuickFixTest(dataPath, name);
}
};
+
File dir = new File(getTestDataPathBase());
List subDirs = Arrays.asList(quickFixTestsFilter != null ? dir.list(quickFixTestsFilter) : dir.list());
Collections.sort(subDirs);
for (String subDirName : subDirs) {
- suite.addTest(JetTestCaseBuilder.suiteForDirectory(getTestDataPathBase(), subDirName, true, fileNameFilter, namedTestFactory));
-
+ final TestSuite singleFileTestSuite = JetTestCaseBuilder.suiteForDirectory(getTestDataPathBase(), subDirName, true, singleFileNameFilter, singleFileNamedTestFactory);
+ if (singleFileTestSuite.countTestCases() != 0) {
+ suite.addTest(singleFileTestSuite);
+ }
}
return suite;
}
diff --git a/stdlib.ipr b/stdlib.ipr
new file mode 100644
index 00000000000..30c354500c5
--- /dev/null
+++ b/stdlib.ipr
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ http://www.w3.org/1999/xhtml
+
+
+
+
+
+
+
+
+
diff --git a/stdlib/ktSrc/Filter.kt b/stdlib/ktSrc/Filter.kt
new file mode 100644
index 00000000000..1fa5cb45317
--- /dev/null
+++ b/stdlib/ktSrc/Filter.kt
@@ -0,0 +1,66 @@
+namespace std
+
+import java.util.*
+import java.lang.Iterable
+
+/*
+Filters given iterator
+*/
+inline fun java.util.Iterator.filter(f: fun(T): Boolean) : java.util.Iterator = FilterIterator(this, f)
+
+/*
+Adds filtered elements in to given container
+*/
+/*
+inline fun > java.lang.Iterable.filterTo(var container: U, filter: fun(T): Boolean) : U {
+ for(element in this) {
+ if(filter(element))
+ container.add(element)
+ }
+ return container
+}
+*/
+
+/*
+Create iterator filtering given java.lang.Iterable
+*/
+/*
+inline fun java.lang.Iterable.filter(f: fun(T): Boolean) : java.util.Iterator = (iterator() as java.util.Iterator).filter(f)
+*/
+
+private class FilterIterator(val original: java.util.Iterator, val filter: fun(T): Boolean) : java.util.Iterator {
+ var state = 0
+ var nextElement: T? = null
+
+ override fun hasNext(): Boolean =
+ when(state) {
+ 1 => true // checked and next present
+ 2 => false // checked and next not present
+ else => {
+ while(original.hasNext()) {
+ val candidate = original.next()
+ if((filter)(candidate)) {
+ nextElement = candidate
+ state = 1
+ true
+ }
+ }
+ state = 2
+ false
+ }
+ }
+
+ override fun next(): T =
+ if(state != 1)
+ throw java.util.NoSuchElementException()
+ else {
+ val res = nextElement as T
+ nextElement = null
+ state = 0
+ res
+ }
+
+ override fun remove() {
+ throw java.lang.UnsupportedOperationException()
+ }
+}
diff --git a/stdlib/ktSrc/Iterators.kt b/stdlib/ktSrc/Iterators.kt
new file mode 100644
index 00000000000..8a9b592ab26
--- /dev/null
+++ b/stdlib/ktSrc/Iterators.kt
@@ -0,0 +1,38 @@
+namespace std.util
+
+import java.util.*
+import java.util.Iterator
+
+/*
+Add iterated elements to given container
+*/
+fun > java.util.Iterator.to(container: U) : U {
+ while(hasNext())
+ container.add(next())
+ return container
+}
+
+/*
+Add iterated elements to java.util.ArrayList
+*/
+inline fun java.util.Iterator.toArrayList() = to(ArrayList())
+
+/*
+Add iterated elements to java.util.LinkedList
+*/
+inline fun java.util.Iterator.toLinkedList() = to(LinkedList())
+
+/*
+Add iterated elements to java.util.HashSet
+*/
+inline fun java.util.Iterator.toHashSet() = to(HashSet())
+
+/*
+Add iterated elements to java.util.LinkedHashSet
+*/
+inline fun java.util.Iterator.toLinkedHashSet() = to(LinkedHashSet())
+
+/*
+Add iterated elements to java.util.TreeSet
+*/
+inline fun java.util.Iterator.toTreeSet() = to(TreeSet())
diff --git a/stdlib/ktSrc/JavaUtil.kt b/stdlib/ktSrc/JavaUtil.kt
index a75df8656d9..c9ef555cf0d 100644
--- a/stdlib/ktSrc/JavaUtil.kt
+++ b/stdlib/ktSrc/JavaUtil.kt
@@ -2,8 +2,212 @@ namespace std.util
import java.util.*
+/** Returns the size of the collection */
val Collection<*>.size : Int
get() = size()
+/** Returns true if this collection is empty */
val Collection<*>.empty : Boolean
get() = isEmpty()
+
+/** Returns a new ArrayList with a variable number of initial elements */
+inline fun arrayList(vararg values: T) : ArrayList {
+ val answer = ArrayList()
+ for (v in values)
+ answer.add(v)
+ return answer;
+}
+
+/** Returns a new LinkedList with a variable number of initial elements */
+inline fun linkedList(vararg values: T) : LinkedList {
+ val answer = LinkedList()
+ for (v in values)
+ answer.add(v)
+ return answer;
+}
+
+/** Returns a new HashSet with a variable number of initial elements */
+inline fun hashSet(vararg values: T) : HashSet {
+ val answer = HashSet()
+ for (v in values)
+ answer.add(v)
+ return answer;
+}
+
+/** Returns true if any elements in the collection match the given predicate */
+inline fun java.lang.Iterable.any(predicate: fun(T): Boolean) : Boolean {
+ for (elem in this) {
+ if (predicate(elem)) {
+ return true
+ }
+ }
+ return false
+}
+
+/** Returns true if all elements in the collection match the given predicate */
+inline fun java.lang.Iterable.all(predicate: fun(T): Boolean) : Boolean {
+ for (elem in this) {
+ if (!predicate(elem)) {
+ return false
+ }
+ }
+ return true
+}
+
+/** Returns the first item in the collection which matches the given predicate or null if none matched */
+inline fun java.lang.Iterable.find(predicate: fun(T): Boolean) : T? {
+ for (elem in this) {
+ if (predicate(elem))
+ return elem
+ }
+ return null
+}
+
+/** Returns a new collection containing all elements in this collection which match the given predicate */
+inline fun java.lang.Iterable.filter(result: Collection = ArrayList(), predicate: fun(T): Boolean) : Collection {
+ for (elem in this) {
+ if (predicate(elem))
+ result.add(elem)
+ }
+ return result
+}
+
+/**
+ * Returns the result of transforming each item in the collection to a one or more values which
+ * are concatenated together into a single collection
+ */
+inline fun java.lang.Iterable.flatMap(result: Collection = ArrayList(), transform: fun(T): Collection) : Collection {
+ for (elem in this) {
+ val coll = transform(elem)
+ if (coll != null) {
+ for (r in coll) {
+ result.add(r)
+ }
+ }
+ }
+ return result
+}
+
+/** Performs the given operation on each element inside the collection */
+inline fun java.lang.Iterable.foreach(operation: fun(element: T) : Unit) {
+ for (elem in this)
+ operation(elem)
+}
+
+/** Creates a String from all the elements in the collection, using the seperator between them and using the given prefix and postfix if supplied */
+inline fun java.lang.Iterable.join(separator: String, prefix: String = "", postfix: String = "") : String {
+ val buffer = StringBuilder(prefix)
+ var first = true
+ for (elem in this) {
+ if (first)
+ first = false
+ else
+ buffer.append(separator)
+ buffer.append(elem)
+ }
+ buffer.append(postfix)
+ return buffer.toString().sure()
+}
+
+/** Returns a new collection containing the results of applying the given function to each element in this collection */
+inline fun java.lang.Iterable.map(result: Collection = ArrayList(), transform : fun(T) : R) : Collection {
+ for (item in this)
+ result.add(transform(item))
+ return result
+}
+
+/** Returns a new collection containing the results of applying the given function to each element in this collection */
+inline fun java.util.Collection.map(result: Collection = ArrayList(this.size), transform : fun(T) : R) : Collection {
+ for (item in this)
+ result.add(transform(item))
+ return result
+}
+
+inline fun > java.lang.Iterable.toSortedList() : List {
+ val answer = this.toList()
+ answer.sort()
+ return answer
+}
+
+inline fun > java.lang.Iterable.toSortedList(comparator: java.util.Comparator) : List {
+ val answer = this.toList()
+ answer.sort(comparator)
+ return answer
+}
+
+/**
+ TODO figure out necessary variance/generics ninja stuff... :)
+inline fun java.lang.Iterable.toSortedList(transform: fun(T) : java.lang.Comparable<*>) : List {
+ val answer = this.toList()
+ answer.sort(transform)
+ return answer
+}
+*/
+
+inline fun java.lang.Iterable.toList() : List {
+ if (this is List)
+ return this
+ else {
+ val list = ArrayList()
+ for (elem in this)
+ list.add(elem)
+ return list
+ }
+}
+
+inline fun java.util.Collection.toArray() : Array {
+ if (this is Array)
+ return this
+ else {
+ val answer = Array(this.size)
+ var idx = 0
+ for (elem in this)
+ answer[idx++] = elem
+ return answer as Array
+ }
+}
+
+
+// List APIs
+
+inline fun > List.sort() : Unit {
+ Collections.sort(this)
+}
+
+inline fun > List.sort(comparator: java.util.Comparator) : Unit {
+ Collections.sort(this, comparator)
+}
+
+/**
+ TODO figure out necessary variance/generics ninja stuff... :)
+inline fun List.sort(transform: fun(T) : java.lang.Comparable<*>) : List {
+ val comparator = java.util.Comparator() {
+ fun compare(o1: T, o2: T): Int {
+ val v1 = transform(o1)
+ val v2 = transform(o2)
+ if (v1 == v2) {
+ return 0
+ } else {
+ return v1.compareTo(v2)
+ }
+ }
+ }
+ answer.sort(comparator)
+}
+*/
+
+val List