diff --git a/src/org/jetbrains/jet/j2k/Converter.java b/src/org/jetbrains/jet/j2k/Converter.java index 360c7cda192..c198eeb5688 100644 --- a/src/org/jetbrains/jet/j2k/Converter.java +++ b/src/org/jetbrains/jet/j2k/Converter.java @@ -26,9 +26,15 @@ public class Converter { add("javax.annotation.Nonnull"); } }; - @NotNull private static Set ourClassIdentifiers = new HashSet(); - @NotNull private static final Dispatcher ourDispatcher = new Dispatcher(); - @Nullable private static PsiType ourMethodReturnType = null; + @NotNull + private static Set ourClassIdentifiers = new HashSet(); + @NotNull + private static final Dispatcher ourDispatcher = new Dispatcher(); + @Nullable + private static PsiType ourMethodReturnType = null; + + private Converter() { + } public static void setClassIdentifiers(@NotNull Set identifiers) { ourClassIdentifiers = identifiers; @@ -269,7 +275,8 @@ public class Converter { new IdentifierImpl(field.getName()), // TODO modifiers, typeToType(field.getType()), - expressionToExpression(field.getInitializer()) // TODO: add modifiers + expressionToExpression(field.getInitializer()), // TODO: add modifiers + createConversionForCallChains(field.getInitializer(), field.getType()) ); } @@ -549,4 +556,104 @@ public class Converter { } return modifiersSet; } + + @NotNull + public static List createConversions(@NotNull PsiCallExpression expression) { + List conversions = new LinkedList(); + 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 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++) + conversions.set(i, createConversionForExpression(arguments[i], expectedTypes.get(i))); + } + return conversions; + } + + @NotNull + public static String createConversionForExpression(@Nullable PsiExpression expression, @NotNull PsiType expectedType) { + String conversion = ""; + if (expression != null) { + PsiType actualType = expression.getType(); + if (actualType != null) { + if (isConversionNeeded(actualType, expectedType)) + conversion += getPrimitiveTypeConversion(expectedType.getCanonicalText()); + if (expression instanceof PsiReferenceExpression && Node.PRIMITIVE_TYPES.contains(actualType.getCanonicalText()) && ((PsiReferenceExpression) expression).isQualified()) + conversion += ".sure()"; + } + } + return conversion; + } + + public static boolean isConversionNeeded(@Nullable final PsiType actual, @Nullable final PsiType expected) { + if (actual == null || expected == null) + return false; + 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 = AstUtil.getOrElse(typeMap, actualStr, "").equals(expectedStr); + boolean o2 = AstUtil.getOrElse(typeMap, expectedStr, "").equals(actualStr); + return !actualStr.equals(expectedStr) && (!(o1 ^ o2)); + } + + @NotNull + public static String getPrimitiveTypeConversion(@NotNull 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 ""; + } + +// @NotNull +// private static String applyConversion(Expression expression, String conversion) { +// if (conversion.isEmpty()) +// return expression.toKotlin(); +// return "(" + expression.toKotlin() + ")" + conversion; +// } + + @NotNull + public static String createConversionForCallChains(PsiExpression initializer, PsiType type) { + if (initializer != null && initializer instanceof PsiReferenceExpression && ((PsiReferenceExpression) initializer).isQualified()) + return createConversionForExpression(initializer, type); + return ""; + } } \ No newline at end of file diff --git a/src/org/jetbrains/jet/j2k/ast/Field.java b/src/org/jetbrains/jet/j2k/ast/Field.java index 8c2bbde5b94..c0593ffd9eb 100644 --- a/src/org/jetbrains/jet/j2k/ast/Field.java +++ b/src/org/jetbrains/jet/j2k/ast/Field.java @@ -14,16 +14,23 @@ import static org.jetbrains.jet.j2k.Converter.getDefaultInitializer; */ public class Field extends Member { final Identifier myIdentifier; + @NotNull + private final String myConversion; final Type myType; final Element myInitializer; - public Field(Identifier identifier, Set modifiers, Type type, Element initializer) { + public Field(Identifier identifier, Set modifiers, Type type, Element initializer, @NotNull String conversionForCallChains) { myIdentifier = identifier; + myConversion = conversionForCallChains; myModifiers = modifiers; myType = type; myInitializer = initializer; } + public Field(Identifier identifier, Set modifiers, Type type, Element initializer) { + this(identifier, modifiers, type, initializer, ""); + } + public Element getInitializer() { return myInitializer; } @@ -71,6 +78,6 @@ public class Field extends Member { return modifier + myIdentifier.toKotlin() + SPACE + COLON + SPACE + myType.toKotlin() + SPACE + EQUAL + SPACE + getDefaultInitializer(this); return modifier + myIdentifier.toKotlin() + SPACE + COLON + SPACE + myType.toKotlin() + SPACE + - EQUAL + SPACE + myInitializer.toKotlin(); + EQUAL + SPACE + myInitializer.toKotlin() + myConversion; } } \ No newline at end of file diff --git a/src/org/jetbrains/jet/j2k/ast/LocalVariable.java b/src/org/jetbrains/jet/j2k/ast/LocalVariable.java index 0c561827a18..c377b9af56d 100644 --- a/src/org/jetbrains/jet/j2k/ast/LocalVariable.java +++ b/src/org/jetbrains/jet/j2k/ast/LocalVariable.java @@ -12,12 +12,14 @@ public class LocalVariable extends Expression { private final Set myModifiersSet; private final Type myType; private final Expression myInitializer; + private final String myConversion; - public LocalVariable(Identifier identifier, Set modifiersSet, Type type, Expression initializer) { + public LocalVariable(Identifier identifier, Set modifiersSet, Type type, Expression initializer, @NotNull String conversionForExpression) { myIdentifier = identifier; myModifiersSet = modifiersSet; myType = type; myInitializer = initializer; + myConversion = conversionForExpression; } public boolean hasModifier(String modifier) { @@ -31,6 +33,6 @@ public class LocalVariable extends Expression { return myIdentifier.toKotlin() + SPACE + COLON + SPACE + myType.toKotlin(); return myIdentifier.toKotlin() + SPACE + COLON + SPACE + myType.toKotlin() + SPACE + - EQUAL + SPACE + myInitializer.toKotlin(); + EQUAL + SPACE + myInitializer.toKotlin() + myConversion; } } diff --git a/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.java b/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.java index 4a39cf57ca5..cda41ceba8b 100644 --- a/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.java +++ b/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.java @@ -30,7 +30,8 @@ public class ElementVisitor extends JavaElementVisitor { new IdentifierImpl(variable.getName()), // TODO modifiersListToModifiersSet(variable.getModifierList()), typeToType(variable.getType(), Converter.isNotNull(variable.getModifierList())), - expressionToExpression(variable.getInitializer()) + expressionToExpression(variable.getInitializer()), + createConversionForCallChains(variable.getInitializer(), variable.getType()) ); } diff --git a/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java b/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java index ce61907a114..6311bea2780 100644 --- a/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java +++ b/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.java @@ -4,9 +4,7 @@ import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.j2k.Converter; import org.jetbrains.jet.j2k.ast.*; -import org.jetbrains.jet.j2k.util.AstUtil; import java.util.*; @@ -16,7 +14,7 @@ import static org.jetbrains.jet.j2k.Converter.*; * @author ignatov */ public class ExpressionVisitor extends StatementVisitor { - @Nullable + @NotNull Expression myResult = Expression.EMPTY_EXPRESSION; @Override @@ -204,92 +202,6 @@ public class ExpressionVisitor extends StatementVisitor { } } - @NotNull - private static List createConversions(@NotNull PsiCallExpression expression) { - List conversions = new LinkedList(); - 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 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); - PsiExpression argument = arguments[i]; - - String conversion = ""; - if (isConversionNeeded(actual, expected)) - conversion += getPrimitiveTypeConversion(expected.getCanonicalText()); - - PsiType type = argument.getType(); - if (argument instanceof PsiReferenceExpression && - type != null && Node.PRIMITIVE_TYPES.contains(type.getCanonicalText()) && - ((PsiReferenceExpression) argument).isQualified()) - conversion += ".sure()"; - - conversions.set(i, conversion); - } - } - return conversions; - } - - static boolean isConversionNeeded(@Nullable final PsiType actual, @Nullable final PsiType expected) { - if (actual == null || expected == null) - return false; - 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 = AstUtil.getOrElse(typeMap, actualStr, "").equals(expectedStr); - boolean o2 = AstUtil.getOrElse(typeMap, expectedStr, "").equals(actualStr); - return !actualStr.equals(expectedStr) && (!(o1 ^ o2)); - } - - @NotNull - static String getPrimitiveTypeConversion(@NotNull 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 public void visitCallExpression(PsiCallExpression callExpression) { super.visitCallExpression(callExpression); @@ -313,7 +225,7 @@ public class ExpressionVisitor extends StatementVisitor { final PsiAnonymousClass anonymousClass = expression.getAnonymousClass(); final PsiMethod constructor = expression.resolveMethod(); PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference(); - final boolean isNotConvertedClass = classReference != null && !Converter.getClassIdentifiers().contains(classReference.getQualifiedName()); + final boolean isNotConvertedClass = classReference != null && !getClassIdentifiers().contains(classReference.getQualifiedName()); PsiExpressionList argumentList = expression.getArgumentList(); PsiExpression[] arguments = argumentList != null ? argumentList.getExpressions() : new PsiExpression[]{}; if (constructor == null || isConstructorPrimary(constructor) || isNotConvertedClass) { diff --git a/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.java b/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.java index 07b4689822c..d7d1ea178aa 100644 --- a/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.java +++ b/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.java @@ -15,8 +15,8 @@ import java.util.LinkedList; import java.util.List; import static org.jetbrains.jet.j2k.Converter.*; -import static org.jetbrains.jet.j2k.visitors.ExpressionVisitor.getPrimitiveTypeConversion; -import static org.jetbrains.jet.j2k.visitors.ExpressionVisitor.isConversionNeeded; +import static org.jetbrains.jet.j2k.Converter.getPrimitiveTypeConversion; +import static org.jetbrains.jet.j2k.Converter.isConversionNeeded; /** * @author ignatov diff --git a/testData/ast/issues/file/kt-820-field.jav b/testData/ast/issues/file/kt-820-field.jav new file mode 100644 index 00000000000..ca2c1588ef7 --- /dev/null +++ b/testData/ast/issues/file/kt-820-field.jav @@ -0,0 +1,13 @@ +package demo; + +class Container { + int myInt = 1; +} + +class One { + static Container myContainer = new Container(); +} + +class Test { + byte b = One.myContainer.myInt; +} \ No newline at end of file diff --git a/testData/ast/issues/file/kt-820-field.kt b/testData/ast/issues/file/kt-820-field.kt new file mode 100644 index 00000000000..7326083fac8 --- /dev/null +++ b/testData/ast/issues/file/kt-820-field.kt @@ -0,0 +1,12 @@ +namespace demo +open class Container() { +var myInt : Int = 1 +} +open class One() { +class object { +var myContainer : Container? = Container() +} +} +open class Test() { +var b : Byte = One.myContainer?.myInt.byt.sure() +} \ No newline at end of file diff --git a/testData/ast/issues/file/kt-820.jav b/testData/ast/issues/file/kt-820.jav new file mode 100644 index 00000000000..20ac0acdb97 --- /dev/null +++ b/testData/ast/issues/file/kt-820.jav @@ -0,0 +1,15 @@ +package demo; + +class Container { + int myInt = 1; +} + +class One { + static Container myContainer = new Container(); +} + +class Test { + void test() { + byte b = One.myContainer.myInt; + } +} \ No newline at end of file diff --git a/testData/ast/issues/file/kt-820.kt b/testData/ast/issues/file/kt-820.kt new file mode 100644 index 00000000000..6fd43add913 --- /dev/null +++ b/testData/ast/issues/file/kt-820.kt @@ -0,0 +1,14 @@ +namespace demo +open class Container() { +var myInt : Int = 1 +} +open class One() { +class object { +var myContainer : Container? = Container() +} +} +open class Test() { +open fun test() : Unit { +var b : Byte = One.myContainer?.myInt.byt.sure() +} +} \ No newline at end of file