KT-792 Support autoboxing primitive types (for constructor invocations)
This commit is contained in:
@@ -2,25 +2,32 @@ package org.jetbrains.jet.j2k.ast;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.j2k.util.AstUtil;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ignatov
|
* @author ignatov
|
||||||
*/
|
*/
|
||||||
public class NewClassExpression extends Expression {
|
public class NewClassExpression extends Expression {
|
||||||
private final Element myName;
|
private final Element myName;
|
||||||
private final Element myArguments;
|
private final List<Expression> myArguments;
|
||||||
private Expression myQualifier;
|
private Expression myQualifier;
|
||||||
|
private List<String> myConversions;
|
||||||
private AnonymousClass myAnonymousClass = null;
|
private AnonymousClass myAnonymousClass = null;
|
||||||
|
|
||||||
public NewClassExpression(Element name, Element arguments) {
|
public NewClassExpression(Element name, List<Expression> arguments) {
|
||||||
myName = name;
|
myName = name;
|
||||||
myQualifier = EMPTY_EXPRESSION;
|
myQualifier = EMPTY_EXPRESSION;
|
||||||
myArguments = arguments;
|
myArguments = arguments;
|
||||||
|
myConversions = AstUtil.createListWithEmptyString(arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NewClassExpression(Expression qualifier, Element name, Element arguments, @Nullable AnonymousClass anonymousClass) {
|
public NewClassExpression(@NotNull Expression qualifier, @NotNull Element name, @NotNull List<Expression> arguments,
|
||||||
|
@NotNull List<String> conversions, @Nullable AnonymousClass anonymousClass) {
|
||||||
this(name, arguments);
|
this(name, arguments);
|
||||||
myQualifier = qualifier;
|
myQualifier = qualifier;
|
||||||
|
myConversions = conversions;
|
||||||
myAnonymousClass = anonymousClass;
|
myAnonymousClass = anonymousClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,8 +36,10 @@ public class NewClassExpression extends Expression {
|
|||||||
public String toKotlin() {
|
public String toKotlin() {
|
||||||
final String callOperator = myQualifier.isNullable() ? QUESTDOT : DOT;
|
final String callOperator = myQualifier.isNullable() ? QUESTDOT : DOT;
|
||||||
final String qualifier = myQualifier.isEmpty() ? EMPTY : myQualifier.toKotlin() + callOperator;
|
final String qualifier = myQualifier.isEmpty() ? EMPTY : myQualifier.toKotlin() + callOperator;
|
||||||
|
List<String> applyConversions = AstUtil.applyConversions(AstUtil.nodesToKotlin(myArguments), myConversions);
|
||||||
|
String appliedArguments = AstUtil.join(applyConversions, COMMA_WITH_SPACE);
|
||||||
return myAnonymousClass != null ?
|
return myAnonymousClass != null ?
|
||||||
"object" + SPACE + ":" + SPACE + qualifier + myName.toKotlin() + "(" + myArguments.toKotlin() + ")" + myAnonymousClass.toKotlin() :
|
"object" + SPACE + ":" + SPACE + qualifier + myName.toKotlin() + "(" + appliedArguments + ")" + myAnonymousClass.toKotlin() :
|
||||||
qualifier + myName.toKotlin() + "(" + myArguments.toKotlin() + ")";
|
qualifier + myName.toKotlin() + "(" + appliedArguments + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,47 +191,52 @@ public class ExpressionVisitor extends StatementVisitor {
|
|||||||
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
|
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
|
||||||
super.visitMethodCallExpression(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
|
myResult = // TODO: not resolved
|
||||||
new MethodCallExpression(
|
new MethodCallExpression(
|
||||||
expressionToExpression(expression.getMethodExpression()),
|
expressionToExpression(expression.getMethodExpression()),
|
||||||
expressionsToExpressionList(arguments),
|
expressionsToExpressionList(expression.getArgumentList().getExpressions()),
|
||||||
conversions,
|
createConversions(expression),
|
||||||
typeToType(expression.getType()).isNullable(),
|
typeToType(expression.getType()).isNullable(),
|
||||||
typesToTypeList(expression.getTypeArguments())
|
typesToTypeList(expression.getTypeArguments())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static List<String> createConversions(@NotNull PsiCallExpression expression) {
|
||||||
|
List<String> conversions = new LinkedList<String>();
|
||||||
|
PsiExpressionList argumentList = expression.getArgumentList();
|
||||||
|
PsiExpression[] arguments = argumentList != null? argumentList.getExpressions() : new PsiExpression[]{};
|
||||||
|
//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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return conversions;
|
||||||
|
}
|
||||||
|
|
||||||
static boolean isConversionNeeded(@Nullable final PsiType actual,@Nullable final PsiType expected) {
|
static boolean isConversionNeeded(@Nullable final PsiType actual,@Nullable final PsiType expected) {
|
||||||
if (actual == null || expected == null)
|
if (actual == null || expected == null)
|
||||||
return false;
|
return false;
|
||||||
@@ -299,23 +304,24 @@ public class ExpressionVisitor extends StatementVisitor {
|
|||||||
PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference();
|
PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference();
|
||||||
final boolean isNotConvertedClass = classReference != null && !Converter.getClassIdentifiers().contains(classReference.getQualifiedName());
|
final boolean isNotConvertedClass = classReference != null && !Converter.getClassIdentifiers().contains(classReference.getQualifiedName());
|
||||||
PsiExpressionList argumentList = expression.getArgumentList();
|
PsiExpressionList argumentList = expression.getArgumentList();
|
||||||
|
PsiExpression[] arguments = argumentList != null ? argumentList.getExpressions() : new PsiExpression[]{};
|
||||||
if (constructor == null || isConstructorPrimary(constructor) || isNotConvertedClass) {
|
if (constructor == null || isConstructorPrimary(constructor) || isNotConvertedClass) {
|
||||||
return new NewClassExpression(
|
return new NewClassExpression(
|
||||||
expressionToExpression(expression.getQualifier()),
|
expressionToExpression(expression.getQualifier()),
|
||||||
elementToElement(classReference),
|
elementToElement(classReference),
|
||||||
elementToElement(argumentList),
|
expressionsToExpressionList(arguments),
|
||||||
|
createConversions(expression),
|
||||||
anonymousClass != null ? anonymousClassToAnonymousClass(anonymousClass) : null
|
anonymousClass != null ? anonymousClassToAnonymousClass(anonymousClass) : null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// is constructor secondary
|
// is constructor secondary
|
||||||
final PsiJavaCodeReferenceElement reference = expression.getClassReference();
|
final PsiJavaCodeReferenceElement reference = expression.getClassReference();
|
||||||
final List<Type> typeParameters = reference != null ? typesToTypeList(reference.getTypeParameters()) : Collections.<Type>emptyList();
|
final List<Type> typeParameters = reference != null ? typesToTypeList(reference.getTypeParameters()) : Collections.<Type>emptyList();
|
||||||
PsiExpression[] expressions = argumentList != null ? argumentList.getExpressions() : new PsiExpression[]{};
|
|
||||||
return new CallChainExpression(
|
return new CallChainExpression(
|
||||||
new IdentifierImpl(constructor.getName(), false),
|
new IdentifierImpl(constructor.getName(), false),
|
||||||
new MethodCallExpression(
|
new MethodCallExpression(
|
||||||
new IdentifierImpl("init"),
|
new IdentifierImpl("init"),
|
||||||
expressionsToExpressionList(expressions),
|
expressionsToExpressionList(arguments),
|
||||||
false,
|
false,
|
||||||
typeParameters));
|
typeParameters));
|
||||||
}
|
}
|
||||||
@@ -326,7 +332,7 @@ public class ExpressionVisitor extends StatementVisitor {
|
|||||||
callExpression.add(new IdentifierImpl("{null}")); // TODO: remove
|
callExpression.add(new IdentifierImpl("{null}")); // TODO: remove
|
||||||
return new NewClassExpression(
|
return new NewClassExpression(
|
||||||
typeToType(expression.getType()),
|
typeToType(expression.getType()),
|
||||||
new ExpressionList(callExpression)
|
callExpression
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package demo;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
Test(Integer i) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
int i = 10;
|
||||||
|
new Test(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace demo
|
||||||
|
open class Test(i : Int?) {
|
||||||
|
open fun test() : Unit {
|
||||||
|
var i : Int = 10
|
||||||
|
Test(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package demo;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
Test(int i) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
byte b = 10;
|
||||||
|
new Test(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace demo
|
||||||
|
open class Test(i : Int) {
|
||||||
|
open fun test() : Unit {
|
||||||
|
var b : Byte = 10
|
||||||
|
Test((b).int)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user