KT-792 Support autoboxing primitive types (for constructor invocations)

This commit is contained in:
Sergey Ignatov
2011-12-12 14:09:10 +04:00
parent aea06bf980
commit eca1f32a55
6 changed files with 92 additions and 41 deletions
@@ -2,25 +2,32 @@ package org.jetbrains.jet.j2k.ast;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.j2k.util.AstUtil;
import java.util.List;
/**
* @author ignatov
*/
public class NewClassExpression extends Expression {
private final Element myName;
private final Element myArguments;
private final List<Expression> myArguments;
private Expression myQualifier;
private List<String> myConversions;
private AnonymousClass myAnonymousClass = null;
public NewClassExpression(Element name, Element arguments) {
public NewClassExpression(Element name, List<Expression> arguments) {
myName = name;
myQualifier = EMPTY_EXPRESSION;
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);
myQualifier = qualifier;
myConversions = conversions;
myAnonymousClass = anonymousClass;
}
@@ -29,8 +36,10 @@ public class NewClassExpression extends Expression {
public String toKotlin() {
final String callOperator = myQualifier.isNullable() ? QUESTDOT : DOT;
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 ?
"object" + SPACE + ":" + SPACE + qualifier + myName.toKotlin() + "(" + myArguments.toKotlin() + ")" + myAnonymousClass.toKotlin() :
qualifier + myName.toKotlin() + "(" + myArguments.toKotlin() + ")";
"object" + SPACE + ":" + SPACE + qualifier + myName.toKotlin() + "(" + appliedArguments + ")" + myAnonymousClass.toKotlin() :
qualifier + myName.toKotlin() + "(" + appliedArguments + ")";
}
}
@@ -191,47 +191,52 @@ public class ExpressionVisitor extends StatementVisitor {
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
super.visitMethodCallExpression(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()),
expressionsToExpressionList(arguments),
conversions,
expressionsToExpressionList(expression.getArgumentList().getExpressions()),
createConversions(expression),
typeToType(expression.getType()).isNullable(),
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) {
if (actual == null || expected == null)
return false;
@@ -299,23 +304,24 @@ public class ExpressionVisitor extends StatementVisitor {
PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference();
final boolean isNotConvertedClass = classReference != null && !Converter.getClassIdentifiers().contains(classReference.getQualifiedName());
PsiExpressionList argumentList = expression.getArgumentList();
PsiExpression[] arguments = argumentList != null ? argumentList.getExpressions() : new PsiExpression[]{};
if (constructor == null || isConstructorPrimary(constructor) || isNotConvertedClass) {
return new NewClassExpression(
expressionToExpression(expression.getQualifier()),
elementToElement(classReference),
elementToElement(argumentList),
expressionsToExpressionList(arguments),
createConversions(expression),
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"),
expressionsToExpressionList(expressions),
expressionsToExpressionList(arguments),
false,
typeParameters));
}
@@ -326,7 +332,7 @@ public class ExpressionVisitor extends StatementVisitor {
callExpression.add(new IdentifierImpl("{null}")); // TODO: remove
return new NewClassExpression(
typeToType(expression.getType()),
new ExpressionList(callExpression)
callExpression
);
}
+11
View File
@@ -0,0 +1,11 @@
package demo;
class Test {
Test(Integer i) {
}
void test() {
int i = 10;
new Test(i);
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace demo
open class Test(i : Int?) {
open fun test() : Unit {
var i : Int = 10
Test(i)
}
}
+11
View File
@@ -0,0 +1,11 @@
package demo;
class Test {
Test(int i) {
}
void test() {
byte b = 10;
new Test(b);
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace demo
open class Test(i : Int) {
open fun test() : Unit {
var b : Byte = 10
Test((b).int)
}
}