KT-543 Support autoboxing primitive types (for method calls)
This commit is contained in:
@@ -10,13 +10,19 @@ import java.util.List;
|
||||
*/
|
||||
public class MethodCallExpression extends Expression {
|
||||
private final Expression myMethodCall;
|
||||
private final Element myParamList;
|
||||
private final List<Expression> myArguments;
|
||||
private List<String> myConversions;
|
||||
private final boolean myIsResultNullable;
|
||||
private final List<Type> myTypeParameters;
|
||||
|
||||
public MethodCallExpression(Expression methodCall, Element paramList, boolean nullable, List<Type> typeParameters) {
|
||||
public MethodCallExpression(Expression methodCall, List<Expression> arguments, boolean nullable, List<Type> typeParameters) {
|
||||
this(methodCall, arguments, AstUtil.createListWithEmptyString(arguments), nullable, typeParameters);
|
||||
}
|
||||
|
||||
public MethodCallExpression(Expression methodCall, List<Expression> arguments, List<String> conversions, boolean nullable, List<Type> 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<String> applyConversions = AstUtil.applyConversions(AstUtil.nodesToKotlin(myArguments), myConversions);
|
||||
return myMethodCall.toKotlin() + typeParamsToKotlin + "(" + AstUtil.join(applyConversions, COMMA_WITH_SPACE) + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String> createListWithEmptyString(final List<Expression> arguments) {
|
||||
final List<String> conversions = new LinkedList<String>();
|
||||
//noinspection UnusedDeclaration
|
||||
for (Expression argument : arguments) conversions.add("");
|
||||
return conversions;
|
||||
}
|
||||
|
||||
public static List<String> applyConversions(List<String> first, List<String> second) {
|
||||
List<String> result = new LinkedList<String>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String> conversions = new LinkedList<String>();
|
||||
PsiExpression[] arguments = expression.getArgumentList().getExpressions();
|
||||
//noinspection UnusedDeclaration
|
||||
for (final PsiExpression a : arguments) {
|
||||
conversions.add("");
|
||||
}
|
||||
|
||||
PsiMethod resolve = expression.resolveMethod();
|
||||
if (resolve != null) {
|
||||
List<PsiType> expectedTypes = new LinkedList<PsiType>();
|
||||
List<PsiType> actualTypes = new LinkedList<PsiType>();
|
||||
|
||||
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<String, String> typeMap = new HashMap<String, String>();
|
||||
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> T getOrElse(Map<T, T> map, T e, T orElse) {
|
||||
if (map.containsKey(e))
|
||||
return map.get(e);
|
||||
return orElse;
|
||||
}
|
||||
|
||||
private static String getPrimitiveTypeConversion(String type) {
|
||||
Map<String, String> conversions = new HashMap<String, String>();
|
||||
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<Type> typeParameters = reference != null ? typesToTypeList(reference.getTypeParameters()) : Collections.<Type>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));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package demo;
|
||||
|
||||
class Test {
|
||||
void putInt(Integer i) {}
|
||||
|
||||
void test() {
|
||||
byte b = 10;
|
||||
putInt(b);
|
||||
|
||||
Byte b2 = 10;
|
||||
putInt(b2);
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package demo;
|
||||
|
||||
class Test {
|
||||
void putInt(Integer i) {}
|
||||
|
||||
void test() {
|
||||
int i = 10;
|
||||
putInt(i);
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package demo;
|
||||
|
||||
class Test {
|
||||
void putInt(int i) {}
|
||||
|
||||
void test() {
|
||||
byte b = 10;
|
||||
putInt(b);
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user