KT-696 Create a bunch of functions for java.lang.Object compatibility
This commit is contained in:
@@ -26,6 +26,10 @@ public class Converter {
|
|||||||
}
|
}
|
||||||
} ;
|
} ;
|
||||||
private static Set<String> ourClassIdentifiers = new HashSet<String>();
|
private static Set<String> ourClassIdentifiers = new HashSet<String>();
|
||||||
|
private static final Dispatcher ourDispatcher = new Dispatcher();
|
||||||
|
// private static ExpressionVisitor ourExpressionVisitor = new ExpressionVisitor();
|
||||||
|
|
||||||
|
private static final java.lang.Class<ExpressionVisitor> visitorClass = ExpressionVisitor.class;
|
||||||
|
|
||||||
public static void setClassIdentifiers(Set<String> identifiers) {
|
public static void setClassIdentifiers(Set<String> identifiers) {
|
||||||
ourClassIdentifiers = identifiers;
|
ourClassIdentifiers = identifiers;
|
||||||
@@ -107,7 +111,7 @@ public class Converter {
|
|||||||
List<Statement> result = new LinkedList<Statement>();
|
List<Statement> result = new LinkedList<Statement>();
|
||||||
for (Field f : fields) {
|
for (Field f : fields) {
|
||||||
final String identifierToKotlin = f.getIdentifier().toKotlin();
|
final String identifierToKotlin = f.getIdentifier().toKotlin();
|
||||||
result.add(new DummyStringStatement("$" + identifierToKotlin + " = " + identifierToKotlin));
|
result.add(new DummyStringExpression("$" + identifierToKotlin + " = " + identifierToKotlin));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -184,7 +188,7 @@ public class Converter {
|
|||||||
|
|
||||||
newStatements.add(
|
newStatements.add(
|
||||||
0,
|
0,
|
||||||
new DummyStringStatement(
|
new DummyStringExpression(
|
||||||
"val __ = " + createPrimaryConstructorInvocation(
|
"val __ = " + createPrimaryConstructorInvocation(
|
||||||
name.toKotlin(),
|
name.toKotlin(),
|
||||||
finalOrWithEmptyInitializer,
|
finalOrWithEmptyInitializer,
|
||||||
@@ -294,6 +298,11 @@ public class Converter {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static Function methodToFunction(@NotNull PsiMethod method, boolean notEmpty) {
|
private static Function methodToFunction(@NotNull PsiMethod method, boolean notEmpty) {
|
||||||
|
if (isOverrideObjectDirect(method))
|
||||||
|
ourDispatcher.setExpressionVisitor(new ExpressionVisitorForDirectObjectInheritors());
|
||||||
|
else
|
||||||
|
ourDispatcher.setExpressionVisitor(new ExpressionVisitor());
|
||||||
|
|
||||||
final IdentifierImpl identifier = new IdentifierImpl(method.getName());
|
final IdentifierImpl identifier = new IdentifierImpl(method.getName());
|
||||||
final Type returnType = typeToType(method.getReturnType(), isNotNull(method.getModifierList()));
|
final Type returnType = typeToType(method.getReturnType(), isNotNull(method.getModifierList()));
|
||||||
final Block body = blockToBlock(method.getBody(), notEmpty);
|
final Block body = blockToBlock(method.getBody(), notEmpty);
|
||||||
@@ -350,6 +359,17 @@ public class Converter {
|
|||||||
return counter > 0;
|
return counter > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isOverrideObjectDirect(@NotNull final PsiMethod method) {
|
||||||
|
List<HierarchicalMethodSignature> superSignatures = method.getHierarchicalMethodSignature().getSuperSignatures();
|
||||||
|
if (superSignatures.size() == 1) {
|
||||||
|
final PsiClass containingClass = superSignatures.get(0).getMethod().getContainingClass();
|
||||||
|
final String qualifiedName = containingClass != null ? containingClass.getQualifiedName() : "";
|
||||||
|
if (qualifiedName != null && qualifiedName.equals("java.lang.Object"))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static Block blockToBlock(@Nullable PsiCodeBlock block, boolean notEmpty) {
|
public static Block blockToBlock(@Nullable PsiCodeBlock block, boolean notEmpty) {
|
||||||
if (block == null) return Block.EMPTY_BLOCK;
|
if (block == null) return Block.EMPTY_BLOCK;
|
||||||
@@ -386,7 +406,7 @@ public class Converter {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static Expression expressionToExpression(@Nullable PsiExpression e) {
|
public static Expression expressionToExpression(@Nullable PsiExpression e) {
|
||||||
if (e == null) return Expression.EMPTY_EXPRESSION;
|
if (e == null) return Expression.EMPTY_EXPRESSION;
|
||||||
final ExpressionVisitor expressionVisitor = new ExpressionVisitor();
|
final ExpressionVisitor expressionVisitor = ourDispatcher.getExpressionVisitor();
|
||||||
e.accept(expressionVisitor);
|
e.accept(expressionVisitor);
|
||||||
return expressionVisitor.getResult();
|
return expressionVisitor.getResult();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
* @author ignatov
|
* @author ignatov
|
||||||
*/
|
*/
|
||||||
public class DummyMethodCallExpression extends Expression {
|
public class DummyMethodCallExpression extends Expression {
|
||||||
private final Expression myWho;
|
private final Element myWho;
|
||||||
private final String myMethodName;
|
private final String myMethodName;
|
||||||
private final Expression myWhat;
|
private final Element myWhat;
|
||||||
|
|
||||||
public DummyMethodCallExpression(Expression who, String methodName, Expression what) {
|
public DummyMethodCallExpression(Element who, String methodName, Element what) {
|
||||||
myWho = who;
|
myWho = who;
|
||||||
myMethodName = methodName;
|
myMethodName = methodName;
|
||||||
myWhat = what;
|
myWhat = what;
|
||||||
|
|||||||
+2
-2
@@ -5,10 +5,10 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
/**
|
/**
|
||||||
* @author ignatov
|
* @author ignatov
|
||||||
*/
|
*/
|
||||||
public class DummyStringStatement extends Statement {
|
public class DummyStringExpression extends Expression {
|
||||||
private final String myString;
|
private final String myString;
|
||||||
|
|
||||||
public DummyStringStatement(String string) {
|
public DummyStringExpression(String string) {
|
||||||
myString = string;
|
myString = string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package org.jetbrains.jet.j2k.visitors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ignatov
|
||||||
|
*/
|
||||||
|
public class Dispatcher {
|
||||||
|
private ExpressionVisitor myExpressionVisitor;
|
||||||
|
|
||||||
|
public void setExpressionVisitor(final ExpressionVisitor expressionVisitor) {
|
||||||
|
this.myExpressionVisitor = expressionVisitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dispatcher() {
|
||||||
|
myExpressionVisitor = new ExpressionVisitor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExpressionVisitor getExpressionVisitor() {
|
||||||
|
return myExpressionVisitor;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,12 @@ import static org.jetbrains.jet.j2k.Converter.*;
|
|||||||
* @author ignatov
|
* @author ignatov
|
||||||
*/
|
*/
|
||||||
public class ExpressionVisitor extends StatementVisitor {
|
public class ExpressionVisitor extends StatementVisitor {
|
||||||
private Expression myResult = Expression.EMPTY_EXPRESSION;
|
Expression myResult = Expression.EMPTY_EXPRESSION;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitExpression(final PsiExpression expression) {
|
||||||
|
myResult = Expression.EMPTY_EXPRESSION;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
@@ -295,7 +300,7 @@ public class ExpressionVisitor extends StatementVisitor {
|
|||||||
final boolean hasReceiver = isFieldReference && insideSecondaryConstructor;
|
final boolean hasReceiver = isFieldReference && insideSecondaryConstructor;
|
||||||
final boolean isThis = isThisExpression(expression);
|
final boolean isThis = isThisExpression(expression);
|
||||||
final boolean isNullable = typeToType(expression.getType()).isNullable();
|
final boolean isNullable = typeToType(expression.getType()).isNullable();
|
||||||
final String className = getClassName(expression);
|
final String className = getClassNameWithConstructor(expression);
|
||||||
|
|
||||||
Expression identifier = new IdentifierImpl(expression.getReferenceName(), isNullable);
|
Expression identifier = new IdentifierImpl(expression.getReferenceName(), isNullable);
|
||||||
|
|
||||||
@@ -316,7 +321,7 @@ public class ExpressionVisitor extends StatementVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static String getClassName(@NotNull PsiReferenceExpression expression) {
|
static String getClassNameWithConstructor(@NotNull PsiReferenceExpression expression) {
|
||||||
PsiElement context = expression.getContext();
|
PsiElement context = expression.getContext();
|
||||||
while (context != null) {
|
while (context != null) {
|
||||||
if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) {
|
if (context instanceof PsiMethod && ((PsiMethod) context).isConstructor()) {
|
||||||
@@ -332,6 +337,21 @@ public class ExpressionVisitor extends StatementVisitor {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
static String getClassName(@NotNull PsiExpression expression) {
|
||||||
|
PsiElement context = expression.getContext();
|
||||||
|
while (context != null) {
|
||||||
|
if (context instanceof PsiClass) {
|
||||||
|
final PsiClass containingClass = (PsiClass) context;
|
||||||
|
final PsiIdentifier identifier = containingClass.getNameIdentifier();
|
||||||
|
if (identifier != null)
|
||||||
|
return identifier.getText();
|
||||||
|
}
|
||||||
|
context = context.getContext();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean isFieldReference(@NotNull PsiReferenceExpression expression, PsiClass currentClass) {
|
private static boolean isFieldReference(@NotNull PsiReferenceExpression expression, PsiClass currentClass) {
|
||||||
final PsiReference reference = expression.getReference();
|
final PsiReference reference = expression.getReference();
|
||||||
if (reference != null) {
|
if (reference != null) {
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package org.jetbrains.jet.j2k.visitors;
|
||||||
|
|
||||||
|
import com.intellij.psi.*;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.j2k.Converter;
|
||||||
|
import org.jetbrains.jet.j2k.ast.DummyMethodCallExpression;
|
||||||
|
import org.jetbrains.jet.j2k.ast.DummyStringExpression;
|
||||||
|
import org.jetbrains.jet.j2k.ast.IdentifierImpl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ignatov
|
||||||
|
*/
|
||||||
|
public class ExpressionVisitorForDirectObjectInheritors extends ExpressionVisitor {
|
||||||
|
@Override
|
||||||
|
public void visitMethodCallExpression(@NotNull final PsiMethodCallExpression expression) {
|
||||||
|
if (superMethodInvocation(expression.getMethodExpression(), "hashCode"))
|
||||||
|
myResult = new DummyMethodCallExpression(new IdentifierImpl("System"), "identityHashCode", new IdentifierImpl("this"));
|
||||||
|
else if (superMethodInvocation(expression.getMethodExpression(), "equals"))
|
||||||
|
myResult = new DummyMethodCallExpression(new IdentifierImpl("this"), "identityEquals", Converter.elementToElement(expression.getArgumentList()));
|
||||||
|
else if (superMethodInvocation(expression.getMethodExpression(), "toString"))
|
||||||
|
myResult = new DummyStringExpression(String.format("getJavaClass<%s>.getName() + '@' + Integer.toHexString(hashCode())", getClassName(expression.getMethodExpression())));
|
||||||
|
else
|
||||||
|
super.visitMethodCallExpression(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitReferenceExpression(@NotNull final PsiReferenceExpression expression) {
|
||||||
|
super.visitReferenceExpression(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean superMethodInvocation(@NotNull final PsiReferenceExpression expression, final String methodName) {
|
||||||
|
String referenceName = expression.getReferenceName();
|
||||||
|
PsiExpression qualifierExpression = expression.getQualifierExpression();
|
||||||
|
if (referenceName != null && referenceName.equals(methodName)) {
|
||||||
|
if (qualifierExpression instanceof PsiSuperExpression) {
|
||||||
|
PsiType type = qualifierExpression.getType();
|
||||||
|
if (type != null && type.getCanonicalText().equals("java.lang.Object"))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,16 +18,16 @@ super.finalize()
|
|||||||
}
|
}
|
||||||
open class Base() {
|
open class Base() {
|
||||||
open public fun hashCode() : Int {
|
open public fun hashCode() : Int {
|
||||||
return super.hashCode()
|
return System.identityHashCode(this)
|
||||||
}
|
}
|
||||||
open public fun equals(o : Any?) : Boolean {
|
open public fun equals(o : Any?) : Boolean {
|
||||||
return super.equals(o)
|
return this.identityEquals(o)
|
||||||
}
|
}
|
||||||
open protected fun clone() : Any? {
|
open protected fun clone() : Any? {
|
||||||
return super.clone()
|
return super.clone()
|
||||||
}
|
}
|
||||||
open public fun toString() : String? {
|
open public fun toString() : String? {
|
||||||
return super.toString()
|
return getJavaClass<Base>.getName() + '@' + Integer.toHexString(hashCode())
|
||||||
}
|
}
|
||||||
open protected fun finalize() : Unit {
|
open protected fun finalize() : Unit {
|
||||||
super.finalize()
|
super.finalize()
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
namespace test
|
namespace test
|
||||||
open class Test() {
|
open class Test() {
|
||||||
open public fun hashCode() : Int {
|
open public fun hashCode() : Int {
|
||||||
return super.hashCode()
|
return System.identityHashCode(this)
|
||||||
}
|
}
|
||||||
open public fun equals(o : Any?) : Boolean {
|
open public fun equals(o : Any?) : Boolean {
|
||||||
return super.equals(o)
|
return this.identityEquals(o)
|
||||||
}
|
}
|
||||||
open protected fun clone() : Any? {
|
open protected fun clone() : Any? {
|
||||||
return super.clone()
|
return super.clone()
|
||||||
}
|
}
|
||||||
open public fun toString() : String? {
|
open public fun toString() : String? {
|
||||||
return super.toString()
|
return getJavaClass<Test>.getName() + '@' + Integer.toHexString(hashCode())
|
||||||
}
|
}
|
||||||
open protected fun finalize() : Unit {
|
open protected fun finalize() : Unit {
|
||||||
super.finalize()
|
super.finalize()
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
class Base {
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return super.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
return super.equals(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return super.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Child extends Base {
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return super.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
return super.equals(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return super.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
namespace test
|
||||||
|
open class Base() {
|
||||||
|
open public fun hashCode() : Int {
|
||||||
|
return System.identityHashCode(this)
|
||||||
|
}
|
||||||
|
open public fun equals(o : Any?) : Boolean {
|
||||||
|
return this.identityEquals(o)
|
||||||
|
}
|
||||||
|
open public fun toString() : String? {
|
||||||
|
return getJavaClass<Base>.getName() + '@' + Integer.toHexString(hashCode())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
open class Child() : Base() {
|
||||||
|
override public fun hashCode() : Int {
|
||||||
|
return super.hashCode()
|
||||||
|
}
|
||||||
|
override public fun equals(o : Any?) : Boolean {
|
||||||
|
return super.equals(o)
|
||||||
|
}
|
||||||
|
override public fun toString() : String? {
|
||||||
|
return super.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user