New J2K: Use returnType instead of methodSymbol in operator expressions
This commit is contained in:
committed by
Ilya Kirillov
parent
a92c5ebe61
commit
8aa28c0d50
@@ -33,6 +33,7 @@ object ConversionsRunner {
|
||||
+AssignmentStatementOperatorConversion()
|
||||
+AssignmentStatementSimplifyValConversion()
|
||||
+AssignmentStatementSimplifyAlsoConversion()
|
||||
+PolyadicExpressionConversion(context)
|
||||
+OperatorExpressionConversion(context)
|
||||
+ThrowStatementConversion()
|
||||
+EnumClassConversion()
|
||||
@@ -52,7 +53,6 @@ object ConversionsRunner {
|
||||
+JavaMethodToKotlinFunctionConversion(context)
|
||||
+MainFunctionConversion(context)
|
||||
+AssertStatementConversion(context)
|
||||
+PolyadicExpressionConversion(context)
|
||||
+SwitchStatementConversion(context)
|
||||
+LiteralConversion()
|
||||
+ForConversion(context)
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.psi.JavaTokenType.THIS_KEYWORD
|
||||
import com.intellij.psi.impl.source.tree.ChildRole
|
||||
import com.intellij.psi.impl.source.tree.java.*
|
||||
import com.intellij.psi.javadoc.PsiDocComment
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import com.intellij.psi.util.InheritanceUtil
|
||||
import com.intellij.psi.util.PsiUtil
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||
@@ -32,6 +33,8 @@ import org.jetbrains.kotlin.j2k.ast.Nullability
|
||||
import org.jetbrains.kotlin.j2k.tree.*
|
||||
import org.jetbrains.kotlin.j2k.tree.JKLiteralExpression.LiteralType.*
|
||||
import org.jetbrains.kotlin.j2k.tree.impl.*
|
||||
import org.jetbrains.kotlin.lexer.KtToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
|
||||
@@ -99,7 +102,7 @@ class JavaToJKTreeBuilder(
|
||||
)
|
||||
is PsiPolyadicExpression -> JKJavaPolyadicExpressionImpl(
|
||||
operands.map { it.toJK() },
|
||||
Array(operands.lastIndex) { getTokenBeforeOperand(operands[it + 1]) }.map { it?.toJK() ?: TODO() }
|
||||
Array(operands.lastIndex) { getTokenBeforeOperand(operands[it + 1]) }.map { it?.tokenType?.toJK() ?: TODO() }
|
||||
)
|
||||
is PsiArrayInitializerExpression -> toJK()
|
||||
is PsiLambdaExpression -> toJK()
|
||||
@@ -132,12 +135,21 @@ class JavaToJKTreeBuilder(
|
||||
return JKJavaAssignmentExpressionImpl(
|
||||
lExpression.toJK() as? JKAssignableExpression ?: error("Its possible? ${lExpression.toJK().prettyDebugPrintTree()}"),
|
||||
rExpression.toJK(),
|
||||
operationSign.toJK()
|
||||
operationSign.tokenType.toJK()
|
||||
)
|
||||
}
|
||||
|
||||
fun PsiBinaryExpression.toJK(): JKExpression {
|
||||
return JKBinaryExpressionImpl(lOperand.toJK(), rOperand.toJK(), operationSign.toJK())
|
||||
val token = when (operationSign.tokenType) {
|
||||
JavaTokenType.EQEQ, JavaTokenType.NE ->
|
||||
when {
|
||||
canKeepEqEq(lOperand, rOperand) -> operationSign.tokenType
|
||||
operationSign.tokenType == JavaTokenType.EQEQ -> KtTokens.EQEQEQ
|
||||
else -> KtTokens.EXCLEQEQEQ
|
||||
}
|
||||
else -> operationSign.tokenType
|
||||
}
|
||||
return JKBinaryExpressionImpl(lOperand.toJK(), rOperand.toJK(), token.toJK())
|
||||
}
|
||||
|
||||
fun PsiLiteralExpression.toJK(): JKLiteralExpression {
|
||||
@@ -157,10 +169,10 @@ class JavaToJKTreeBuilder(
|
||||
}
|
||||
}
|
||||
|
||||
fun PsiJavaToken.toJK(): JKOperator = JKJavaOperatorImpl.tokenToOperator[tokenType] ?: error("Unsupported token-type: $tokenType")
|
||||
fun IElementType.toJK(): JKOperator = JKJavaOperatorImpl.tokenToOperator[this] ?: error("Unsupported token-type: $this")
|
||||
|
||||
fun PsiPrefixExpression.toJK(): JKExpression {
|
||||
return JKPrefixExpressionImpl(operand.toJK(), operationSign.toJK()).let {
|
||||
return JKPrefixExpressionImpl(operand.toJK(), operationSign.tokenType.toJK()).let {
|
||||
if (it.operator.token.text in listOf("+", "-") && it.expression is JKLiteralExpression) {
|
||||
JKJavaLiteralExpressionImpl(
|
||||
it.operator.token.text + (it.expression as JKLiteralExpression).literal,
|
||||
@@ -171,7 +183,7 @@ class JavaToJKTreeBuilder(
|
||||
}
|
||||
|
||||
fun PsiPostfixExpression.toJK(): JKExpression {
|
||||
return JKPostfixExpressionImpl(operand.toJK(), operationSign.toJK())
|
||||
return JKPostfixExpressionImpl(operand.toJK(), operationSign.tokenType.toJK())
|
||||
}
|
||||
|
||||
fun PsiLambdaExpression.toJK(): JKExpression {
|
||||
|
||||
@@ -5,13 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.j2k.conversions
|
||||
|
||||
import org.jetbrains.kotlin.j2k.ConversionContext
|
||||
import org.jetbrains.kotlin.j2k.kotlinBinaryExpression
|
||||
import org.jetbrains.kotlin.j2k.kotlinPostfixExpression
|
||||
import org.jetbrains.kotlin.j2k.kotlinPrefixExpression
|
||||
import org.jetbrains.kotlin.j2k.*
|
||||
import org.jetbrains.kotlin.j2k.tree.*
|
||||
import org.jetbrains.kotlin.j2k.tree.impl.JKJavaOperatorImpl
|
||||
import org.jetbrains.kotlin.j2k.tree.impl.toKtToken
|
||||
import org.jetbrains.kotlin.j2k.tree.impl.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
|
||||
|
||||
class OperatorExpressionConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
|
||||
@@ -24,17 +21,37 @@ class OperatorExpressionConversion(private val context: ConversionContext) : Rec
|
||||
is JKBinaryExpression -> {
|
||||
val left = applyToElement(element::left.detached()) as JKExpression
|
||||
val right = applyToElement(element::right.detached()) as JKExpression
|
||||
kotlinBinaryExpression(left, right, operatorToken, context.symbolProvider)?.let { recurse(it) }
|
||||
recurse(convertBinaryExpression(left, right, operatorToken))
|
||||
}
|
||||
is JKPrefixExpression -> {
|
||||
val operand = applyToElement(element::expression.detached()) as JKExpression
|
||||
kotlinPrefixExpression(operand, operatorToken, context.symbolProvider)?.let { recurse(it) }
|
||||
recurse(kotlinPrefixExpression(operand, operatorToken, context.symbolProvider))
|
||||
}
|
||||
is JKPostfixExpression -> {
|
||||
val operand = applyToElement(element::expression.detached()) as JKExpression
|
||||
kotlinPostfixExpression(operand, operatorToken, context.symbolProvider)?.let { recurse(it) }
|
||||
recurse(kotlinPostfixExpression(operand, operatorToken, context.symbolProvider))
|
||||
}
|
||||
else -> TODO(element.javaClass.toString())
|
||||
} ?: recurse(element)
|
||||
}
|
||||
|
||||
private fun convertBinaryExpression(left: JKExpression, right: JKExpression, token: JKKtOperatorToken): JKBinaryExpression =
|
||||
convertStringImplicitConcatenation(left, right, token)
|
||||
?: kotlinBinaryExpression(left, right, token, context.symbolProvider)
|
||||
|
||||
|
||||
private fun convertStringImplicitConcatenation(left: JKExpression, right: JKExpression, token: JKKtOperatorToken): JKBinaryExpression? =
|
||||
if (token is JKKtSingleValueOperatorToken
|
||||
&& token.psiToken == KtTokens.PLUS
|
||||
&& right.type(context.symbolProvider)?.isStringType() == true
|
||||
&& left.type(context.symbolProvider)?.isStringType() == false
|
||||
) {
|
||||
val toStringCall =
|
||||
JKKtCallExpressionImpl(
|
||||
context.symbolProvider.provideByFqName("kotlin.Any.toString"),
|
||||
JKExpressionListImpl()
|
||||
)
|
||||
val qualifiedCall = JKQualifiedExpressionImpl(left, JKKtQualifierImpl.DOT, toStringCall)
|
||||
kotlinBinaryExpression(qualifiedCall, right, KtTokens.PLUS, context.symbolProvider)
|
||||
} else null
|
||||
}
|
||||
@@ -7,21 +7,20 @@ package org.jetbrains.kotlin.j2k.conversions
|
||||
|
||||
import org.jetbrains.kotlin.j2k.ConversionContext
|
||||
import org.jetbrains.kotlin.j2k.kotlinBinaryExpression
|
||||
import org.jetbrains.kotlin.j2k.tree.JKExpression
|
||||
import org.jetbrains.kotlin.j2k.tree.JKJavaPolyadicExpression
|
||||
import org.jetbrains.kotlin.j2k.tree.JKOperator
|
||||
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
|
||||
import org.jetbrains.kotlin.j2k.tree.*
|
||||
import org.jetbrains.kotlin.j2k.tree.impl.*
|
||||
|
||||
|
||||
class PolyadicExpressionConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
|
||||
override fun applyToElement(element: JKTreeElement): JKTreeElement {
|
||||
return (if (element is JKJavaPolyadicExpression)
|
||||
convertPolyadic(element.operands.also { element.operands = emptyList() }, element.tokens)
|
||||
else
|
||||
element).also {
|
||||
recurse(it)
|
||||
}
|
||||
return recurse(
|
||||
if (element is JKJavaPolyadicExpression)
|
||||
convertPolyadic(
|
||||
element.operands.also { element.operands = emptyList() },
|
||||
element.tokens
|
||||
)
|
||||
else element
|
||||
)
|
||||
}
|
||||
|
||||
private fun convertPolyadic(operands: List<JKExpression>, operators: List<JKOperator>): JKExpression {
|
||||
@@ -29,16 +28,15 @@ class PolyadicExpressionConversion(private val context: ConversionContext) : Rec
|
||||
operands.first()
|
||||
else {
|
||||
val operator = operators.maxBy { it.precedence }
|
||||
val token =
|
||||
when (operator) {
|
||||
is JKJavaOperatorImpl -> operator.token.toKtToken()
|
||||
is JKKtOperatorImpl -> operator.token
|
||||
else -> error("operator should be either kotlin or java")
|
||||
}
|
||||
when (operator) {
|
||||
is JKJavaOperatorImpl -> operator.token.toKtToken()
|
||||
is JKKtOperatorImpl -> operator.token
|
||||
else -> error("operator should be either kotlin or java")
|
||||
}
|
||||
val index = operators.indexOf(operator)
|
||||
val left = convertPolyadic(operands.subList(0, index + 1), operators.subList(0, index))
|
||||
val right = convertPolyadic(operands.subList(index + 1, operands.size), operators.subList(index + 1, operators.size))
|
||||
kotlinBinaryExpression(left, right, token, context.symbolProvider)!!
|
||||
JKBinaryExpressionImpl(left, right, operator)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.j2k
|
||||
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.tree.TokenSet
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.j2k.ast.Nullability
|
||||
import org.jetbrains.kotlin.j2k.conversions.RecursiveApplicableConversionBase
|
||||
@@ -14,6 +15,7 @@ import org.jetbrains.kotlin.j2k.conversions.multiResolveFqName
|
||||
import org.jetbrains.kotlin.j2k.conversions.resolveFqName
|
||||
import org.jetbrains.kotlin.j2k.tree.*
|
||||
import org.jetbrains.kotlin.j2k.tree.impl.*
|
||||
import org.jetbrains.kotlin.lexer.KtSingleValueToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
@@ -42,12 +44,12 @@ private fun JKType.classSymbol(symbolProvider: JKSymbolProvider) =
|
||||
else -> null
|
||||
}
|
||||
|
||||
private fun JKKtOperatorToken.binaryExpressionMethodSymbol(
|
||||
private fun JKKtOperatorToken.arithmeticMethodType(
|
||||
leftType: JKType,
|
||||
rightType: JKType,
|
||||
symbolProvider: JKSymbolProvider
|
||||
): JKMethodSymbol {
|
||||
fun PsiClass.methodSymbol() =
|
||||
): JKType? {
|
||||
fun PsiClass.methodReturnType() =
|
||||
allMethods
|
||||
.filter { it.name == operatorName }
|
||||
.firstOrNull {
|
||||
@@ -56,28 +58,13 @@ private fun JKKtOperatorToken.binaryExpressionMethodSymbol(
|
||||
if (type !is JKTypeParameterType) rightType.isSubtypeOf(type, symbolProvider)
|
||||
else true//TODO check for type bounds
|
||||
} != null
|
||||
}?.let { symbolProvider.provideDirectSymbol(it) as JKMethodSymbol }
|
||||
}?.let { it.returnType?.toJK(symbolProvider) }
|
||||
|
||||
|
||||
val classSymbol =
|
||||
if (leftType.isStringType()) symbolProvider.provideByFqName(KotlinBuiltIns.FQ_NAMES.string.toSafe())
|
||||
else leftType.classSymbol(symbolProvider)
|
||||
|
||||
val defaultClassSymbol by lazy {
|
||||
when (text) {
|
||||
"<", ">", "<=", ">=", "==", "!=", "&&", "||" ->
|
||||
JKUnresolvedMethod(
|
||||
text,
|
||||
kotlinTypeByName(
|
||||
KotlinBuiltIns.FQ_NAMES._boolean.toSafe().asString(),
|
||||
symbolProvider,
|
||||
Nullability.NotNull
|
||||
)
|
||||
)
|
||||
"+", "-", "*", "/" -> JKUnresolvedMethod(text, leftType)//TODO fix that
|
||||
else -> TODO()
|
||||
}
|
||||
}
|
||||
return when (classSymbol) {
|
||||
is JKMultiverseKtClassSymbol ->
|
||||
classSymbol.target.declarations
|
||||
@@ -86,53 +73,112 @@ private fun JKKtOperatorToken.binaryExpressionMethodSymbol(
|
||||
.filter { it.name == operatorName }
|
||||
.mapNotNull { symbolProvider.provideDirectSymbol(it) as? JKMethodSymbol }
|
||||
.firstOrNull { it.parameterTypes?.singleOrNull()?.takeIf { rightType.isSubtypeOf(it, symbolProvider) } != null }
|
||||
?: defaultClassSymbol
|
||||
is JKUniverseClassSymbol -> classSymbol.target.psi<PsiClass>()?.methodSymbol() ?: defaultClassSymbol
|
||||
is JKMultiverseClassSymbol -> classSymbol.target.methodSymbol() ?: defaultClassSymbol
|
||||
else -> defaultClassSymbol
|
||||
?.returnType
|
||||
is JKUniverseClassSymbol -> classSymbol.target.psi<PsiClass>()?.methodReturnType()
|
||||
is JKMultiverseClassSymbol -> classSymbol.target.methodReturnType()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun JKKtOperatorToken.unaryExpressionMethodSymbol(
|
||||
operandType: JKType,
|
||||
private fun JKKtOperatorToken.unaryExpressionMethodType(
|
||||
operandType: JKType?,
|
||||
symbolProvider: JKSymbolProvider
|
||||
): JKMethodSymbol {
|
||||
if (this == KtTokens.EXCLEQ) {
|
||||
return JKExclExclMethod(operandType)
|
||||
): JKType {
|
||||
if (operandType is JKNoType) {
|
||||
return operandType
|
||||
}
|
||||
val classSymbol = operandType.classSymbol(symbolProvider)
|
||||
if (this == KtTokens.EXCLEXCL) {
|
||||
return operandType!!
|
||||
}
|
||||
if (this == KtTokens.EXCL) {
|
||||
return symbolProvider.provideByFqName<JKClassSymbol>(KotlinBuiltIns.FQ_NAMES._boolean).asType()
|
||||
}
|
||||
if (this == KtTokens.MINUS || this == KtTokens.PLUS) {
|
||||
return operandType!!
|
||||
}
|
||||
val classSymbol = operandType!!.classSymbol(symbolProvider)
|
||||
return when (classSymbol) {
|
||||
is JKMultiverseKtClassSymbol ->// todo look for extensions
|
||||
classSymbol.target.declarations.asSequence()
|
||||
.filterIsInstance<KtNamedFunction>()
|
||||
.filter { it.name == operatorName }
|
||||
.mapNotNull { symbolProvider.provideDirectSymbol(it) as? JKMethodSymbol }
|
||||
.firstOrNull()!!
|
||||
.mapNotNull { it.typeReference?.typeElement?.toJK(symbolProvider) }
|
||||
.firstOrNull() ?: TODO(classSymbol::class.toString() + this.operatorName)
|
||||
null -> TODO(" No class symbol")
|
||||
else -> TODO(classSymbol::class.toString())
|
||||
}
|
||||
}
|
||||
|
||||
private val booleanOperators = TokenSet.create(
|
||||
KtTokens.LT,
|
||||
KtTokens.GT,
|
||||
KtTokens.LTEQ,
|
||||
KtTokens.GTEQ,
|
||||
KtTokens.EQEQEQ,
|
||||
KtTokens.EXCLEQEQEQ,
|
||||
KtTokens.EQEQ,
|
||||
KtTokens.EXCLEQ,
|
||||
KtTokens.ANDAND,
|
||||
KtTokens.OROR
|
||||
)
|
||||
|
||||
private val arithmeticOperators = TokenSet.create(
|
||||
KtTokens.MUL,
|
||||
KtTokens.PLUS,
|
||||
KtTokens.MINUS,
|
||||
KtTokens.DIV,
|
||||
KtTokens.PERC
|
||||
)
|
||||
|
||||
private fun JKKtOperatorToken.defaultReturnType(leftType: JKType?, rightType: JKType?, symbolProvider: JKSymbolProvider): JKType? {
|
||||
if (this is JKKtSingleValueOperatorToken && psiToken in arithmeticOperators) return leftType
|
||||
return null
|
||||
}
|
||||
|
||||
fun kotlinBinaryExpression(
|
||||
left: JKExpression,
|
||||
right: JKExpression,
|
||||
token: JKKtOperatorToken,
|
||||
symbolProvider: JKSymbolProvider
|
||||
): JKBinaryExpression? {
|
||||
val leftType = left.type(symbolProvider) ?: return null
|
||||
val rightType = right.type(symbolProvider) ?: return null
|
||||
val methodSymbol = token.binaryExpressionMethodSymbol(leftType, rightType, symbolProvider)
|
||||
return JKBinaryExpressionImpl(left, right, JKKtOperatorImpl(token, methodSymbol))
|
||||
): JKBinaryExpression {
|
||||
val returnType =
|
||||
when {
|
||||
token is JKKtSingleValueOperatorToken && token.psiToken in booleanOperators ->
|
||||
JKClassTypeImpl(symbolProvider.provideByFqName(KotlinBuiltIns.FQ_NAMES._boolean))
|
||||
else -> {
|
||||
val leftType = left.type(symbolProvider)
|
||||
val rightType = right.type(symbolProvider)
|
||||
leftType?.let { l ->
|
||||
rightType?.let { r ->
|
||||
token.arithmeticMethodType(l, r, symbolProvider)
|
||||
}
|
||||
} ?: token.defaultReturnType(leftType, rightType, symbolProvider)
|
||||
?: symbolProvider.provideByFqName<JKClassSymbol>(KotlinBuiltIns.FQ_NAMES.nothing).asType()
|
||||
}
|
||||
}
|
||||
return JKBinaryExpressionImpl(left, right, JKKtOperatorImpl(token, returnType))
|
||||
}
|
||||
|
||||
fun kotlinBinaryExpression(
|
||||
left: JKExpression,
|
||||
right: JKExpression,
|
||||
token: KtSingleValueToken,
|
||||
symbolProvider: JKSymbolProvider
|
||||
): JKBinaryExpression =
|
||||
kotlinBinaryExpression(
|
||||
left,
|
||||
right,
|
||||
JKKtSingleValueOperatorToken(token),
|
||||
symbolProvider
|
||||
)
|
||||
|
||||
fun kotlinPrefixExpression(
|
||||
operand: JKExpression,
|
||||
token: JKKtOperatorToken,
|
||||
symbolProvider: JKSymbolProvider
|
||||
): JKPrefixExpression? {
|
||||
val operandType = operand.type(symbolProvider) ?: return null
|
||||
val methodSymbol = token.unaryExpressionMethodSymbol(operandType, symbolProvider)
|
||||
): JKPrefixExpression {
|
||||
val operandType = operand.type(symbolProvider)
|
||||
val methodSymbol = token.unaryExpressionMethodType(operandType, symbolProvider)
|
||||
return JKPrefixExpressionImpl(operand, JKKtOperatorImpl(token, methodSymbol))
|
||||
}
|
||||
|
||||
@@ -140,9 +186,9 @@ fun kotlinPostfixExpression(
|
||||
operand: JKExpression,
|
||||
token: JKKtOperatorToken,
|
||||
symbolProvider: JKSymbolProvider
|
||||
): JKPostfixExpression? {
|
||||
val operandType = operand.type(symbolProvider) ?: return null
|
||||
val methodSymbol = token.unaryExpressionMethodSymbol(operandType, symbolProvider)
|
||||
): JKPostfixExpression {
|
||||
val operandType = operand.type(symbolProvider)
|
||||
val methodSymbol = token.unaryExpressionMethodType(operandType, symbolProvider)
|
||||
return JKPostfixExpressionImpl(operand, JKKtOperatorImpl(token, methodSymbol))
|
||||
}
|
||||
|
||||
@@ -181,10 +227,10 @@ fun rangeExpression(
|
||||
conversionContext: ConversionContext,
|
||||
psiContext: PsiElement
|
||||
): JKExpression {
|
||||
val symbol = conversionContext.symbolProvider.provideDirectSymbol(
|
||||
val returnType = (conversionContext.symbolProvider.provideDirectSymbol(
|
||||
multiResolveFqName(ClassId.fromString("kotlin/ranges/$operatorName"), psiContext).first()
|
||||
) as JKMethodSymbol
|
||||
return JKBinaryExpressionImpl(from, to, JKKtOperatorImpl(JKKtWordOperatorToken(operatorName), symbol))
|
||||
) as JKMethodSymbol).returnType
|
||||
return JKBinaryExpressionImpl(from, to, JKKtOperatorImpl(JKKtWordOperatorToken(operatorName), returnType!!))
|
||||
}
|
||||
|
||||
fun blockStatement(vararg statements: JKStatement) =
|
||||
@@ -291,7 +337,7 @@ fun JKFieldAccessExpression.isInDecrementOrIncrement(): Boolean =
|
||||
fun JKExpression.bangedBangedExpr(symbolProvider: JKSymbolProvider): JKExpression =
|
||||
JKPostfixExpressionImpl(
|
||||
this,
|
||||
JKKtOperatorImpl(KtTokens.EXCLEXCL, JKExclExclMethod(type(symbolProvider)!!))
|
||||
JKKtOperatorImpl(KtTokens.EXCLEXCL, type(symbolProvider)!!)
|
||||
)
|
||||
|
||||
fun JKVariable.hasWritableUsages(scope: JKTreeElement, context: ConversionContext): Boolean =
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.j2k
|
||||
|
||||
import com.intellij.codeInsight.generation.GenerateEqualsHelper.getEqualsSignature
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.util.MethodSignatureUtil
|
||||
|
||||
//copied from old j2k
|
||||
fun canKeepEqEq(left: PsiExpression, right: PsiExpression?): Boolean {
|
||||
if (left.isNullLiteral() || (right?.isNullLiteral() == true)) return true
|
||||
val type = left.type
|
||||
when (type) {
|
||||
is PsiPrimitiveType, is PsiArrayType -> return true
|
||||
|
||||
is PsiClassType -> {
|
||||
if (right?.type is PsiPrimitiveType) return true
|
||||
|
||||
val psiClass = type.resolve() ?: return false
|
||||
if (!psiClass.hasModifierProperty(PsiModifier.FINAL)) return false
|
||||
if (psiClass.isEnum) return true
|
||||
|
||||
val equalsSignature = getEqualsSignature(left.project, GlobalSearchScope.allScope(left.project))
|
||||
val equalsMethod = MethodSignatureUtil.findMethodBySignature(psiClass, equalsSignature, true)
|
||||
if (equalsMethod != null && equalsMethod.containingClass?.qualifiedName != CommonClassNames.JAVA_LANG_OBJECT) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
else -> return false
|
||||
}
|
||||
|
||||
}
|
||||
@@ -145,6 +145,9 @@ fun JKJavaOperatorToken.toKtToken(): JKKtOperatorToken =
|
||||
JavaTokenType.MINUSMINUS -> JKKtSingleValueOperatorToken(KtTokens.MINUSMINUS)
|
||||
JavaTokenType.EXCL -> JKKtSingleValueOperatorToken(KtTokens.EXCL)
|
||||
|
||||
KtTokens.EQEQEQ -> JKKtSingleValueOperatorToken(KtTokens.EQEQEQ)
|
||||
KtTokens.EXCLEQEQEQ -> JKKtSingleValueOperatorToken(KtTokens.EXCLEQEQEQ)
|
||||
|
||||
JavaTokenType.AND -> JKKtWordOperatorToken("and")
|
||||
JavaTokenType.OR -> JKKtWordOperatorToken("or")
|
||||
JavaTokenType.XOR -> JKKtWordOperatorToken("xor")
|
||||
@@ -180,9 +183,11 @@ class JKJavaOperatorImpl private constructor(psiToken: IElementType) : JKOperato
|
||||
}
|
||||
|
||||
companion object {
|
||||
val tokenToOperator = OPERATION_BIT_SET.types.associate {
|
||||
it to JKJavaOperatorImpl(it)
|
||||
}
|
||||
val tokenToOperator =
|
||||
(OPERATION_BIT_SET.types + arrayOf(KtTokens.EQEQEQ, KtTokens.EXCLEQEQEQ))
|
||||
.associate {
|
||||
it to JKJavaOperatorImpl(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -102,13 +102,11 @@ class JKBlockImpl(statements: List<JKStatement> = emptyList()) : JKBlock, JKBran
|
||||
override var statements by children(statements)
|
||||
}
|
||||
|
||||
//todo split to java and kt sbinary expression
|
||||
class JKBinaryExpressionImpl(
|
||||
left: JKExpression,
|
||||
right: JKExpression,
|
||||
override var operator: JKOperator
|
||||
) : JKBinaryExpression,
|
||||
JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
|
||||
) : JKBinaryExpression, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
|
||||
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitBinaryExpression(this, data)
|
||||
override var right by child(right)
|
||||
override var left by child(left)
|
||||
|
||||
@@ -104,10 +104,10 @@ class JKKtWordOperatorToken(override val text: String) : JKKtOperatorToken {
|
||||
override val operatorName: String = text
|
||||
}
|
||||
|
||||
class JKKtOperatorImpl(override val token: JKKtOperatorToken, val methodSymbol: JKMethodSymbol) : JKOperator, JKElementBase() {
|
||||
constructor(singleValueToken: KtSingleValueToken, methodSymbol: JKMethodSymbol) : this(
|
||||
class JKKtOperatorImpl(override val token: JKKtOperatorToken, val returnType: JKType) : JKOperator, JKElementBase() {
|
||||
constructor(singleValueToken: KtSingleValueToken, returnType: JKType) : this(
|
||||
JKKtSingleValueOperatorToken(singleValueToken),
|
||||
methodSymbol
|
||||
returnType
|
||||
)
|
||||
|
||||
override val precedence: Int
|
||||
|
||||
@@ -221,6 +221,7 @@ interface JKOperatorExpression : JKExpression {
|
||||
var operator: JKOperator
|
||||
}
|
||||
|
||||
//TODO make left & right to be immutable
|
||||
interface JKBinaryExpression : JKOperatorExpression {
|
||||
var left: JKExpression
|
||||
var right: JKExpression
|
||||
|
||||
@@ -30,13 +30,9 @@ fun JKExpression.type(symbolProvider: JKSymbolProvider): JKType? =
|
||||
when (this) {
|
||||
is JKLiteralExpression -> type.toJkType(symbolProvider)
|
||||
is JKOperatorExpression -> {
|
||||
if (operator !is JKKtOperatorImpl) {
|
||||
error("Cannot get type of ${operator::class}, it should be first converted to KtOperator")
|
||||
}
|
||||
val operatorSymbol = (operator as JKKtOperatorImpl).methodSymbol
|
||||
if (operatorSymbol.name == "compareTo") {
|
||||
kotlinTypeByName("kotlin.Boolean", symbolProvider)
|
||||
} else operatorSymbol.returnType
|
||||
(operator as? JKKtOperatorImpl)?.returnType
|
||||
?: error("Cannot get type of ${operator::class}, it should be first converted to KtOperator")
|
||||
|
||||
}
|
||||
is JKMethodCallExpression -> identifier.returnType
|
||||
is JKFieldAccessExpressionImpl -> identifier.fieldType
|
||||
@@ -118,6 +114,9 @@ fun PsiType.toJK(symbolProvider: JKSymbolProvider, nullability: Nullability = Nu
|
||||
}
|
||||
}
|
||||
|
||||
fun JKClassSymbol.asType(nullability: Nullability = Nullability.Default): JKClassType =
|
||||
JKClassTypeImpl(this, emptyList(), nullability)
|
||||
|
||||
fun JKType.isSubtypeOf(other: JKType, symbolProvider: JKSymbolProvider): Boolean =
|
||||
other.toKtType(symbolProvider)
|
||||
?.let { otherType -> this.toKtType(symbolProvider)?.isSubtypeOf(otherType) } == true
|
||||
|
||||
Reference in New Issue
Block a user