KT-820 Add explicit conversion in assignment expression
This commit is contained in:
@@ -26,9 +26,15 @@ public class Converter {
|
||||
add("javax.annotation.Nonnull");
|
||||
}
|
||||
};
|
||||
@NotNull private static Set<String> ourClassIdentifiers = new HashSet<String>();
|
||||
@NotNull private static final Dispatcher ourDispatcher = new Dispatcher();
|
||||
@Nullable private static PsiType ourMethodReturnType = null;
|
||||
@NotNull
|
||||
private static Set<String> ourClassIdentifiers = new HashSet<String>();
|
||||
@NotNull
|
||||
private static final Dispatcher ourDispatcher = new Dispatcher();
|
||||
@Nullable
|
||||
private static PsiType ourMethodReturnType = null;
|
||||
|
||||
private Converter() {
|
||||
}
|
||||
|
||||
public static void setClassIdentifiers(@NotNull Set<String> 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<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++)
|
||||
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<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 = 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<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 "";
|
||||
}
|
||||
|
||||
// @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 "";
|
||||
}
|
||||
}
|
||||
@@ -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<String> modifiers, Type type, Element initializer) {
|
||||
public Field(Identifier identifier, Set<String> modifiers, Type type, Element initializer, @NotNull String conversionForCallChains) {
|
||||
myIdentifier = identifier;
|
||||
myConversion = conversionForCallChains;
|
||||
myModifiers = modifiers;
|
||||
myType = type;
|
||||
myInitializer = initializer;
|
||||
}
|
||||
|
||||
public Field(Identifier identifier, Set<String> 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;
|
||||
}
|
||||
}
|
||||
@@ -12,12 +12,14 @@ public class LocalVariable extends Expression {
|
||||
private final Set<String> myModifiersSet;
|
||||
private final Type myType;
|
||||
private final Expression myInitializer;
|
||||
private final String myConversion;
|
||||
|
||||
public LocalVariable(Identifier identifier, Set<String> modifiersSet, Type type, Expression initializer) {
|
||||
public LocalVariable(Identifier identifier, Set<String> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<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);
|
||||
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<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 = 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<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
|
||||
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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user