From 512e12d26c3c4850f1bdeab11e81aecea00005fa Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 24 May 2012 21:03:24 +0200 Subject: [PATCH] conversions as wrappers; generate !! instead of sure() (for constructor calls only for now) --- src/org/jetbrains/jet/j2k/Converter.java | 87 +++++++++++++++---- .../jet/j2k/ast/BangBangExpression.kt | 5 ++ .../jet/j2k/ast/CallChainExpression.kt | 5 +- src/org/jetbrains/jet/j2k/ast/Expression.java | 2 +- .../jet/j2k/ast/NewClassExpression.java | 8 +- .../jet/j2k/visitors/ExpressionVisitor.java | 3 +- tests/testData/ast/issues/file/kt-792.kt | 2 +- tests/testData/ast/issues/file/kt-809.kt | 2 +- 8 files changed, 83 insertions(+), 31 deletions(-) create mode 100644 src/org/jetbrains/jet/j2k/ast/BangBangExpression.kt diff --git a/src/org/jetbrains/jet/j2k/Converter.java b/src/org/jetbrains/jet/j2k/Converter.java index 016bcd059d0..a0725bc5066 100644 --- a/src/org/jetbrains/jet/j2k/Converter.java +++ b/src/org/jetbrains/jet/j2k/Converter.java @@ -16,6 +16,7 @@ package org.jetbrains.jet.j2k; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import com.intellij.psi.*; @@ -49,6 +50,24 @@ public class Converter { "javax.annotation.Nonnull" ); + private static final Map PRIMITIVE_TYPE_CONVERSIONS = ImmutableMap.builder() + .put("byte", BYTE) + .put("short", SHORT) + .put("int", INT) + .put("long", LONG) + .put("float", FLOAT) + .put("double", DOUBLE) + .put("char", CHAR) + + .put(JAVA_LANG_BYTE, BYTE) + .put(JAVA_LANG_SHORT, SHORT) + .put(JAVA_LANG_INTEGER, INT) + .put(JAVA_LANG_LONG, LONG) + .put(JAVA_LANG_FLOAT, FLOAT) + .put(JAVA_LANG_DOUBLE, DOUBLE) + .put(JAVA_LANG_CHARACTER, CHAR) + .build(); + @NotNull private Set classIdentifiers = Sets.newHashSet(); @@ -695,6 +714,53 @@ public class Converter { return modifiersSet; } + public List argumentsToExpressionList(@NotNull PsiCallExpression expression) { + PsiExpressionList argumentList = expression.getArgumentList(); + PsiExpression[] arguments = argumentList != null ? argumentList.getExpressions() : PsiExpression.EMPTY_ARRAY; + List result = new ArrayList(); + + PsiMethod resolved = expression.resolveMethod(); + List expectedTypes = new ArrayList(); + if (resolved != null) { + for (PsiParameter p : resolved.getParameterList().getParameters()) + expectedTypes.add(p.getType()); + } + + // TODO handle varargs correctly + if (arguments.length == expectedTypes.size()) { + for (int i = 0; i < expectedTypes.size(); i++) + result.add(expressionToExpression(arguments[i], expectedTypes.get(i))); + } + else { + for (PsiExpression argument : arguments) { + result.add(expressionToExpression(argument)); + } + } + + return result; + } + + public Expression expressionToExpression(PsiExpression argument, PsiType expectedType) { + Expression expression = expressionToExpression(argument); + PsiType actualType = argument.getType(); + boolean isPrimitiveTypeOrNull = actualType == null || actualType instanceof PsiPrimitiveType; + boolean isRef = (argument instanceof PsiReferenceExpression && ((PsiReferenceExpression) argument).isQualified() || argument instanceof PsiMethodCallExpression); + + if (isPrimitiveTypeOrNull && isRef && expression.isNullable()) { + expression = new BangBangExpression(expression); + } + + if (actualType != null) { + if (isConversionNeeded(actualType, expectedType)) { + String conversion = PRIMITIVE_TYPE_CONVERSIONS.get(expectedType.getCanonicalText()); + if (conversion != null) { + expression = new DummyMethodCallExpression(expression, conversion, (IdentifierImpl) Identifier.EMPTY_IDENTIFIER); + } + } + } + return expression; + } + @NotNull public List createConversions(@NotNull PsiCallExpression expression) { PsiExpressionList argumentList = expression.getArgumentList(); @@ -787,25 +853,8 @@ public class Converter { @NotNull private static String getPrimitiveTypeConversion(@NotNull String type) { - Map conversions = new HashMap(); - conversions.put("byte", BYTE); - conversions.put("short", SHORT); - conversions.put("int", INT); - conversions.put("long", LONG); - conversions.put("float", FLOAT); - conversions.put("double", DOUBLE); - conversions.put("char", CHAR); - - conversions.put(JAVA_LANG_BYTE, BYTE); - conversions.put(JAVA_LANG_SHORT, SHORT); - conversions.put(JAVA_LANG_INTEGER, INT); - conversions.put(JAVA_LANG_LONG, LONG); - conversions.put(JAVA_LANG_FLOAT, FLOAT); - conversions.put(JAVA_LANG_DOUBLE, DOUBLE); - conversions.put(JAVA_LANG_CHARACTER, CHAR); - - if (conversions.containsKey(type)) { - return "." + conversions.get(type) + "()"; + if (PRIMITIVE_TYPE_CONVERSIONS.containsKey(type)) { + return "." + PRIMITIVE_TYPE_CONVERSIONS.get(type) + "()"; } return ""; } diff --git a/src/org/jetbrains/jet/j2k/ast/BangBangExpression.kt b/src/org/jetbrains/jet/j2k/ast/BangBangExpression.kt new file mode 100644 index 00000000000..bc2cc371c58 --- /dev/null +++ b/src/org/jetbrains/jet/j2k/ast/BangBangExpression.kt @@ -0,0 +1,5 @@ +package org.jetbrains.jet.j2k.ast + +public class BangBangExpression(val expr: Expression): Expression() { + public override fun toKotlin(): String = expr.toKotlin() + "!!" +} diff --git a/src/org/jetbrains/jet/j2k/ast/CallChainExpression.kt b/src/org/jetbrains/jet/j2k/ast/CallChainExpression.kt index 69464a42327..0b8d3f5fa75 100644 --- a/src/org/jetbrains/jet/j2k/ast/CallChainExpression.kt +++ b/src/org/jetbrains/jet/j2k/ast/CallChainExpression.kt @@ -8,7 +8,10 @@ public open class CallChainExpression(val expression : Expression, val identifie return INode.Kind.CALL_CHAIN } - public override fun isNullable() : Boolean = identifier.isNullable() + public override fun isNullable() : Boolean { + if (!expression.isEmpty() && expression.isNullable()) return true + return identifier.isNullable() + } public override fun toKotlin() : String { if (!expression.isEmpty()) { diff --git a/src/org/jetbrains/jet/j2k/ast/Expression.java b/src/org/jetbrains/jet/j2k/ast/Expression.java index 28c9a6143f0..aa8b4f78ae8 100644 --- a/src/org/jetbrains/jet/j2k/ast/Expression.java +++ b/src/org/jetbrains/jet/j2k/ast/Expression.java @@ -41,7 +41,7 @@ public abstract class Expression extends Statement { } } - boolean isNullable() { + public boolean isNullable() { return false; } } diff --git a/src/org/jetbrains/jet/j2k/ast/NewClassExpression.java b/src/org/jetbrains/jet/j2k/ast/NewClassExpression.java index 7bbf906dff0..038a158ea99 100644 --- a/src/org/jetbrains/jet/j2k/ast/NewClassExpression.java +++ b/src/org/jetbrains/jet/j2k/ast/NewClassExpression.java @@ -29,7 +29,6 @@ public class NewClassExpression extends Expression { private final Element myName; private final List myArguments; private Expression myQualifier; - private List myConversions; @Nullable private AnonymousClass myAnonymousClass = null; @@ -37,14 +36,12 @@ public class NewClassExpression extends Expression { myName = name; myQualifier = EMPTY_EXPRESSION; myArguments = arguments; - myConversions = AstUtil.createListWithEmptyString(arguments); } public NewClassExpression(@NotNull Expression qualifier, @NotNull Element name, @NotNull List arguments, - @NotNull List conversions, @Nullable AnonymousClass anonymousClass) { + @Nullable AnonymousClass anonymousClass) { this(name, arguments); myQualifier = qualifier; - myConversions = conversions; myAnonymousClass = anonymousClass; } @@ -53,8 +50,7 @@ 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 applyConversions = AstUtil.applyConversions(AstUtil.nodesToKotlin(myArguments), myConversions); - String appliedArguments = AstUtil.join(applyConversions, COMMA_WITH_SPACE); + String appliedArguments = AstUtil.joinNodes(myArguments, COMMA_WITH_SPACE); return myAnonymousClass != null ? "object" + SPACE + ":" + SPACE + qualifier + myName.toKotlin() + "(" + appliedArguments + ")" + myAnonymousClass.toKotlin() : diff --git a/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java b/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java index a51c0af463f..e39b9ffc450 100644 --- a/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java +++ b/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java @@ -276,8 +276,7 @@ public class ExpressionVisitor extends StatementVisitor { return new NewClassExpression( getConverter().expressionToExpression(expression.getQualifier()), getConverter().elementToElement(classReference), - getConverter().expressionsToExpressionList(arguments), - getConverter().createConversions(expression), + getConverter().argumentsToExpressionList(expression), anonymousClass != null ? getConverter().anonymousClassToAnonymousClass(anonymousClass) : null ); } diff --git a/tests/testData/ast/issues/file/kt-792.kt b/tests/testData/ast/issues/file/kt-792.kt index 18ec9156bcd..c11e69dc440 100644 --- a/tests/testData/ast/issues/file/kt-792.kt +++ b/tests/testData/ast/issues/file/kt-792.kt @@ -2,6 +2,6 @@ package demo open class Test(i : Int) { open fun test() : Unit { var b : Byte = 10 -Test((b).toInt()) +Test(b.toInt()) } } \ No newline at end of file diff --git a/tests/testData/ast/issues/file/kt-809.kt b/tests/testData/ast/issues/file/kt-809.kt index c1b65a57a35..0087d79ef81 100644 --- a/tests/testData/ast/issues/file/kt-809.kt +++ b/tests/testData/ast/issues/file/kt-809.kt @@ -14,6 +14,6 @@ open fun putInt(i : Int) : Unit { } open fun test() : Unit { putInt((One.myContainer?.myInt).sure()) -IntContainer((One.myContainer?.myInt).sure()) +IntContainer(One.myContainer?.myInt!!) } } \ No newline at end of file