Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -8,3 +8,4 @@ out
|
||||
.idea/codeStyleSettings.xml
|
||||
.idea/workspace.xml
|
||||
tmp
|
||||
*TestMy.java
|
||||
|
||||
Generated
+1
@@ -12,6 +12,7 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/grammar/grammar.iml" filepath="$PROJECT_DIR$/grammar/grammar.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea.iml" filepath="$PROJECT_DIR$/idea/idea.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/stdlib/stdlib.iml" filepath="$PROJECT_DIR$/stdlib/stdlib.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/testlib/testlib.iml" filepath="$PROJECT_DIR$/testlib/testlib.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
||||
@@ -126,9 +126,7 @@ public abstract class ClassBodyCodegen {
|
||||
}
|
||||
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
|
||||
mv.visitEnd();
|
||||
FunctionCodegen.endVisit(v, "static initializer", myClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -130,7 +130,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
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<StackValue, StackValue> {
|
||||
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<StackValue, StackValue> {
|
||||
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<StackValue, StackValue> {
|
||||
|
||||
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<StackValue, StackValue> {
|
||||
return mask;
|
||||
}
|
||||
|
||||
private int pushMethodArguments(JetCallElement expression, List<Type> valueParameterTypes) {
|
||||
public int pushMethodArguments(JetCallElement expression, List<Type> 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<StackValue, StackValue> {
|
||||
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<StackValue, StackValue> {
|
||||
}
|
||||
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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,6 @@ public class JetTypeMapper {
|
||||
private final HashMap<JetType,String> knowTypeNames = new HashMap<JetType, String>();
|
||||
private final HashMap<JetType,Type> knowTypes = new HashMap<JetType, Type>();
|
||||
|
||||
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:
|
||||
// <P:>Ljava/lang/Object;
|
||||
// TODO: avoid writing java/lang/Object if interface list is not empty
|
||||
}
|
||||
signatureVisitor.writeClassBoundEnd();
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<JetExpression> 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);
|
||||
}
|
||||
}
|
||||
+267
-123
@@ -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<JetType> upperBoundsForKotlin;
|
||||
@Nullable
|
||||
private final List<JetType> lowerBoundsForKotlin;
|
||||
|
||||
private TypeParameterDescriptorInitialization(TypeParameterDescriptor descriptor) {
|
||||
this.origin = TypeParameterDescriptorOrigin.JAVA;
|
||||
this.descriptor = descriptor;
|
||||
this.upperBoundsForKotlin = null;
|
||||
this.lowerBoundsForKotlin = null;
|
||||
}
|
||||
|
||||
private TypeParameterDescriptorInitialization(TypeParameterDescriptor descriptor,
|
||||
List<JetType> upperBoundsForKotlin, List<JetType> lowerBoundsForKotlin) {
|
||||
this.origin = TypeParameterDescriptorOrigin.KOTLIN;
|
||||
this.descriptor = descriptor;
|
||||
this.upperBoundsForKotlin = upperBoundsForKotlin;
|
||||
this.lowerBoundsForKotlin = lowerBoundsForKotlin;
|
||||
}
|
||||
}
|
||||
|
||||
protected final Map<String, ClassDescriptor> classDescriptorCache = Maps.newHashMap();
|
||||
protected final Map<PsiTypeParameter, TypeParameterDescriptor> typeParameterDescriptorCache = Maps.newHashMap();
|
||||
protected final Map<PsiTypeParameter, TypeParameterDescriptorInitialization> typeParameterDescriptorCache = Maps.newHashMap();
|
||||
protected final Map<PsiMethod, FunctionDescriptor> methodDescriptorCache = Maps.newHashMap();
|
||||
protected final Map<PsiField, VariableDescriptor> fieldDescriptorCache = Maps.newHashMap();
|
||||
protected final Map<PsiElement, NamespaceDescriptor> 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.<AnnotationDescriptor>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<JetType> upperBounds = new ArrayList<JetType>();
|
||||
List<JetType> lowerBounds = new ArrayList<JetType>();
|
||||
|
||||
@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.<AnnotationDescriptor>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<TypeParameterDescriptor> resolveClassTypeParametersFromJetSignature(String jetSignature, final JavaClassDescriptor classDescriptor) {
|
||||
private List<TypeParameterDescriptor> resolveClassTypeParametersFromJetSignature(String jetSignature, final PsiClass clazz, final JavaClassDescriptor classDescriptor) {
|
||||
final List<TypeParameterDescriptor> r = new ArrayList<TypeParameterDescriptor>();
|
||||
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.<AnnotationDescriptor>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<ValueParameterDescriptor> descriptors;
|
||||
|
||||
public List<ValueParameterDescriptor> resolveParameterDescriptors(DeclarationDescriptor containingDeclaration, PsiParameter[] parameters) {
|
||||
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
|
||||
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<ValueParameterDescriptor> 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<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
|
||||
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.<AnnotationDescriptor>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.<AnnotationDescriptor>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<TypeParameterDescriptor> 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<TypeParameterDescriptor> 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<TypeParameterDescriptor> resolveMethodTypeParametersFromJetSignature(String jetSignature, final FunctionDescriptor functionDescriptor) {
|
||||
private List<TypeParameterDescriptor> resolveMethodTypeParametersFromJetSignature(String jetSignature, final PsiMethod method, final FunctionDescriptor functionDescriptor) {
|
||||
final List<TypeParameterDescriptor> r = new ArrayList<TypeParameterDescriptor>();
|
||||
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.<AnnotationDescriptor>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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace io {
|
||||
fun readLine() : String?
|
||||
}
|
||||
|
||||
fun <R> 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<out T> {
|
||||
fun iterator() : Iterator<T>
|
||||
}
|
||||
|
||||
trait ByteIterable : Iterable<Byte> {
|
||||
override fun iterator() : ByteIterator
|
||||
}
|
||||
|
||||
trait ShortIterable : Iterable<Short> {
|
||||
override fun iterator() : ShortIterator
|
||||
}
|
||||
|
||||
trait IntIterable : Iterable<Int> {
|
||||
override fun iterator() : IntIterator
|
||||
}
|
||||
|
||||
trait LongIterable : Iterable<Long> {
|
||||
override fun iterator() : LongIterator
|
||||
}
|
||||
|
||||
trait FloatIterable : Iterable<Float> {
|
||||
override fun iterator() : FloatIterator
|
||||
}
|
||||
|
||||
trait DoubleIterable : Iterable<Double> {
|
||||
override fun iterator() : DoubleIterator
|
||||
}
|
||||
|
||||
trait BooleanIterable : Iterable<Boolean> {
|
||||
override fun iterator() : BooleanIterator
|
||||
}
|
||||
|
||||
trait CharIterable : Iterable<Char> {
|
||||
override fun iterator() : CharIterator
|
||||
}
|
||||
|
||||
fun Array<T>(val size : Int) : Array<T?>
|
||||
|
||||
class Array<T>(val size : Int, init : fun(Int) : T) {
|
||||
@@ -230,7 +264,7 @@ trait Range<in T : Comparable<T>> {
|
||||
fun contains(item : T) : Boolean
|
||||
}
|
||||
|
||||
class IntRange(val start : Int, size : Int, reversed : Boolean = false) : Range<Int>, Iterable<Int> {
|
||||
class IntRange(val start : Int, size : Int, reversed : Boolean = false) : Range<Int>, IntIterable {
|
||||
fun iterator () : Iterator<Int>
|
||||
|
||||
fun contains (elem: Int) : Boolean
|
||||
|
||||
+50
-1
@@ -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<AnnotationDescriptor> 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<JetType> 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<JetType> 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, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
||||
checkInitialized();
|
||||
return visitor.visitTypeParameterDescriptor(this, data);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetType getDefaultType() {
|
||||
//checkInitialized();
|
||||
if (defaultType == null) {
|
||||
defaultType = new JetTypeImpl(
|
||||
Collections.<AnnotationDescriptor>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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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");
|
||||
|
||||
@@ -44,6 +44,7 @@ public class DescriptorSubstitutor {
|
||||
descriptor.getVariance(),
|
||||
descriptor.getName(),
|
||||
descriptor.getIndex());
|
||||
substituted.setInitialized();
|
||||
|
||||
mutableSubstitution.put(descriptor.getTypeConstructor(), new TypeProjection(substituted.getDefaultType()));
|
||||
|
||||
|
||||
+29
-14
@@ -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<String> NUMBER_CONVERSIONS = ImmutableSet.of(
|
||||
@@ -23,7 +28,7 @@ public class OperatorConventions {
|
||||
"int"
|
||||
);
|
||||
|
||||
public static final ImmutableMap<IElementType, String> UNARY_OPERATION_NAMES = ImmutableMap.<IElementType, String>builder()
|
||||
public static final ImmutableBiMap<JetToken, String> UNARY_OPERATION_NAMES = ImmutableBiMap.<JetToken, String>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<IElementType, String> BINARY_OPERATION_NAMES = ImmutableMap.<IElementType, String>builder()
|
||||
public static final ImmutableBiMap<JetToken, String> BINARY_OPERATION_NAMES = ImmutableBiMap.<JetToken, String>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<IElementType> COMPARISON_OPERATIONS = ImmutableSet.<IElementType>of(JetTokens.LT, JetTokens.GT, JetTokens.LTEQ, JetTokens.GTEQ);
|
||||
public static final ImmutableSet<IElementType> EQUALS_OPERATIONS = ImmutableSet.<IElementType>of(JetTokens.EQEQ, JetTokens.EXCLEQ);
|
||||
public static final ImmutableSet<JetToken> NOT_OVERLOADABLE =
|
||||
ImmutableSet.<JetToken>of(JetTokens.ANDAND, JetTokens.OROR, JetTokens.ELVIS);
|
||||
|
||||
public static final ImmutableSet<JetToken> INCREMENT_OPERATIONS =
|
||||
ImmutableSet.<JetToken>of(JetTokens.PLUSPLUS, JetTokens.MINUSMINUS);
|
||||
|
||||
public static final ImmutableSet<IElementType> IN_OPERATIONS = ImmutableSet.<IElementType>of(JetTokens.IN_KEYWORD, JetTokens.NOT_IN);
|
||||
public static final ImmutableMap<IElementType, String> ASSIGNMENT_OPERATIONS = ImmutableMap.<IElementType, String>builder()
|
||||
public static final ImmutableSet<JetToken> COMPARISON_OPERATIONS =
|
||||
ImmutableSet.<JetToken>of(JetTokens.LT, JetTokens.GT, JetTokens.LTEQ, JetTokens.GTEQ);
|
||||
|
||||
public static final ImmutableSet<JetToken> EQUALS_OPERATIONS =
|
||||
ImmutableSet.<JetToken>of(JetTokens.EQEQ, JetTokens.EXCLEQ);
|
||||
|
||||
public static final ImmutableSet<JetToken> IN_OPERATIONS =
|
||||
ImmutableSet.<JetToken>of(JetTokens.IN_KEYWORD, JetTokens.NOT_IN);
|
||||
|
||||
public static final ImmutableBiMap<JetToken, String> ASSIGNMENT_OPERATIONS = ImmutableBiMap.<JetToken, String>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<IElementType, IElementType> ASSIGNMENT_OPERATION_COUNTERPARTS = ImmutableMap.<IElementType, IElementType>builder()
|
||||
public static final ImmutableMap<JetToken, JetToken> ASSIGNMENT_OPERATION_COUNTERPARTS = ImmutableMap.<JetToken, JetToken>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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace one_extends_base
|
||||
|
||||
open class Base<T>(name : T?) {
|
||||
var myName : T?
|
||||
{
|
||||
$myName = name
|
||||
}
|
||||
}
|
||||
open class One<T, K>(name : T?, second : K?) : Base<T?>(name) {
|
||||
var mySecond : K?
|
||||
{
|
||||
$mySecond = second
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = if(One<String, Int>("ola", 0).myName == "ola") "OK" else "fail"
|
||||
@@ -0,0 +1,25 @@
|
||||
namespace demo2
|
||||
|
||||
fun print(o : Any?) {}
|
||||
|
||||
fun test(i : Int) {
|
||||
var monthString : String? = "<empty>"
|
||||
when (i) {
|
||||
1 => {
|
||||
print(1)
|
||||
print(2)
|
||||
print(3)
|
||||
print(4)
|
||||
print(5)
|
||||
}
|
||||
else => {
|
||||
monthString = "Invalid month"
|
||||
}
|
||||
}
|
||||
print(monthString)
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
for (i in 1..12) test(i)
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
val <T> Array<T>.length : Int get() = this.size
|
||||
|
||||
fun box() = if(Array(10, {1}).length == 10) "OK" else "fail"
|
||||
@@ -0,0 +1,14 @@
|
||||
// KT-860 ConcurrentModificationException in frontend
|
||||
// +JDK
|
||||
|
||||
namespace std.util
|
||||
|
||||
import java.util.*
|
||||
|
||||
fun <T, U: Collection<in T>> Iterator<T>.to(container: U) : U {
|
||||
while(hasNext)
|
||||
container.add(next())
|
||||
return container
|
||||
}
|
||||
|
||||
inline fun <T> Iterator<T>.toArrayList() = to(ArrayList<T>())
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace test
|
||||
|
||||
class Clock<A : java.lang.Number>
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace test
|
||||
|
||||
class Clock<A> where A : java.lang.Number, A : java.lang.CharSequence
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace test
|
||||
|
||||
class Clock<A : java.lang.CharSequence>
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace test
|
||||
|
||||
class Clock<A> where A : java.lang.CharSequence, A : java.lang.Number
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace test
|
||||
|
||||
trait Trtrtr
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace test
|
||||
|
||||
fun Int.shuffle() = 1
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace test
|
||||
|
||||
fun <A : java.lang.Number> uno() = 1
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace test
|
||||
|
||||
fun <A> tres() where A : java.lang.Number, A : java.lang.CharSequence = 1
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace test
|
||||
|
||||
fun <A : java.lang.CharSequence> dos() = 1
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace test
|
||||
|
||||
fun <A> cuatro() where A : java.lang.CharSequence, A : java.lang.Number = 1
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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<TypeProjection> typeArguments = new ArrayList<TypeProjection>();
|
||||
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<String> list = new ArrayList<String>();
|
||||
for (JetType upper : param.getUpperBounds()) {
|
||||
list.add(serialize(upper));
|
||||
}
|
||||
Collections.sort(list);
|
||||
serializeSeparated(list, sb, " & "); // TODO: use where
|
||||
}
|
||||
// TODO: lower bounds
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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<Array<Int>> (5, { Array<Int>(it, {239}) })");
|
||||
Method foo = generateFunction();
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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 <T> Int.latch(op: fun CountDownLatch.() : T) : T {
|
||||
val cdl = CountDownLatch(this)
|
||||
val res = cdl.op()
|
||||
@@ -22,41 +15,37 @@ fun <T> 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<String>) {
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<JetDeclaration> 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());
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
// "Import Class" "true"
|
||||
|
||||
import TestData.TestSample
|
||||
|
||||
fun test() {
|
||||
val a = TestSample
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace TestData
|
||||
|
||||
class TestSample() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
// "Import Class" "true"
|
||||
|
||||
fun test() {
|
||||
val a = <caret>TestSample
|
||||
}
|
||||
@@ -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<String, Boolean> 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<IntentionAction> actions = getAvailableActions();
|
||||
List<String> texts = new ArrayList<String>();
|
||||
for (IntentionAction intentionAction : actions) {
|
||||
texts.add(intentionAction.getText());
|
||||
}
|
||||
Collection<HighlightInfo> 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<File> 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<File> allTestFiles = Arrays.asList(dir.listFiles(resultFilter));
|
||||
|
||||
final Collection<File> mainFiles = Collections2.filter(allTestFiles, new Predicate<File>() {
|
||||
@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<File> dataFiles = Collections2.filter(allTestFiles, new Predicate<File>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable File file) {
|
||||
return file != null && file.getName().contains(DATA_SUBSTRING);
|
||||
}
|
||||
});
|
||||
|
||||
final ArrayList<File> fileResult = new ArrayList<File>(allTestFiles);
|
||||
fileResult.addAll(dataFiles);
|
||||
|
||||
return fileResult;
|
||||
}
|
||||
|
||||
protected static List<String> getFileNames(List<File> files) {
|
||||
return Lists.newArrayList(Collections2.transform(files, new Function<File, String>() {
|
||||
@Override
|
||||
public String apply(File file) {
|
||||
return file.getName();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
protected List<IntentionAction> 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<String> 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/";
|
||||
}
|
||||
}
|
||||
@@ -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<String> 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;
|
||||
}
|
||||
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AntConfiguration">
|
||||
<defaultAnt bundledAnt="true" />
|
||||
</component>
|
||||
<component name="CompilerConfiguration">
|
||||
<option name="DEFAULT_COMPILER" value="Javac" />
|
||||
<resourceExtensions />
|
||||
<wildcardResourcePatterns>
|
||||
<entry name="?*.properties" />
|
||||
<entry name="?*.xml" />
|
||||
<entry name="?*.gif" />
|
||||
<entry name="?*.png" />
|
||||
<entry name="?*.jpeg" />
|
||||
<entry name="?*.jpg" />
|
||||
<entry name="?*.html" />
|
||||
<entry name="?*.dtd" />
|
||||
<entry name="?*.tld" />
|
||||
<entry name="?*.ftl" />
|
||||
</wildcardResourcePatterns>
|
||||
<annotationProcessing enabled="false" useClasspath="true" />
|
||||
</component>
|
||||
<component name="CopyrightManager" default="">
|
||||
<module2copyright />
|
||||
</component>
|
||||
<component name="DependencyValidationManager">
|
||||
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
|
||||
</component>
|
||||
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
|
||||
<component name="IdProvider" IDEtalkID="89F322227D19AFBE9B68C2A85DBC4124" />
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profiles>
|
||||
<profile version="1.0" is_locked="false">
|
||||
<option name="myName" value="Project Default" />
|
||||
<option name="myLocal" value="false" />
|
||||
<inspection_tool class="EjbErrorInspection" level="ERROR" enabled="false" />
|
||||
<inspection_tool class="EjbWarningInspection" level="WARNING" enabled="false" />
|
||||
<inspection_tool class="JpaModelErrorInspection" level="ERROR" enabled="false" />
|
||||
</profile>
|
||||
</profiles>
|
||||
<option name="PROJECT_PROFILE" value="Project Default" />
|
||||
<option name="USE_PROJECT_PROFILE" value="true" />
|
||||
<version value="1.0" />
|
||||
</component>
|
||||
<component name="JavadocGenerationManager">
|
||||
<option name="OUTPUT_DIRECTORY" />
|
||||
<option name="OPTION_SCOPE" value="protected" />
|
||||
<option name="OPTION_HIERARCHY" value="true" />
|
||||
<option name="OPTION_NAVIGATOR" value="true" />
|
||||
<option name="OPTION_INDEX" value="true" />
|
||||
<option name="OPTION_SEPARATE_INDEX" value="true" />
|
||||
<option name="OPTION_DOCUMENT_TAG_USE" value="false" />
|
||||
<option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
|
||||
<option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
|
||||
<option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
|
||||
<option name="OPTION_DEPRECATED_LIST" value="true" />
|
||||
<option name="OTHER_OPTIONS" value="" />
|
||||
<option name="HEAP_SIZE" />
|
||||
<option name="LOCALE" />
|
||||
<option name="OPEN_IN_BROWSER" value="true" />
|
||||
</component>
|
||||
<component name="ModuleEditorState">
|
||||
<option name="LAST_EDITED_MODULE_NAME" />
|
||||
<option name="LAST_EDITED_TAB_NAME" />
|
||||
</component>
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/stdlib/stdlib.iml" filepath="$PROJECT_DIR$/stdlib/stdlib.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/testlib/testlib.iml" filepath="$PROJECT_DIR$/testlib/testlib.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
<component name="ProjectResources">
|
||||
<default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
namespace std
|
||||
|
||||
import java.util.*
|
||||
import java.lang.Iterable
|
||||
|
||||
/*
|
||||
Filters given iterator
|
||||
*/
|
||||
inline fun <T> java.util.Iterator<T>.filter(f: fun(T): Boolean) : java.util.Iterator<T> = FilterIterator<T>(this, f)
|
||||
|
||||
/*
|
||||
Adds filtered elements in to given container
|
||||
*/
|
||||
/*
|
||||
inline fun <T,U : Collection<in T>> java.lang.Iterable<T>.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 <T> java.lang.Iterable<T>.filter(f: fun(T): Boolean) : java.util.Iterator<T> = (iterator() as java.util.Iterator<T>).filter(f)
|
||||
*/
|
||||
|
||||
private class FilterIterator<T>(val original: java.util.Iterator<T>, val filter: fun(T): Boolean) : java.util.Iterator<T> {
|
||||
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()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
namespace std.util
|
||||
|
||||
import java.util.*
|
||||
import java.util.Iterator
|
||||
|
||||
/*
|
||||
Add iterated elements to given container
|
||||
*/
|
||||
fun <T,U: Collection<in T>> java.util.Iterator<T>.to(container: U) : U {
|
||||
while(hasNext())
|
||||
container.add(next())
|
||||
return container
|
||||
}
|
||||
|
||||
/*
|
||||
Add iterated elements to java.util.ArrayList
|
||||
*/
|
||||
inline fun <T> java.util.Iterator<T>.toArrayList() = to(ArrayList<T>())
|
||||
|
||||
/*
|
||||
Add iterated elements to java.util.LinkedList
|
||||
*/
|
||||
inline fun <T> java.util.Iterator<T>.toLinkedList() = to(LinkedList<T>())
|
||||
|
||||
/*
|
||||
Add iterated elements to java.util.HashSet
|
||||
*/
|
||||
inline fun <T> java.util.Iterator<T>.toHashSet() = to(HashSet<T>())
|
||||
|
||||
/*
|
||||
Add iterated elements to java.util.LinkedHashSet
|
||||
*/
|
||||
inline fun <T> java.util.Iterator<T>.toLinkedHashSet() = to(LinkedHashSet<T>())
|
||||
|
||||
/*
|
||||
Add iterated elements to java.util.TreeSet
|
||||
*/
|
||||
inline fun <T> java.util.Iterator<T>.toTreeSet() = to(TreeSet<T>())
|
||||
@@ -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<T>(vararg values: T) : ArrayList<T> {
|
||||
val answer = ArrayList<T>()
|
||||
for (v in values)
|
||||
answer.add(v)
|
||||
return answer;
|
||||
}
|
||||
|
||||
/** Returns a new LinkedList with a variable number of initial elements */
|
||||
inline fun linkedList<T>(vararg values: T) : LinkedList<T> {
|
||||
val answer = LinkedList<T>()
|
||||
for (v in values)
|
||||
answer.add(v)
|
||||
return answer;
|
||||
}
|
||||
|
||||
/** Returns a new HashSet with a variable number of initial elements */
|
||||
inline fun hashSet<T>(vararg values: T) : HashSet<T> {
|
||||
val answer = HashSet<T>()
|
||||
for (v in values)
|
||||
answer.add(v)
|
||||
return answer;
|
||||
}
|
||||
|
||||
/** Returns true if any elements in the collection match the given predicate */
|
||||
inline fun <T> java.lang.Iterable<T>.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 <T> java.lang.Iterable<T>.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 <T> java.lang.Iterable<T>.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 <T> java.lang.Iterable<T>.filter(result: Collection<T> = ArrayList<T>(), predicate: fun(T): Boolean) : Collection<T> {
|
||||
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 <T, out R> java.lang.Iterable<T>.flatMap(result: Collection<R> = ArrayList<R>(), transform: fun(T): Collection<R>) : Collection<R> {
|
||||
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 <T> java.lang.Iterable<T>.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 <T> java.lang.Iterable<T>.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 <T, R> java.lang.Iterable<T>.map(result: Collection<R> = ArrayList<R>(), transform : fun(T) : R) : Collection<R> {
|
||||
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 <T, R> java.util.Collection<T>.map(result: Collection<R> = ArrayList<R>(this.size), transform : fun(T) : R) : Collection<R> {
|
||||
for (item in this)
|
||||
result.add(transform(item))
|
||||
return result
|
||||
}
|
||||
|
||||
inline fun <in T: java.lang.Comparable<T>> java.lang.Iterable<T>.toSortedList() : List<T> {
|
||||
val answer = this.toList()
|
||||
answer.sort()
|
||||
return answer
|
||||
}
|
||||
|
||||
inline fun <in T: java.lang.Comparable<T>> java.lang.Iterable<T>.toSortedList(comparator: java.util.Comparator<T>) : List<T> {
|
||||
val answer = this.toList()
|
||||
answer.sort(comparator)
|
||||
return answer
|
||||
}
|
||||
|
||||
/**
|
||||
TODO figure out necessary variance/generics ninja stuff... :)
|
||||
inline fun <in T> java.lang.Iterable<T>.toSortedList(transform: fun(T) : java.lang.Comparable<*>) : List<T> {
|
||||
val answer = this.toList()
|
||||
answer.sort(transform)
|
||||
return answer
|
||||
}
|
||||
*/
|
||||
|
||||
inline fun <T> java.lang.Iterable<T>.toList() : List<T> {
|
||||
if (this is List<T>)
|
||||
return this
|
||||
else {
|
||||
val list = ArrayList<T>()
|
||||
for (elem in this)
|
||||
list.add(elem)
|
||||
return list
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <T> java.util.Collection<T>.toArray() : Array<T> {
|
||||
if (this is Array<T>)
|
||||
return this
|
||||
else {
|
||||
val answer = Array<T>(this.size)
|
||||
var idx = 0
|
||||
for (elem in this)
|
||||
answer[idx++] = elem
|
||||
return answer as Array<T>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// List APIs
|
||||
|
||||
inline fun <in T: java.lang.Comparable<T>> List<T>.sort() : Unit {
|
||||
Collections.sort(this)
|
||||
}
|
||||
|
||||
inline fun <in T: java.lang.Comparable<T>> List<T>.sort(comparator: java.util.Comparator<T>) : Unit {
|
||||
Collections.sort(this, comparator)
|
||||
}
|
||||
|
||||
/**
|
||||
TODO figure out necessary variance/generics ninja stuff... :)
|
||||
inline fun <in T> List<T>.sort(transform: fun(T) : java.lang.Comparable<*>) : List<T> {
|
||||
val comparator = java.util.Comparator<T>() {
|
||||
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 <T> List<T>.head : T?
|
||||
get() = this.get(0)
|
||||
|
||||
val <T> List<T>.first : T?
|
||||
get() = this.head
|
||||
|
||||
val <T> List<T>.tail : T?
|
||||
get() {
|
||||
val s = this.size
|
||||
return if (s > 0) this.get(s - 1) else null
|
||||
|
||||
}
|
||||
val <T> List<T>.last : T?
|
||||
get() = this.tail
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace std.util
|
||||
|
||||
/**
|
||||
Executes current block and returns elapsed time in milliseconds
|
||||
*/
|
||||
fun measureTimeMillis(block: fun() : Unit) : Long {
|
||||
val start = System.currentTimeMillis()
|
||||
block()
|
||||
return System.currentTimeMillis() - start
|
||||
}
|
||||
|
||||
/**
|
||||
Executes current block and returns elapsed time in milliseconds
|
||||
*/
|
||||
fun measureTimeNano(block: fun() : Unit) : Long {
|
||||
val start = System.nanoTime()
|
||||
block()
|
||||
return System.nanoTime() - start
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
namespace std.concurrent
|
||||
|
||||
import java.lang.*
|
||||
|
||||
inline var Thread.name : String
|
||||
get() = getName().sure()
|
||||
set(name: String) { setName(name) }
|
||||
|
||||
inline var Thread.daemon : Boolean
|
||||
get() = isDaemon()
|
||||
set(on: Boolean) { setDaemon(on) }
|
||||
|
||||
inline val Thread.alive : Boolean
|
||||
get() = isAlive()
|
||||
|
||||
inline var Thread.priority : Int
|
||||
get() = getPriority()
|
||||
set(prio: Int) { setPriority(prio) }
|
||||
|
||||
inline var Thread.contextClassLoader : ClassLoader?
|
||||
get() = getContextClassLoader()
|
||||
set(loader: ClassLoader?) { setContextClassLoader(loader) }
|
||||
|
||||
fun thread(start: Boolean = true, daemon: Boolean = false, contextClassLoader: ClassLoader? = null, name: String? = null, priority: Int = -1, block: fun():Unit) : Thread {
|
||||
val thread = object: Thread() {
|
||||
override fun run() {
|
||||
block()
|
||||
}
|
||||
}
|
||||
if(daemon)
|
||||
thread.setDaemon(true)
|
||||
if(priority > 0)
|
||||
thread.setPriority(priority)
|
||||
if(name != null)
|
||||
thread.setName(name)
|
||||
if(contextClassLoader != null)
|
||||
thread.setContextClassLoader(contextClassLoader)
|
||||
if(start)
|
||||
thread.start()
|
||||
return thread
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package jet;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public interface BooleanIterable extends Iterable<Boolean> {
|
||||
@Override
|
||||
BooleanIterator iterator();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package jet;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public interface ByteIterable extends Iterable<Byte> {
|
||||
@Override
|
||||
ByteIterator iterator();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package jet;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public interface CharIterable extends Iterable<Character> {
|
||||
@Override
|
||||
CharIterator iterator();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package jet;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public interface DoubleIterable extends Iterable<Double> {
|
||||
@Override
|
||||
DoubleIterator iterator();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package jet;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public interface FloatIterable extends Iterable<Float> {
|
||||
@Override
|
||||
FloatIterator iterator();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package jet;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public interface IntIterable extends Iterable<Integer> {
|
||||
@Override
|
||||
IntIterator iterator();
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package jet;
|
||||
|
||||
import jet.typeinfo.TypeInfo;
|
||||
|
||||
public final class IntRange implements Range<Integer>, Iterable<Integer>, JetObject {
|
||||
public final class IntRange implements Range<Integer>, IntIterable, JetObject {
|
||||
private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(IntRange.class, false);
|
||||
|
||||
private final int start;
|
||||
@@ -39,7 +39,7 @@ public final class IntRange implements Range<Integer>, Iterable<Integer>, JetObj
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Integer> iterator() {
|
||||
public IntIterator iterator() {
|
||||
return new MyIterator(start, count);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ public final class IntRange implements Range<Integer>, Iterable<Integer>, JetObj
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyIterator implements Iterator<Integer> {
|
||||
private static class MyIterator extends IntIterator {
|
||||
private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(MyIterator.class, false);
|
||||
|
||||
private int cur;
|
||||
@@ -86,7 +86,7 @@ public final class IntRange implements Range<Integer>, Iterable<Integer>, JetObj
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer next() {
|
||||
public int nextInt() {
|
||||
count--;
|
||||
if(reversed) {
|
||||
return cur--;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package jet;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public interface LongIterable extends Iterable<Long> {
|
||||
@Override
|
||||
LongIterator iterator();
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package jet;
|
||||
|
||||
import jet.typeinfo.TypeInfo;
|
||||
|
||||
public final class LongRange implements Range<Long>, Iterable<Long>, JetObject {
|
||||
public final class LongRange implements Range<Long>, LongIterable, JetObject {
|
||||
private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(IntRange.class, false);
|
||||
|
||||
private final long start;
|
||||
@@ -39,7 +39,7 @@ public final class LongRange implements Range<Long>, Iterable<Long>, JetObject {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Long> iterator() {
|
||||
public LongIterator iterator() {
|
||||
return new MyIterator(start, count);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ public final class LongRange implements Range<Long>, Iterable<Long>, JetObject {
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyIterator implements Iterator<Long> {
|
||||
private static class MyIterator extends LongIterator {
|
||||
private final static TypeInfo typeInfo = TypeInfo.getTypeInfo(MyIterator.class, false);
|
||||
|
||||
private long cur;
|
||||
@@ -86,7 +86,7 @@ public final class LongRange implements Range<Long>, Iterable<Long>, JetObject {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long next() {
|
||||
public long nextLong() {
|
||||
count--;
|
||||
if(reversed) {
|
||||
return cur--;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package jet;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public interface ShortIterable extends Iterable<Short> {
|
||||
@Override
|
||||
ShortIterator iterator();
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package jet.runtime;
|
||||
|
||||
import jet.Function0;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
@@ -29,6 +31,12 @@ public class Intrinsics {
|
||||
return (thisVal == anotherVal ? 0 : (anotherVal ? 1 : -1));
|
||||
}
|
||||
|
||||
public static <R> R stupidSync(Object lock, Function0<R> block) {
|
||||
synchronized (lock) {
|
||||
return block.invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private static Throwable sanitizeStackTrace(Throwable throwable) {
|
||||
StackTraceElement[] stackTrace = throwable.getStackTrace();
|
||||
ArrayList<StackTraceElement> list = new ArrayList<StackTraceElement>();
|
||||
|
||||
@@ -35,6 +35,11 @@ public @interface JetValueParameter {
|
||||
*/
|
||||
boolean hasDefaultValue () default false;
|
||||
|
||||
/**
|
||||
* @return if this parameter is receiver
|
||||
*/
|
||||
boolean receiver() default false;
|
||||
|
||||
/**
|
||||
* @return type unless Java type is correct Kotlin type.
|
||||
*/
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,69 @@
|
||||
namespace std.test
|
||||
|
||||
import std.io.*
|
||||
import std.util.*
|
||||
import java.util.*
|
||||
|
||||
import org.junit.*
|
||||
import org.junit.runner.*
|
||||
import org.junit.runner.notification.*
|
||||
import junit.framework.*
|
||||
|
||||
fun assert(message: String, block: fun() : Boolean) {
|
||||
val actual = block()
|
||||
Assert.assertTrue(message, actual)
|
||||
}
|
||||
|
||||
fun assert(block: fun() : Boolean) = assert(block.toString(), block)
|
||||
|
||||
fun assertNot(message: String, block: fun() : Boolean) {
|
||||
assert(message){ !block() }
|
||||
}
|
||||
|
||||
fun assertNot(block: fun() : Boolean) = assertNot(block.toString(), block)
|
||||
|
||||
fun assert(actual: Boolean, message: String) {
|
||||
println("Answer: ${actual} for ${message}")
|
||||
}
|
||||
|
||||
fun assertEquals(expected: Any, actual: Any?, message: String = "") {
|
||||
Assert.assertEquals(message, expected, actual)
|
||||
}
|
||||
|
||||
fun assertNull(actual: Any?, message: String = "") {
|
||||
Assert.assertNull(message, actual)
|
||||
}
|
||||
|
||||
fun fails(block: fun() : Any) {
|
||||
try {
|
||||
block()
|
||||
Assert.fail("Expected an exception to be thrown")
|
||||
} catch (e: Exception) {
|
||||
// OK
|
||||
}
|
||||
}
|
||||
|
||||
fun todo(block: fun(): Any) {
|
||||
println("TODO at " + Exception().getStackTrace()?.get(1))
|
||||
}
|
||||
|
||||
/*
|
||||
TODO we could maybe create our own test runner for JUnit
|
||||
to avoid a runtime dependency on JUnit for running tests?
|
||||
|
||||
class KotlinTestRunner() : Runner() {
|
||||
|
||||
override fun getDescription(): Description? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun run(notifier: RunNotifier?) {
|
||||
println("About to run a test case on ${this}")
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// TODO no annotations yet?
|
||||
//@RunWith(KotlinTestRunner)
|
||||
abstract class TestSupport() : TestCase() {
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
namespace test.apicheck
|
||||
|
||||
import std.util.*
|
||||
import java.util.*
|
||||
|
||||
trait Traversable<T> {
|
||||
|
||||
/** Returns true if any elements in the collection match the given predicate */
|
||||
fun any(predicate: fun(T): Boolean) : Boolean
|
||||
|
||||
/** Returns true if all elements in the collection match the given predicate */
|
||||
fun all(predicate: fun(T): Boolean) : Boolean
|
||||
|
||||
/** Returns the first item in the collection which matches the given predicate or null if none matched */
|
||||
fun find(predicate: fun(T): Boolean) : T?
|
||||
|
||||
/** Returns a new collection containing all elements in this collection which match the given predicate */
|
||||
// TODO using: Collection<T> for the return type - I wonder if this exact type could be
|
||||
// deduced somewhat from the This.Type; e.g. returning Set on a Set, Array on Array etc
|
||||
fun filter(predicate: fun(T): Boolean) : Collection<T>
|
||||
|
||||
/** Performs the given operation on each element inside the collection */
|
||||
fun foreach(operation: fun(element: T) : Unit)
|
||||
|
||||
/** Returns a new collection containing the results of applying the given function to each element in this collection */
|
||||
fun <T, R> java.lang.Iterable<T>.map(transform : fun(T) : R) : Collection<R>
|
||||
}
|
||||
|
||||
/**
|
||||
TODO try use delegation here to make sure we implement all the methods in the Traversable API
|
||||
|
||||
class ListImpl<T>(coll: ArrayList<out T>) : Traversable<T> by coll {
|
||||
}
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,153 @@
|
||||
namespace test.collections
|
||||
|
||||
// TODO can we avoid importing all this stuff by default I wonder?
|
||||
// e.g. making println and the collection builder methods public by default?
|
||||
import std.*
|
||||
import std.io.*
|
||||
import std.util.*
|
||||
import std.test.*
|
||||
import java.util.*
|
||||
|
||||
class CollectionTest() : TestSupport() {
|
||||
val data = arrayList("foo", "bar")
|
||||
|
||||
fun testAny() {
|
||||
assert {
|
||||
data.any{it.startsWith("f")}
|
||||
}
|
||||
assertNot {
|
||||
data.any{it.startsWith("x")}
|
||||
}
|
||||
}
|
||||
|
||||
fun testAll() {
|
||||
assert {
|
||||
data.all{it.length == 3}
|
||||
}
|
||||
assertNot {
|
||||
data.all{s => s.startsWith("b")}
|
||||
}
|
||||
}
|
||||
|
||||
fun testFilter() {
|
||||
val foo = data.filter{it.startsWith("f")}
|
||||
|
||||
assert {
|
||||
foo.all{it.startsWith("f")}
|
||||
}
|
||||
assertEquals(1, foo.size)
|
||||
assertEquals(arrayList("foo"), foo)
|
||||
}
|
||||
|
||||
fun testFilterIntoLinkedList() {
|
||||
// TODO would be nice to avoid the <String>
|
||||
val foo = data.filter(linkedList<String>()){it.startsWith("f")}
|
||||
|
||||
assert {
|
||||
foo.all{it.startsWith("f")}
|
||||
}
|
||||
assertEquals(1, foo.size)
|
||||
assertEquals(linkedList("foo"), foo)
|
||||
|
||||
assert {
|
||||
foo is LinkedList<String>
|
||||
}
|
||||
}
|
||||
|
||||
fun testFilterIntoSortedSet() {
|
||||
// TODO would be nice to avoid the <String>
|
||||
val foo = data.filter(hashSet<String>()){it.startsWith("f")}
|
||||
|
||||
assert {
|
||||
foo.all{it.startsWith("f")}
|
||||
}
|
||||
assertEquals(1, foo.size)
|
||||
assertEquals(hashSet("foo"), foo)
|
||||
|
||||
assert {
|
||||
foo is HashSet<String>
|
||||
}
|
||||
}
|
||||
|
||||
fun testFind() {
|
||||
val x = data.find{it.startsWith("x")}
|
||||
assertNull(x)
|
||||
fails {
|
||||
x.sure()
|
||||
}
|
||||
|
||||
val f = data.find{it.startsWith("f")}
|
||||
f.sure()
|
||||
assertEquals("foo", f)
|
||||
}
|
||||
|
||||
fun testFlatMap() {
|
||||
/**
|
||||
TODO compiler bug
|
||||
we should be able to remove the explicit type on the function
|
||||
http://youtrack.jetbrains.net/issue/KT-849
|
||||
*/
|
||||
// TODO there should be a neater way to do this :)
|
||||
|
||||
val characters = arrayList('f', 'o', 'o', 'b', 'a', 'r')
|
||||
/*
|
||||
val characters = data.flatMap<String,Character>{
|
||||
Arrays.asList((it as java.lang.String).toCharArray()) as Collection<Character>
|
||||
}
|
||||
*/
|
||||
todo {
|
||||
println("Got list of characters ${characters}")
|
||||
val text = characters.join("")
|
||||
assertEquals("foobar", text)
|
||||
}
|
||||
}
|
||||
|
||||
fun testForeach() {
|
||||
var count = 0
|
||||
val x = data.foreach{ count += it.length }
|
||||
assertEquals(6, count)
|
||||
}
|
||||
|
||||
fun testJoin() {
|
||||
val text = data.join("-", "<", ">")
|
||||
assertEquals("<foo-bar>", text)
|
||||
}
|
||||
|
||||
fun testMap() {
|
||||
/**
|
||||
TODO compiler bug
|
||||
we should be able to remove the explicit type on the function
|
||||
http://youtrack.jetbrains.net/issue/KT-849
|
||||
*/
|
||||
val lengths = data.map<String,Int>{s => s.length}
|
||||
assert {
|
||||
lengths.all{it == 3}
|
||||
}
|
||||
assertEquals(2, lengths.size)
|
||||
assertEquals(arrayList(3, 3), lengths)
|
||||
}
|
||||
|
||||
fun testSort() {
|
||||
val coll: List<String> = arrayList("foo", "bar", "abc")
|
||||
|
||||
// TODO fixme
|
||||
// Some sort of in/out variance thing - or an issue with Java interop?
|
||||
//coll.sort()
|
||||
todo {
|
||||
assertEquals(3, coll.size)
|
||||
assertEquals(arrayList("abc", "bar", "foo"), coll)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun testToArray() {
|
||||
val arr = data.toArray()
|
||||
println("Got array ${arr}")
|
||||
todo {
|
||||
assert {
|
||||
arr is Array<String>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace test.collections
|
||||
|
||||
import std.test.*
|
||||
|
||||
// TODO can we avoid importing all this stuff by default I wonder?
|
||||
// e.g. making println and the collection builder methods public by default?
|
||||
import std.*
|
||||
import std.io.*
|
||||
import std.util.*
|
||||
import java.util.*
|
||||
|
||||
class ListTest() : TestSupport() {
|
||||
val data = arrayList("foo", "bar")
|
||||
|
||||
fun testHeadAndTail() {
|
||||
val h = data.head
|
||||
assertEquals("foo", h)
|
||||
|
||||
val t = data.tail
|
||||
assertEquals("bar", t)
|
||||
}
|
||||
|
||||
fun testFirstAndLast() {
|
||||
val h = data.first
|
||||
assertEquals("foo", h)
|
||||
|
||||
val t = data.last
|
||||
assertEquals("bar", t)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
namespace test.collections
|
||||
|
||||
import std.*
|
||||
import std.io.*
|
||||
import std.util.*
|
||||
import std.test.*
|
||||
import java.util.*
|
||||
|
||||
class SetTest() : TestSupport() {
|
||||
val data = hashSet("foo", "bar")
|
||||
|
||||
fun testAny() {
|
||||
assert {
|
||||
data.any{it.startsWith("f")}
|
||||
}
|
||||
assertNot {
|
||||
data.any{it.startsWith("x")}
|
||||
}
|
||||
}
|
||||
|
||||
fun testAll() {
|
||||
assert {
|
||||
data.all{it.length == 3}
|
||||
}
|
||||
assertNot {
|
||||
data.all{s => s.startsWith("b")}
|
||||
}
|
||||
}
|
||||
|
||||
fun testFilter() {
|
||||
val foo = data.filter{it.startsWith("f")}
|
||||
|
||||
assert {
|
||||
foo.all{it.startsWith("f")}
|
||||
}
|
||||
assertEquals(1, foo.size)
|
||||
assertEquals(arrayList("foo"), foo)
|
||||
|
||||
// TODO ideally foo would now be a set
|
||||
todo {
|
||||
assert("Filter on a Set should return a Set") {
|
||||
foo is Set<String>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun testFind() {
|
||||
val x = data.find{it.startsWith("x")}
|
||||
assertNull(x)
|
||||
fails {
|
||||
x.sure()
|
||||
}
|
||||
|
||||
val f = data.find{it.startsWith("f")}
|
||||
f.sure()
|
||||
assertEquals("foo", f)
|
||||
}
|
||||
|
||||
fun testMap() {
|
||||
/**
|
||||
TODO compiler bug
|
||||
we should be able to remove the explicit type on the function
|
||||
http://youtrack.jetbrains.net/issue/KT-849
|
||||
*/
|
||||
val lengths = data.map<String,Int>{s => s.length}
|
||||
assert {
|
||||
lengths.all{it == 3}
|
||||
}
|
||||
assertEquals(2, lengths.size)
|
||||
assertEquals(arrayList(3, 3), lengths)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module-library" exported="">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/lib/junit-4.9.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module" module-name="stdlib" exported="" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
Reference in New Issue
Block a user