diff --git a/.idea/runConfigurations/All_Tests.xml b/.idea/runConfigurations/All_Tests.xml
index 6ebba66deda..85e2275839b 100644
--- a/.idea/runConfigurations/All_Tests.xml
+++ b/.idea/runConfigurations/All_Tests.xml
@@ -23,10 +23,16 @@
+
+
+
+
+
+
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java
index fd4e66256a3..6ffc688431f 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java
@@ -71,13 +71,17 @@ public abstract class ClassBodyCodegen {
}
else if (declaration instanceof JetNamedFunction) {
try {
- functionCodegen.gen((JetNamedFunction) declaration);
+ genNamedFunction((JetNamedFunction) declaration, functionCodegen);
} catch (RuntimeException e) {
throw new RuntimeException("Error generating method " + myClass.getName() + "." + declaration.getName() + " in " + context, e);
}
}
}
+ protected void genNamedFunction(JetNamedFunction declaration, FunctionCodegen functionCodegen) {
+ functionCodegen.gen(declaration);
+ }
+
private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen) {
OwnerKind kind = context.getContextKind();
for (JetParameter p : getPrimaryConstructorParameters()) {
@@ -90,7 +94,7 @@ public abstract class ClassBodyCodegen {
}
//noinspection ConstantConditions
- if (!(kind instanceof OwnerKind.DelegateKind) && kind != OwnerKind.INTERFACE && state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
+ if (!(kind instanceof OwnerKind.DelegateKind) && state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
v.visitField(Opcodes.ACC_PRIVATE, p.getName(), state.getTypeMapper().mapType(propertyDescriptor.getOutType()).getDescriptor(), null, null);
}
}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java
index 5c117ce1962..1933acff885 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java
@@ -9,6 +9,7 @@ import org.objectweb.asm.commons.InstructionAdapter;
/**
* @author max
+ * @author alex.tkachman
*/
public class ClassCodegen {
private final GenerationState state;
@@ -35,6 +36,11 @@ public class ClassCodegen {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
ClassVisitor v = state.forClassImplementation(descriptor);
new ImplementationBodyCodegen(aClass, parentContext.intoClass(descriptor, kind), v, state).generate();
+
+ if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) {
+ v = state.forTraitImplementation(descriptor);
+ new TraitImplBodyCodegen(aClass, parentContext.intoClass(descriptor, OwnerKind.TRAIT_IMPL), v, state).generate();
+ }
}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java
index 3bf85426225..df479228c83 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java
@@ -914,7 +914,7 @@ public class ExpressionCodegen extends JetVisitor {
CallableMethod callableMethod;
if (declarationPsiElement instanceof PsiMethod || declarationPsiElement instanceof JetNamedFunction) {
- callableMethod = typeMapper.mapToCallableMethod((PsiNamedElement) declarationPsiElement);
+ callableMethod = typeMapper.mapToCallableMethod((PsiNamedElement) declarationPsiElement, null);
}
else if (fd instanceof FunctionDescriptor) {
callableMethod = ClosureCodegen.asCallableMethod((FunctionDescriptor) fd);
@@ -1708,7 +1708,7 @@ public class ExpressionCodegen extends JetVisitor {
accessor = JetTypeMapper.mapToCallableMethod((PsiMethod) declaration);
}
else if (declaration instanceof JetNamedFunction) {
- accessor = typeMapper.mapToCallableMethod((JetNamedFunction) declaration);
+ accessor = typeMapper.mapToCallableMethod((JetNamedFunction) declaration, null);
}
else {
throw new UnsupportedOperationException("unknown accessor type: " + declaration);
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java
index 3c7e3abe22a..b42ac8f0e48 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java
@@ -35,7 +35,7 @@ public class FunctionCodegen {
}
public void gen(JetNamedFunction f) {
- Method method = state.getTypeMapper().mapToCallableMethod(f).getSignature();
+ Method method = state.getTypeMapper().mapToCallableMethod(f, owner.getContextKind()).getSignature();
final FunctionDescriptor functionDescriptor = state.getBindingContext().get(BindingContext.FUNCTION, f);
generateMethod(f, method, functionDescriptor);
}
@@ -86,10 +86,10 @@ public class FunctionCodegen {
OwnerKind kind = context.getContextKind();
- boolean isStatic = kind == OwnerKind.NAMESPACE;
+ boolean isStatic = kind == OwnerKind.NAMESPACE || kind == OwnerKind.TRAIT_IMPL;
if (isStatic) flags |= Opcodes.ACC_STATIC;
- boolean isAbstract = bodyExpressions == null;
+ boolean isAbstract = !isStatic && (bodyExpressions == null || TypeUtils.isInterface(functionDescriptor.getContainingDeclaration(), state.getBindingContext()));
if (isAbstract) flags |= Opcodes.ACC_ABSTRACT;
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java
index c047f642d57..8e342f3ef52 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java
@@ -70,8 +70,8 @@ public class GenerationState {
return factory.newVisitor(typeMapper.jvmName(aClass, OwnerKind.IMPLEMENTATION) + ".class");
}
- public ClassVisitor forClassDelegatingImplementation(ClassDescriptor aClass) {
- return factory.newVisitor(JetTypeMapper.jvmNameForDelegatingImplementation(aClass) + ".class");
+ public ClassVisitor forTraitImplementation(ClassDescriptor aClass) {
+ return factory.newVisitor(typeMapper.jvmName(aClass, OwnerKind.TRAIT_IMPL) + ".class");
}
public Pair forAnonymousSubclass(JetExpression expression) {
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
index a81e6c116da..e9f872046a6 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
@@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
+import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.lexer.JetTokens;
@@ -215,7 +216,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
return;
ConstructorDescriptor constructorDescriptor = state.getBindingContext().get(BindingContext.CONSTRUCTOR, myClass);
-// if (constructorDescriptor == null && !(myClass instanceof JetObjectDeclaration) && !isEnum(myClass)) return;
Method method;
CallableMethod callableMethod;
@@ -302,6 +302,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateInitializers(codegen, iv);
+ generateTraitMethods(codegen);
+
int curParam = 0;
List constructorParameters = getPrimaryConstructorParameters();
for (JetParameter parameter : constructorParameters) {
@@ -320,9 +322,67 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
mv.visitEnd();
}
- static boolean isEnum(JetClassOrObject myClass) {
- final JetModifierList modifierList = myClass.getModifierList();
- return modifierList != null && modifierList.hasModifier(JetTokens.ENUM_KEYWORD);
+ private void generateTraitMethods(ExpressionCodegen codegen) {
+ if(!(myClass instanceof JetClass) || ((JetClass)myClass).isTrait() || ((JetClass)myClass).hasModifier(JetTokens.ABSTRACT_KEYWORD))
+ return;
+
+ HashSet set = new HashSet();
+ getAbstractMethods(descriptor.getDefaultType(), set);
+ for(FunctionDescriptor fun: set) {
+ int flags = Opcodes.ACC_PUBLIC; // TODO.
+
+ Method function = state.getTypeMapper().mapSignature(fun.getName(), fun);
+
+ final MethodVisitor mv = v.visitMethod(flags, function.getName(), function.getDescriptor(), null, null);
+ mv.visitCode();
+
+ codegen.generateThisOrOuter(descriptor);
+
+ Type[] argTypes = function.getArgumentTypes();
+ InstructionAdapter iv = new InstructionAdapter(mv);
+ iv.load(0, JetTypeMapper.TYPE_OBJECT);
+ for (int i = 0, reg = 1; i < argTypes.length; i++) {
+ Type argType = argTypes[i];
+ iv.load(reg, argType);
+ //noinspection AssignmentToForLoopParameter
+ reg += argType.getSize();
+ }
+
+ String fdescriptor = function.getDescriptor().replace("(","(L" + state.getTypeMapper().jvmName((ClassDescriptor) fun.getContainingDeclaration(),OwnerKind.IMPLEMENTATION) + ";");
+ iv.invokestatic(state.getTypeMapper().jvmName((ClassDescriptor) fun.getContainingDeclaration(), OwnerKind.TRAIT_IMPL), function.getName(), fdescriptor);
+ iv.areturn(function.getReturnType());
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+ }
+
+ private void getAbstractMethods(JetType type, Set set) {
+ if(type.equals(JetStandardClasses.getAny())) {
+ return;
+ }
+
+ for(JetType superType : type.getConstructor().getSupertypes()) {
+ getAbstractMethods(superType, set);
+ }
+
+ PsiElement psiElement = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, type.getConstructor().getDeclarationDescriptor());
+ if(psiElement instanceof JetClass) {
+ JetClass jetClass = (JetClass) psiElement;
+ for(JetDeclaration decl : jetClass.getDeclarations()) {
+ if(decl instanceof JetNamedFunction) {
+ JetNamedFunction jetNamedFunction = (JetNamedFunction) decl;
+ FunctionDescriptor funDescriptor = state.getBindingContext().get(BindingContext.FUNCTION, decl);
+ set.removeAll(funDescriptor.getOverriddenDescriptors());
+
+ if(jetNamedFunction.getBodyExpression() == null || jetClass.isTrait()) {
+ set.add(funDescriptor);
+ }
+ }
+ }
+ }
+ else if(psiElement instanceof PsiClass) {
+ PsiClass psiClass = (PsiClass) psiElement;
+ }
}
@Nullable
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java
index 430458dfec5..5896a36e70b 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java
@@ -218,15 +218,15 @@ public class JetTypeMapper {
public String jvmName(JetClassObject classObject) {
final ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, classObject.getObjectDeclaration());
- return jvmName(descriptor, OwnerKind.IMPLEMENTATION);
+ return jvmName(descriptor, OwnerKind.IMPLEMENTATION);
}
- public boolean isInterface(ClassDescriptor jetClass, OwnerKind kind) {
+ public boolean isInterface(ClassDescriptor jetClass) {
PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, jetClass);
if (declaration instanceof JetObjectDeclaration) {
return false;
}
- return jetClass instanceof JetClass ? ((JetClass)jetClass).isTrait() : false;
+ return declaration instanceof JetClass && ((JetClass) declaration).isTrait();
}
private static String jetJvmName(ClassDescriptor jetClass, OwnerKind kind) {
@@ -236,6 +236,9 @@ public class JetTypeMapper {
else if (kind == OwnerKind.IMPLEMENTATION) {
return jvmNameForImplementation(jetClass);
}
+ else if (kind == OwnerKind.TRAIT_IMPL) {
+ return jvmNameForTraitImpl(jetClass);
+ }
else {
assert false : "Unsuitable kind";
return "java/lang/Object";
@@ -277,8 +280,8 @@ public class JetTypeMapper {
return jvmNameForInterface(descriptor);
}
- public static String jvmNameForDelegatingImplementation(ClassDescriptor descriptor) {
- return jvmNameForInterface(descriptor) + "$$DImpl";
+ private static String jvmNameForTraitImpl(ClassDescriptor descriptor) {
+ return jvmNameForInterface(descriptor) + "$$TImpl";
}
public String getOwner(DeclarationDescriptor descriptor, OwnerKind kind) {
@@ -426,7 +429,7 @@ public class JetTypeMapper {
}
- private Method mapSignature(JetNamedFunction f, List valueParameterTypes) {
+ private Method mapSignature(JetNamedFunction f, List valueParameterTypes, OwnerKind kind) {
final JetTypeReference receiverTypeRef = f.getReceiverTypeRef();
final JetType receiverType = receiverTypeRef == null ? null : bindingContext.get(BindingContext.TYPE, receiverTypeRef);
final List parameters = f.getValueParameters();
@@ -434,6 +437,13 @@ public class JetTypeMapper {
if (receiverType != null) {
parameterTypes.add(mapType(receiverType));
}
+ FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, f);
+ if(kind == OwnerKind.TRAIT_IMPL) {
+ JetType jetType = ((ClassDescriptor)functionDescriptor.getContainingDeclaration()).getDefaultType();
+ final Type type = mapType(jetType);
+ valueParameterTypes.add(type);
+ parameterTypes.add(type);
+ }
for (JetParameter parameter : parameters) {
final Type type = mapType(bindingContext.get(BindingContext.TYPE, parameter.getTypeReference()));
valueParameterTypes.add(type);
@@ -445,7 +455,6 @@ public class JetTypeMapper {
final JetTypeReference returnTypeRef = f.getReturnTypeRef();
Type returnType;
if (returnTypeRef == null) {
- final FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, f);
assert functionDescriptor != null;
final JetType type = functionDescriptor.getReturnType();
returnType = mapReturnType(type);
@@ -456,7 +465,7 @@ public class JetTypeMapper {
return new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
}
- public CallableMethod mapToCallableMethod(PsiNamedElement declaration) {
+ public CallableMethod mapToCallableMethod(PsiNamedElement declaration, OwnerKind kind) {
if (declaration instanceof PsiMethod) {
return mapToCallableMethod((PsiMethod) declaration);
}
@@ -468,7 +477,7 @@ public class JetTypeMapper {
assert functionDescriptor != null;
final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration();
final List valueParameterTypes = new ArrayList();
- Method descriptor = mapSignature(f, valueParameterTypes);
+ Method descriptor = mapSignature(f, valueParameterTypes, kind);
String owner;
int invokeOpcode;
boolean needsReceiver;
@@ -481,7 +490,7 @@ public class JetTypeMapper {
else if (functionParent instanceof ClassDescriptor) {
ClassDescriptor containingClass = (ClassDescriptor) functionParent;
owner = jvmName(containingClass, OwnerKind.IMPLEMENTATION);
- invokeOpcode = isInterface(containingClass, OwnerKind.INTERFACE)
+ invokeOpcode = isInterface(containingClass)
? Opcodes.INVOKEINTERFACE
: Opcodes.INVOKEVIRTUAL;
needsReceiver = true;
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/OwnerKind.java b/compiler/backend/src/org/jetbrains/jet/codegen/OwnerKind.java
index efb642c0096..f5259b2098b 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/OwnerKind.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/OwnerKind.java
@@ -11,8 +11,8 @@ public class OwnerKind {
}
public static final OwnerKind NAMESPACE = new OwnerKind("namespace");
- public static final OwnerKind INTERFACE = new OwnerKind("interface");
public static final OwnerKind IMPLEMENTATION = new OwnerKind("implementation");
+ public static final OwnerKind TRAIT_IMPL = new OwnerKind("trait implementation");
public static class DelegateKind extends OwnerKind {
private final StackValue delegate;
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java
index 686fe404c38..0de28e5e0fe 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java
@@ -42,24 +42,6 @@ public class PropertyCodegen {
generateGetter(p, propertyDescriptor);
generateSetter(p, propertyDescriptor);
}
- else if (kind == OwnerKind.INTERFACE) {
- final JetPropertyAccessor getter = p.getGetter();
- if ((getter != null && !getter.hasModifier(JetTokens.PRIVATE_KEYWORD) ||
- (getter == null && isExternallyAccessible(p)))) {
- v.visitMethod(Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC,
- getterName(p.getName()),
- state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor(),
- null, null);
- }
- final JetPropertyAccessor setter = p.getSetter();
- if ((setter != null && !setter.hasModifier(JetTokens.PRIVATE_KEYWORD) ||
- (setter == null && isExternallyAccessible(p) && p.isVar()))) {
- v.visitMethod(Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC,
- setterName(p.getName()),
- state.getTypeMapper().mapSetterSignature(propertyDescriptor).getDescriptor(),
- null, null);
- }
- }
else if (kind instanceof OwnerKind.DelegateKind) {
generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
if (propertyDescriptor.isVar()) {
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java
new file mode 100644
index 00000000000..8c87865c55b
--- /dev/null
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java
@@ -0,0 +1,39 @@
+package org.jetbrains.jet.codegen;
+
+import org.jetbrains.jet.lang.psi.JetClass;
+import org.jetbrains.jet.lang.psi.JetClassOrObject;
+import org.jetbrains.jet.lang.psi.JetDeclaration;
+import org.jetbrains.jet.lang.psi.JetNamedFunction;
+import org.jetbrains.jet.lexer.JetTokens;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Opcodes;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TraitImplBodyCodegen extends ClassBodyCodegen {
+ public TraitImplBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
+ super(aClass, context, v, state);
+ }
+
+ @Override
+ protected void generateDeclaration() {
+ v.visit(Opcodes.V1_6,
+ Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL,
+ jvmName(),
+ null,
+ "java/lang/Object",
+ new String[0]
+ );
+ v.visitSource(myClass.getContainingFile().getName(), null);
+ }
+
+ private String jvmName() {
+ return state.getTypeMapper().jvmName(descriptor, OwnerKind.TRAIT_IMPL);
+ }
+
+ @Override
+ protected void genNamedFunction(JetNamedFunction declaration, FunctionCodegen functionCodegen) {
+ super.genNamedFunction(declaration, functionCodegen); //To change body of overridden methods use File | Settings | File Templates.
+ }
+}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/PsiMethodCall.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/PsiMethodCall.java
index 496f610df9a..1025f23c5a6 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/PsiMethodCall.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/PsiMethodCall.java
@@ -25,7 +25,7 @@ public class PsiMethodCall implements IntrinsicMethod {
@Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element,
List arguments, StackValue receiver) {
- final CallableMethod callableMethod = codegen.getTypeMapper().mapToCallableMethod(myMethod);
+ final CallableMethod callableMethod = codegen.getTypeMapper().mapToCallableMethod(myMethod, null);
codegen.invokeMethodWithArguments(callableMethod, (JetCallExpression) element, receiver);
return StackValue.onStack(callableMethod.getSignature().getReturnType());
}
diff --git a/idea/testData/codegen/traits/simple.jet b/idea/testData/codegen/traits/simple.jet
new file mode 100644
index 00000000000..f8119547d2d
--- /dev/null
+++ b/idea/testData/codegen/traits/simple.jet
@@ -0,0 +1,12 @@
+trait SimpleClass : java.lang.Object {
+ fun foo() : String = "239 " + toString ()
+}
+
+class SimpleClassImpl() : SimpleClass {
+ override fun toString() = "SimpleClassImpl"
+}
+
+fun box() : String {
+ val c = SimpleClassImpl()
+ return if("239 SimpleClassImpl" == c.foo()) "OK" else "fail"
+}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/jet/codegen/TraitsTest.java b/idea/tests/org/jetbrains/jet/codegen/TraitsTest.java
new file mode 100644
index 00000000000..3558c42e455
--- /dev/null
+++ b/idea/tests/org/jetbrains/jet/codegen/TraitsTest.java
@@ -0,0 +1,13 @@
+package org.jetbrains.jet.codegen;
+
+public class TraitsTest extends CodegenTestCase {
+ @Override
+ protected String getPrefix() {
+ return "traits";
+ }
+
+ public void testSimple () throws Exception {
+ blackBoxFile("traits/simple.jet");
+ System.out.println(generateToText());
+ }
+}