diff --git a/src/org/jetbrains/jet/j2k/ast/MethodCallExpression.java b/src/org/jetbrains/jet/j2k/ast/MethodCallExpression.java index 0c8a1d21536..5bfc87b69f5 100644 --- a/src/org/jetbrains/jet/j2k/ast/MethodCallExpression.java +++ b/src/org/jetbrains/jet/j2k/ast/MethodCallExpression.java @@ -10,13 +10,19 @@ import java.util.List; */ public class MethodCallExpression extends Expression { private final Expression myMethodCall; - private final Element myParamList; + private final List myArguments; + private List myConversions; private final boolean myIsResultNullable; private final List myTypeParameters; - public MethodCallExpression(Expression methodCall, Element paramList, boolean nullable, List typeParameters) { + public MethodCallExpression(Expression methodCall, List arguments, boolean nullable, List typeParameters) { + this(methodCall, arguments, AstUtil.createListWithEmptyString(arguments), nullable, typeParameters); + } + + public MethodCallExpression(Expression methodCall, List arguments, List conversions, boolean nullable, List typeParameters) { myMethodCall = methodCall; - myParamList = paramList; + myArguments = arguments; + myConversions = conversions; myIsResultNullable = nullable; myTypeParameters = typeParameters; } @@ -30,6 +36,7 @@ public class MethodCallExpression extends Expression { @Override public String toKotlin() { String typeParamsToKotlin = myTypeParameters.size() > 0 ? "<" + AstUtil.joinNodes(myTypeParameters, COMMA_WITH_SPACE) + ">" : EMPTY; - return myMethodCall.toKotlin() + typeParamsToKotlin + "(" + myParamList.toKotlin() + ")"; + List applyConversions = AstUtil.applyConversions(AstUtil.nodesToKotlin(myArguments), myConversions); + return myMethodCall.toKotlin() + typeParamsToKotlin + "(" + AstUtil.join(applyConversions, COMMA_WITH_SPACE) + ")"; } } diff --git a/src/org/jetbrains/jet/j2k/util/AstUtil.java b/src/org/jetbrains/jet/j2k/util/AstUtil.java index d5715267101..a814767880a 100644 --- a/src/org/jetbrains/jet/j2k/util/AstUtil.java +++ b/src/org/jetbrains/jet/j2k/util/AstUtil.java @@ -1,5 +1,6 @@ package org.jetbrains.jet.j2k.util; +import org.jetbrains.jet.j2k.ast.Expression; import org.jetbrains.jet.j2k.ast.INode; import java.util.LinkedList; @@ -44,4 +45,23 @@ public class AstUtil { public static String upperFirstCharacter(String string) { return string.substring(0, 1).toUpperCase() + string.substring(1); } + + public static List createListWithEmptyString(final List arguments) { + final List conversions = new LinkedList(); + //noinspection UnusedDeclaration + for (Expression argument : arguments) conversions.add(""); + return conversions; + } + + public static List applyConversions(List first, List second) { + List result = new LinkedList(); + assert first.size() == second.size() : "Lists must have the same size."; + for (int i = 0; i < first.size(); i++) { + if (second.get(i).isEmpty()) + result.add(first.get(i)); + else + result.add("(" + first.get(i) + ")" + second.get(i)); + } + return result; + } } diff --git a/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java b/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java index 7654d99f923..9a587d8c4ad 100644 --- a/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java +++ b/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java @@ -7,8 +7,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.j2k.Converter; import org.jetbrains.jet.j2k.ast.*; -import java.util.Collections; -import java.util.List; +import java.util.*; import static org.jetbrains.jet.j2k.Converter.*; @@ -190,14 +189,93 @@ public class ExpressionVisitor extends StatementVisitor { @Override public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) { super.visitMethodCallExpression(expression); - if (!SuperVisitor.isSuper(expression.getMethodExpression()) || !isInsidePrimaryConstructor(expression)) + if (!SuperVisitor.isSuper(expression.getMethodExpression()) || !isInsidePrimaryConstructor(expression)) { + List conversions = new LinkedList(); + PsiExpression[] arguments = expression.getArgumentList().getExpressions(); + //noinspection UnusedDeclaration + for (final PsiExpression a : arguments) { + conversions.add(""); + } + + PsiMethod resolve = expression.resolveMethod(); + if (resolve != null) { + List expectedTypes = new LinkedList(); + List actualTypes = new LinkedList(); + + for (PsiParameter p : resolve.getParameterList().getParameters()) + expectedTypes.add(p.getType()); + + for (PsiExpression e : arguments) + actualTypes.add(e.getType()); + + assert actualTypes.size() == expectedTypes.size() : "The type list must have the same length"; + + for (int i = 0; i < actualTypes.size(); i++) { + PsiType actual = actualTypes.get(i); + PsiType expected = expectedTypes.get(i); + + if (isConversionNeeded(actual, expected)) { + conversions.set(i, getPrimitiveTypeConversion(expected.getCanonicalText())); + } + } + } + myResult = // TODO: not resolved new MethodCallExpression( expressionToExpression(expression.getMethodExpression()), - elementToElement(expression.getArgumentList()), + expressionsToExpressionList(arguments), + conversions, typeToType(expression.getType()).isNullable(), typesToTypeList(expression.getTypeArguments()) ); + } + } + + private static boolean isConversionNeeded(final PsiType actual, final PsiType expected) { + Map typeMap = new HashMap(); + typeMap.put("java.lang.Byte", "byte"); + typeMap.put("java.lang.Short", "short"); + typeMap.put("java.lang.Integer", "int"); + typeMap.put("java.lang.Long", "long"); + typeMap.put("java.lang.Float", "float"); + typeMap.put("java.lang.Double", "double"); + typeMap.put("java.lang.Character", "char"); + String expectedStr = expected.getCanonicalText(); + String actualStr = actual.getCanonicalText(); + boolean o1 = getOrElse(typeMap, actualStr, "").equals(expectedStr); + boolean o2 = getOrElse(typeMap, expectedStr, "").equals(actualStr); + return !actualStr.equals(expectedStr) && (!(o1 ^ o2)); + } + + + + private static T getOrElse(Map map, T e, T orElse) { + if (map.containsKey(e)) + return map.get(e); + return orElse; + } + + private static String getPrimitiveTypeConversion(String type) { + Map conversions = new HashMap(); + conversions.put("byte", "byt"); + conversions.put("short", "sht"); + conversions.put("int", "int"); + conversions.put("long", "lng"); + conversions.put("float", "flt"); + conversions.put("double", "dbl"); + conversions.put("char", "chr"); + + conversions.put("java.lang.Byte", "byt"); + conversions.put("java.lang.Short", "sht"); + conversions.put("java.lang.Integer", "int"); + conversions.put("java.lang.Long", "lng"); + conversions.put("java.lang.Float", "flt"); + conversions.put("java.lang.Double", "dbl"); + conversions.put("java.lang.Character", "chr"); + + if (conversions.containsKey(type)) + return "." + conversions.get(type); + return ""; } @Override @@ -224,22 +302,24 @@ public class ExpressionVisitor extends StatementVisitor { final PsiMethod constructor = expression.resolveMethod(); PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference(); final boolean isNotConvertedClass = classReference != null && !Converter.getClassIdentifiers().contains(classReference.getQualifiedName()); + PsiExpressionList argumentList = expression.getArgumentList(); if (constructor == null || isConstructorPrimary(constructor) || isNotConvertedClass) { return new NewClassExpression( expressionToExpression(expression.getQualifier()), elementToElement(classReference), - elementToElement(expression.getArgumentList()), + elementToElement(argumentList), anonymousClass != null ? anonymousClassToAnonymousClass(anonymousClass) : null ); } // is constructor secondary final PsiJavaCodeReferenceElement reference = expression.getClassReference(); final List typeParameters = reference != null ? typesToTypeList(reference.getTypeParameters()) : Collections.emptyList(); + PsiExpression[] expressions = argumentList != null ? argumentList.getExpressions() : new PsiExpression[]{}; return new CallChainExpression( new IdentifierImpl(constructor.getName(), false), new MethodCallExpression( new IdentifierImpl("init"), - elementToElement(expression.getArgumentList()), + expressionsToExpressionList(expressions), false, typeParameters)); } diff --git a/testData/ast/issues/file/kt-543-boxed.jav b/testData/ast/issues/file/kt-543-boxed.jav new file mode 100644 index 00000000000..e1f28f04faa --- /dev/null +++ b/testData/ast/issues/file/kt-543-boxed.jav @@ -0,0 +1,13 @@ +package demo; + +class Test { + void putInt(Integer i) {} + + void test() { + byte b = 10; + putInt(b); + + Byte b2 = 10; + putInt(b2); + } +} \ No newline at end of file diff --git a/testData/ast/issues/file/kt-543-boxed.kt b/testData/ast/issues/file/kt-543-boxed.kt new file mode 100644 index 00000000000..dafbd546c92 --- /dev/null +++ b/testData/ast/issues/file/kt-543-boxed.kt @@ -0,0 +1,11 @@ +namespace demo +open class Test() { +open fun putInt(i : Int?) : Unit { +} +open fun test() : Unit { +var b : Byte = 10 +putInt((b).int) +var b2 : Byte? = 10 +putInt((b2).int) +} +} \ No newline at end of file diff --git a/testData/ast/issues/file/kt-543-mixed.jav b/testData/ast/issues/file/kt-543-mixed.jav new file mode 100644 index 00000000000..1193a5403bb --- /dev/null +++ b/testData/ast/issues/file/kt-543-mixed.jav @@ -0,0 +1,10 @@ +package demo; + +class Test { + void putInt(Integer i) {} + + void test() { + int i = 10; + putInt(i); + } +} \ No newline at end of file diff --git a/testData/ast/issues/file/kt-543-mixed.kt b/testData/ast/issues/file/kt-543-mixed.kt new file mode 100644 index 00000000000..1fd99286342 --- /dev/null +++ b/testData/ast/issues/file/kt-543-mixed.kt @@ -0,0 +1,9 @@ +namespace demo +open class Test() { +open fun putInt(i : Int?) : Unit { +} +open fun test() : Unit { +var i : Int = 10 +putInt(i) +} +} \ No newline at end of file diff --git a/testData/ast/issues/file/kt-543.jav b/testData/ast/issues/file/kt-543.jav new file mode 100644 index 00000000000..c5e0e602076 --- /dev/null +++ b/testData/ast/issues/file/kt-543.jav @@ -0,0 +1,10 @@ +package demo; + +class Test { + void putInt(int i) {} + + void test() { + byte b = 10; + putInt(b); + } +} \ No newline at end of file diff --git a/testData/ast/issues/file/kt-543.kt b/testData/ast/issues/file/kt-543.kt new file mode 100644 index 00000000000..9e06bf3f48c --- /dev/null +++ b/testData/ast/issues/file/kt-543.kt @@ -0,0 +1,9 @@ +namespace demo +open class Test() { +open fun putInt(i : Int) : Unit { +} +open fun test() : Unit { +var b : Byte = 10 +putInt((b).int) +} +} \ No newline at end of file