equals generation for data classes
This commit is contained in:
@@ -126,7 +126,7 @@ public class ClosureCodegen extends GenerationStateAware {
|
||||
}
|
||||
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||
mv.visitCode();
|
||||
initSingletonField(fun, name.getAsmType(), cv, iv);
|
||||
initSingletonField(name.getAsmType(), iv);
|
||||
mv.visitInsn(RETURN);
|
||||
FunctionCodegen.endVisit(mv, "<clinit>", fun);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -44,6 +45,7 @@ import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -365,7 +367,7 @@ public class CodegenUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void initSingletonField(PsiElement element, Type classAsmType, ClassBuilder builder, InstructionAdapter iv) {
|
||||
public static void initSingletonField(Type classAsmType, InstructionAdapter iv) {
|
||||
iv.anew(classAsmType);
|
||||
iv.dup();
|
||||
iv.invokespecial(classAsmType.getInternalName(), "<init>", "()V");
|
||||
@@ -438,4 +440,99 @@ public class CodegenUtil {
|
||||
iv.xor(Type.LONG_TYPE);
|
||||
mv.visitInsn(L2I);
|
||||
}
|
||||
|
||||
static StackValue compareExpressionsOnStack(InstructionAdapter v, IElementType opToken, Type operandType) {
|
||||
if (operandType.getSort() == Type.OBJECT) {
|
||||
v.invokeinterface("java/lang/Comparable", "compareTo", "(Ljava/lang/Object;)I");
|
||||
v.iconst(0);
|
||||
operandType = Type.INT_TYPE;
|
||||
}
|
||||
return StackValue.cmp(opToken, operandType);
|
||||
}
|
||||
|
||||
static StackValue generateNullSafeEquals(
|
||||
InstructionAdapter v,
|
||||
IElementType opToken,
|
||||
boolean leftNullable,
|
||||
boolean rightNullable
|
||||
) {
|
||||
if (!leftNullable) {
|
||||
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
|
||||
if (opToken == JetTokens.EXCLEQ) {
|
||||
invertBoolean(v);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (rightNullable) {
|
||||
v.dup2(); // left right left right
|
||||
Label rightNull = new Label();
|
||||
v.ifnull(rightNull);
|
||||
Label leftNull = new Label();
|
||||
v.ifnull(leftNull);
|
||||
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
|
||||
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
|
||||
invertBoolean(v);
|
||||
}
|
||||
Label end = new Label();
|
||||
v.goTo(end);
|
||||
v.mark(rightNull);
|
||||
// left right left
|
||||
Label bothNull = new Label();
|
||||
v.ifnull(bothNull);
|
||||
v.mark(leftNull);
|
||||
v.pop2();
|
||||
v.iconst(opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ ? 1 : 0);
|
||||
v.goTo(end);
|
||||
v.mark(bothNull);
|
||||
v.pop2();
|
||||
v.iconst(opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ ? 0 : 1);
|
||||
v.mark(end);
|
||||
}
|
||||
else {
|
||||
v.dup2(); // left right left right
|
||||
v.pop();
|
||||
Label leftNull = new Label();
|
||||
v.ifnull(leftNull);
|
||||
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
|
||||
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
|
||||
invertBoolean(v);
|
||||
}
|
||||
Label end = new Label();
|
||||
v.goTo(end);
|
||||
// left right
|
||||
v.mark(leftNull);
|
||||
v.pop2();
|
||||
v.iconst(opToken == JetTokens.EXCLEQ ? 1 : 0);
|
||||
v.mark(end);
|
||||
}
|
||||
}
|
||||
|
||||
return StackValue.onStack(Type.BOOLEAN_TYPE);
|
||||
}
|
||||
|
||||
static void invertBoolean(InstructionAdapter v) {
|
||||
v.iconst(1);
|
||||
v.xor(Type.INT_TYPE);
|
||||
}
|
||||
|
||||
public static StackValue generateEqualsForExpressionsOnStack(
|
||||
InstructionAdapter v,
|
||||
IElementType opToken,
|
||||
Type leftType,
|
||||
Type rightType,
|
||||
boolean leftNullable,
|
||||
boolean rightNullable
|
||||
) {
|
||||
if ((isNumberPrimitive(leftType) || leftType.getSort() == Type.BOOLEAN) && leftType == rightType) {
|
||||
return compareExpressionsOnStack(v, opToken, leftType);
|
||||
}
|
||||
else {
|
||||
if (opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) {
|
||||
return StackValue.cmp(opToken, leftType);
|
||||
}
|
||||
else {
|
||||
return generateNullSafeEquals(v, opToken, leftNullable, rightNullable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2256,7 +2256,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
else {
|
||||
invokeFunctionByReference(expression.getOperationReference());
|
||||
if (inverted) {
|
||||
invertBoolean();
|
||||
invertBoolean(v);
|
||||
}
|
||||
}
|
||||
return StackValue.onStack(Type.BOOLEAN_TYPE);
|
||||
@@ -2297,7 +2297,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
|
||||
v.and(Type.INT_TYPE);
|
||||
if (inverted) {
|
||||
invertBoolean();
|
||||
invertBoolean(v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2357,10 +2357,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
|
||||
if (isPrimitive(leftType)) // both are primitive
|
||||
{
|
||||
return generateEqualsForExpressionsOnStack(opToken, leftType, rightType, false, false);
|
||||
return generateEqualsForExpressionsOnStack(v, opToken, leftType, rightType, false, false);
|
||||
}
|
||||
|
||||
return generateEqualsForExpressionsOnStack(opToken, leftType, rightType, leftJetType.isNullable(), rightJetType.isNullable());
|
||||
return generateEqualsForExpressionsOnStack(v, opToken, leftType, rightType, leftJetType.isNullable(), rightJetType.isNullable());
|
||||
}
|
||||
|
||||
private StackValue genCmpWithNull(JetExpression exp, Type expType, IElementType opToken) {
|
||||
@@ -2379,81 +2379,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
return StackValue.onStack(Type.BOOLEAN_TYPE);
|
||||
}
|
||||
|
||||
public StackValue generateEqualsForExpressionsOnStack(
|
||||
IElementType opToken,
|
||||
Type leftType,
|
||||
Type rightType,
|
||||
boolean leftNullable,
|
||||
boolean rightNullable
|
||||
) {
|
||||
if ((CodegenUtil.isNumberPrimitive(leftType) || leftType.getSort() == Type.BOOLEAN) && leftType == rightType) {
|
||||
return compareExpressionsOnStack(opToken, leftType);
|
||||
}
|
||||
else {
|
||||
if (opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) {
|
||||
return StackValue.cmp(opToken, leftType);
|
||||
}
|
||||
else {
|
||||
return generateNullSafeEquals(opToken, leftNullable, rightNullable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private StackValue generateNullSafeEquals(IElementType opToken, boolean leftNullable, boolean rightNullable) {
|
||||
if (!leftNullable) {
|
||||
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
|
||||
if (opToken == JetTokens.EXCLEQ) {
|
||||
invertBoolean();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (rightNullable) {
|
||||
v.dup2(); // left right left right
|
||||
Label rightNull = new Label();
|
||||
v.ifnull(rightNull);
|
||||
Label leftNull = new Label();
|
||||
v.ifnull(leftNull);
|
||||
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
|
||||
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
|
||||
invertBoolean();
|
||||
}
|
||||
Label end = new Label();
|
||||
v.goTo(end);
|
||||
v.mark(rightNull);
|
||||
// left right left
|
||||
Label bothNull = new Label();
|
||||
v.ifnull(bothNull);
|
||||
v.mark(leftNull);
|
||||
v.pop2();
|
||||
v.iconst(opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ ? 1 : 0);
|
||||
v.goTo(end);
|
||||
v.mark(bothNull);
|
||||
v.pop2();
|
||||
v.iconst(opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ ? 0 : 1);
|
||||
v.mark(end);
|
||||
}
|
||||
else {
|
||||
v.dup2(); // left right left right
|
||||
v.pop();
|
||||
Label leftNull = new Label();
|
||||
v.ifnull(leftNull);
|
||||
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
|
||||
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
|
||||
invertBoolean();
|
||||
}
|
||||
Label end = new Label();
|
||||
v.goTo(end);
|
||||
// left right
|
||||
v.mark(leftNull);
|
||||
v.pop2();
|
||||
v.iconst(opToken == JetTokens.EXCLEQ ? 1 : 0);
|
||||
v.mark(end);
|
||||
}
|
||||
}
|
||||
|
||||
return StackValue.onStack(Type.BOOLEAN_TYPE);
|
||||
}
|
||||
|
||||
private StackValue generateElvis(JetBinaryExpression expression) {
|
||||
final Type exprType = expressionType(expression);
|
||||
JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getLeft());
|
||||
@@ -2490,16 +2415,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
private StackValue generateCompareOp(JetExpression left, JetExpression right, IElementType opToken, Type operandType) {
|
||||
gen(left, operandType);
|
||||
gen(right, operandType);
|
||||
return compareExpressionsOnStack(opToken, operandType);
|
||||
}
|
||||
|
||||
private StackValue compareExpressionsOnStack(IElementType opToken, Type operandType) {
|
||||
if (operandType.getSort() == Type.OBJECT) {
|
||||
v.invokeinterface("java/lang/Comparable", "compareTo", "(Ljava/lang/Object;)I");
|
||||
v.iconst(0);
|
||||
operandType = Type.INT_TYPE;
|
||||
}
|
||||
return StackValue.cmp(opToken, operandType);
|
||||
return compareExpressionsOnStack(v, opToken, operandType);
|
||||
}
|
||||
|
||||
private StackValue generateAssignmentExpression(JetBinaryExpression expression) {
|
||||
@@ -3294,7 +3210,7 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
patternIsNullable = condJetType != null && condJetType.isNullable();
|
||||
}
|
||||
gen(patternExpression, condType);
|
||||
return generateEqualsForExpressionsOnStack(JetTokens.EQEQ, subjectType, condType, expressionToMatchIsNullable,
|
||||
return generateEqualsForExpressionsOnStack(v, JetTokens.EQEQ, subjectType, condType, expressionToMatchIsNullable,
|
||||
patternIsNullable);
|
||||
}
|
||||
else {
|
||||
@@ -3420,7 +3336,7 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
//invokeFunctionNoParams(op, Type.BOOLEAN_TYPE, v);
|
||||
invokeFunctionByReference(operationReference);
|
||||
if (inverted) {
|
||||
invertBoolean();
|
||||
invertBoolean(v);
|
||||
}
|
||||
}
|
||||
return StackValue.onStack(Type.BOOLEAN_TYPE);
|
||||
@@ -3446,11 +3362,6 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
invokeFunction(call, StackValue.none(), resolvedCall);
|
||||
}
|
||||
|
||||
private void invertBoolean() {
|
||||
v.iconst(1);
|
||||
v.xor(Type.INT_TYPE);
|
||||
}
|
||||
|
||||
private boolean isIntRangeExpr(JetExpression rangeExpression) {
|
||||
if (rangeExpression instanceof JetBinaryExpression) {
|
||||
JetBinaryExpression binaryExpression = (JetBinaryExpression) rangeExpression;
|
||||
|
||||
@@ -386,21 +386,66 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generateDataClassEqualsMethod(List<PropertyDescriptor> properties) {
|
||||
// todo: this is fake implementation
|
||||
|
||||
final MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, superClassAsmType.getInternalName(), "equals", "(Ljava/lang/Object;)Z");
|
||||
mv.visitInsn(IRETURN);
|
||||
mv.visitMaxs(-1,-1);
|
||||
mv.visitEnd();
|
||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
|
||||
mv.visitCode();
|
||||
Label eq = new Label();
|
||||
Label ne = new Label();
|
||||
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
iv.load(1, AsmTypeConstants.OBJECT_TYPE);
|
||||
iv.ifacmpeq(eq);
|
||||
|
||||
iv.load(1, AsmTypeConstants.OBJECT_TYPE);
|
||||
iv.instanceOf(classAsmType);
|
||||
iv.ifeq(ne);
|
||||
|
||||
iv.load(1, AsmTypeConstants.OBJECT_TYPE);
|
||||
iv.checkcast(classAsmType);
|
||||
iv.store(2, AsmTypeConstants.OBJECT_TYPE);
|
||||
|
||||
for (PropertyDescriptor propertyDescriptor : properties) {
|
||||
final JetType type = propertyDescriptor.getType();
|
||||
final Type asmType = typeMapper.mapType(type);
|
||||
|
||||
genPropertyOnStack(iv, propertyDescriptor, 0);
|
||||
genPropertyOnStack(iv, propertyDescriptor, 2);
|
||||
|
||||
if (asmType.getSort() == Type.ARRAY) {
|
||||
final Type elementType = CodegenUtil.correctElementType(asmType);
|
||||
if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
|
||||
iv.invokestatic("java/util/Arrays", "equals", "([Ljava/lang/Object;[Ljava/lang/Object;)Z");
|
||||
}
|
||||
else {
|
||||
iv.invokestatic("java/util/Arrays", "equals", "([" + elementType.getDescriptor() + "[" + elementType.getDescriptor() + ")Z");
|
||||
}
|
||||
}
|
||||
else {
|
||||
final StackValue value =
|
||||
generateEqualsForExpressionsOnStack(iv, JetTokens.EQEQ, asmType, asmType, type.isNullable(), type.isNullable());
|
||||
value.put(Type.BOOLEAN_TYPE, iv);
|
||||
}
|
||||
|
||||
iv.ifeq(ne);
|
||||
}
|
||||
|
||||
iv.mark(eq);
|
||||
iv.iconst(1);
|
||||
iv.areturn(Type.INT_TYPE);
|
||||
|
||||
iv.mark(ne);
|
||||
iv.iconst(0);
|
||||
iv.areturn(Type.INT_TYPE);
|
||||
|
||||
FunctionCodegen.endVisit(mv, "equals", myClass);
|
||||
}
|
||||
|
||||
private void generateDataClassHashCodeMethod(List<PropertyDescriptor> properties) {
|
||||
final MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "hashCode", "()I", null, null);
|
||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
|
||||
mv.visitCode();
|
||||
boolean first = true;
|
||||
for (PropertyDescriptor propertyDescriptor : properties) {
|
||||
if (!first) {
|
||||
@@ -408,7 +453,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
iv.mul(Type.INT_TYPE);
|
||||
}
|
||||
|
||||
genPropertyOnStack(iv, propertyDescriptor);
|
||||
genPropertyOnStack(iv, propertyDescriptor, 0);
|
||||
|
||||
Label ifNull = null;
|
||||
if (propertyDescriptor.getType().isNullable()) {
|
||||
@@ -438,14 +483,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
mv.visitInsn(IRETURN);
|
||||
mv.visitMaxs(-1, -1);
|
||||
mv.visitEnd();
|
||||
|
||||
FunctionCodegen.endVisit(mv, "hashCode", myClass);
|
||||
}
|
||||
|
||||
private void generateDataClassToStringMethod(List<PropertyDescriptor> properties) {
|
||||
final MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null);
|
||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
|
||||
mv.visitCode();
|
||||
generateStringBuilderConstructor(iv);
|
||||
|
||||
boolean first = true;
|
||||
@@ -459,7 +505,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
invokeAppendMethod(iv, JAVA_STRING_TYPE);
|
||||
|
||||
Type type = genPropertyOnStack(iv, propertyDescriptor);
|
||||
Type type = genPropertyOnStack(iv, propertyDescriptor, 0);
|
||||
|
||||
if (type.getSort() == Type.ARRAY) {
|
||||
final Type elementType = correctElementType(type);
|
||||
@@ -486,8 +532,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
FunctionCodegen.endVisit(mv, "toString", myClass);
|
||||
}
|
||||
|
||||
private Type genPropertyOnStack(InstructionAdapter iv, PropertyDescriptor propertyDescriptor) {
|
||||
iv.load(0, classAsmType);
|
||||
private Type genPropertyOnStack(InstructionAdapter iv, PropertyDescriptor propertyDescriptor, int index) {
|
||||
iv.load(index, classAsmType);
|
||||
// todo: seems to be more correct - need to be changed in sync with 'componentX' generation and related tests
|
||||
// final Method
|
||||
// method = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
|
||||
@@ -714,7 +760,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
staticInitializerChunks.add(new CodeChunk() {
|
||||
@Override
|
||||
public void generate(InstructionAdapter iv) {
|
||||
initSingletonField(myClass, classAsmType, v, iv);
|
||||
initSingletonField(classAsmType, iv);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -20,13 +20,14 @@ import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
|
||||
import org.jetbrains.jet.codegen.CodegenUtil;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.lang.psi.JetCallExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
@@ -74,8 +75,9 @@ public class Equals implements IntrinsicMethod {
|
||||
codegen.gen(rightExpr).put(AsmTypeConstants.OBJECT_TYPE, v);
|
||||
|
||||
assert rightType != null;
|
||||
return codegen
|
||||
.generateEqualsForExpressionsOnStack(JetTokens.EQEQ, AsmTypeConstants.OBJECT_TYPE, AsmTypeConstants.OBJECT_TYPE, leftNullable,
|
||||
return CodegenUtil
|
||||
.generateEqualsForExpressionsOnStack(v, JetTokens.EQEQ, AsmTypeConstants.OBJECT_TYPE, AsmTypeConstants.OBJECT_TYPE,
|
||||
leftNullable,
|
||||
rightType.isNullable());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
data class A(val v: Array<Int>)
|
||||
|
||||
fun box() : String {
|
||||
if(A(array(0,1,2)) != A(array(0,1,2))) return "fail"
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class Dummy {
|
||||
fun equals(other: Any?) = true
|
||||
}
|
||||
|
||||
open data class A(val v: Any)
|
||||
|
||||
class B(v: Any) : A(v)
|
||||
|
||||
fun box() : String {
|
||||
val a = A(Dummy())
|
||||
val b = B(Dummy())
|
||||
return if(b == a) "OK" else "fail"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
data class A(val v: IntArray)
|
||||
|
||||
fun box() : String {
|
||||
if(A(intArray(0,1,2)) != A(intArray(0,1,2))) return "fail"
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class Dummy {
|
||||
fun equals(other: Any?) = true
|
||||
}
|
||||
|
||||
data class A(val v: Any?)
|
||||
|
||||
fun box() : String {
|
||||
val a = A(Dummy())
|
||||
val b: A? = null
|
||||
return if(a != b && b != a) "OK" else "fail"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
data class A()
|
||||
|
||||
fun box() : String {
|
||||
val a = A()
|
||||
val b = a
|
||||
return if(b == a) "OK" else "fail"
|
||||
}
|
||||
@@ -26,7 +26,7 @@ import java.io.File;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.jet.codegen.AbstractDataClassCodegenTest}. DO NOT MODIFY MANUALLY */
|
||||
@TestMetadata("compiler/testData/codegen/dataClasses")
|
||||
@InnerTestClasses({DataClassCodegenTestGenerated.Hashcode.class, DataClassCodegenTestGenerated.Tostring.class})
|
||||
@InnerTestClasses({DataClassCodegenTestGenerated.Equals.class, DataClassCodegenTestGenerated.Hashcode.class, DataClassCodegenTestGenerated.Tostring.class})
|
||||
public class DataClassCodegenTestGenerated extends AbstractDataClassCodegenTest {
|
||||
public void testAllFilesPresentInDataClasses() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.codegen.AbstractDataClassCodegenTest", new File("compiler/testData/codegen/dataClasses"), "kt", true);
|
||||
@@ -82,6 +82,39 @@ public class DataClassCodegenTestGenerated extends AbstractDataClassCodegenTest
|
||||
blackBoxFileByFullPath("compiler/testData/codegen/dataClasses/unitComponent.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/dataClasses/equals")
|
||||
public static class Equals extends AbstractDataClassCodegenTest {
|
||||
public void testAllFilesPresentInEquals() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.codegen.AbstractDataClassCodegenTest", new File("compiler/testData/codegen/dataClasses/equals"), "kt", true);
|
||||
}
|
||||
|
||||
@TestMetadata("genericarray.kt")
|
||||
public void testGenericarray() throws Exception {
|
||||
blackBoxFileByFullPath("compiler/testData/codegen/dataClasses/equals/genericarray.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("instanceof.kt")
|
||||
public void testInstanceof() throws Exception {
|
||||
blackBoxFileByFullPath("compiler/testData/codegen/dataClasses/equals/instanceof.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("intarray.kt")
|
||||
public void testIntarray() throws Exception {
|
||||
blackBoxFileByFullPath("compiler/testData/codegen/dataClasses/equals/intarray.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nullother.kt")
|
||||
public void testNullother() throws Exception {
|
||||
blackBoxFileByFullPath("compiler/testData/codegen/dataClasses/equals/nullother.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sameinstance.kt")
|
||||
public void testSameinstance() throws Exception {
|
||||
blackBoxFileByFullPath("compiler/testData/codegen/dataClasses/equals/sameinstance.kt");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/dataClasses/hashcode")
|
||||
public static class Hashcode extends AbstractDataClassCodegenTest {
|
||||
public void testAllFilesPresentInHashcode() throws Exception {
|
||||
@@ -181,6 +214,7 @@ public class DataClassCodegenTestGenerated extends AbstractDataClassCodegenTest
|
||||
public static Test suite() {
|
||||
TestSuite suite = new TestSuite("DataClassCodegenTestGenerated");
|
||||
suite.addTestSuite(DataClassCodegenTestGenerated.class);
|
||||
suite.addTestSuite(Equals.class);
|
||||
suite.addTestSuite(Hashcode.class);
|
||||
suite.addTestSuite(Tostring.class);
|
||||
return suite;
|
||||
|
||||
Reference in New Issue
Block a user