New J2K: Separate new j2k from old j2k

This commit is contained in:
Ilya Kirillov
2019-02-04 11:30:59 +03:00
committed by Ilya Kirillov
parent e6f0a242fd
commit c827247272
109 changed files with 909 additions and 558 deletions
@@ -1,28 +0,0 @@
/*
* Copyright 2010-2018 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.openapi.project.Project
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.j2k.tree.JKElement
data class ConversionContext(
val symbolProvider: JKSymbolProvider,
val converter: NewJavaToKotlinConverter,
val inConversionContext: (PsiElement) -> Boolean
) {
val project: Project get() = converter.project
val typeFlavorCalculator = TypeFlavorCalculator(object : TypeFlavorConverterFacade {
override val referenceSearcher: ReferenceSearcher
get() = converter.converterServices.oldServices.referenceSearcher
override val javaDataFlowAnalyzerFacade: JavaDataFlowAnalyzerFacade
get() = converter.converterServices.oldServices.javaDataFlowAnalyzerFacade
override val resolverForConverter: ResolverForConverter
get() = converter.converterServices.oldServices.resolverForConverter
override fun inConversionScope(element: PsiElement): Boolean = inConversionContext(element)
})
}
@@ -1,89 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k
import org.jetbrains.kotlin.j2k.conversions.*
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
object ConversionsRunner {
private fun createRootConversion(context: ConversionContext) =
batchPipe {
//Java --> Kotlin conversions
+JavaModifiersConversion(context)
+JavaAnnotationsConversion(context)
+AnnotationClassConversion(context)
+AnnotationConversion(context)
+ModalityConversion(context)
+BoxedTypeOperationsConversion(context)
+AssignmentAsExpressionToAlsoConversion(context)
+AssignmentStatementValCreationConversion(context)
+AssignmentStatementOperatorConversion()
+AssignmentStatementSimplifyValConversion()
+AssignmentStatementSimplifyAlsoConversion()
+AssignmentStatementSplitAlsoConversion()
+PolyadicExpressionConversion(context)
+OperatorExpressionConversion(context)
+ThrowStatementConversion()
+ArrayInitializerConversion(context)
+TryStatementConversion(context)
+SynchronizedStatementConversion(context)
+DefaultArgumentsConversion(context)
+ConstructorConversion(context)
+ImplicitInitializerConversion(context)
+ParameterModificationInMethodCallsConversion(context)
+PrintlnConversion(context)
+BlockToRunConversion(context)
+JetbrainsNullableAnnotationsConverter(context)
+PrimaryConstructorDetectConversion(context)
+InsertDefaultPrimaryConstructorConversion(context)
+FieldToPropertyConversion()
+JavaStandartMethodsConversion(context)
+JavaMethodToKotlinFunctionConversion(context)
+MainFunctionConversion(context)
+AssertStatementConversion(context)
+SwitchStatementConversion(context)
+LiteralConversion()
+ForConversion(context)
+LabeledStatementConversion()
+ForInConversion(context)
+TypeParametersNullabilityConversion()
+ArrayOperationsConversion(context)
+BuiltinMembersConversion(context)
+EqualsOperatorConversion(context)
+TypeMappingConversion(context)
+ImplicitCastsConversion(context)
+LowerNullabilityInFunctionParametersConversion(context)
+DefaultNullabilityToNullableConversion()
+NullableQualifierConversion(context)
+InternalClassConversion()
//Kotlin --> Kotlin conversions
+InnerClassConversion()
+StaticsToCompanionExtractConversion()
+InterfaceWithFieldConversion()
+ClassToObjectPromotionConversion(context)
+ImportStatementConversion()
+SortClassMembersConversion()
}
fun doApply(trees: List<JKTreeElement>, context: ConversionContext) {
val conversion = createRootConversion(context)
conversion.runConversion(trees, context)
}
}
@@ -1,163 +0,0 @@
/*
* Copyright 2010-2018 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.psi.*
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
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.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class JKSymbolProvider {
val symbolsByFqName = mutableMapOf<String, JKSymbol>()
val symbolsByPsi = mutableMapOf<PsiElement, JKSymbol>()
val symbolsByJK = mutableMapOf<JKDeclaration, JKSymbol>()
private val elementVisitor = ElementVisitor()
fun preBuildTree(files: List<PsiJavaFile>) {
files.forEach { it.accept(elementVisitor) }
}
fun provideDirectSymbol(psi: PsiElement): JKSymbol {
return symbolsByPsi.getOrPut(psi) {
when (psi) {
is KtLightDeclaration<*, *> -> provideDirectSymbol(psi.kotlinOrigin!!)
is PsiClass -> JKMultiverseClassSymbol(psi)
is KtClassOrObject -> JKMultiverseKtClassSymbol(psi)
is PsiMethod -> JKMultiverseMethodSymbol(psi, this)
is PsiField -> JKMultiverseFieldSymbol(psi, this)
is KtNamedFunction -> JKMultiverseFunctionSymbol(psi, this)
is KtProperty -> JKMultiversePropertySymbol(psi, this)
is KtParameter -> JKMultiversePropertySymbol(psi, this)
is PsiParameter -> JKMultiverseFieldSymbol(psi, this)
is PsiLocalVariable -> JKMultiverseFieldSymbol(psi, this)
else -> TODO(psi::class.toString())
}
}
}
internal inline fun <reified T : JKSymbol> provideSymbol(reference: PsiReference): T {
val target = reference.resolve()
if (target != null) return provideDirectSymbol(target) as T
return (if (isAssignable<T, JKUnresolvedField>()) JKUnresolvedField(reference.canonicalText, this) else JKUnresolvedMethod(reference)) as T
}
fun provideUniverseSymbol(psi: PsiElement, jk: JKDeclaration): JKSymbol = provideUniverseSymbol(psi).also {
when (it) {
is JKUniverseClassSymbol -> it.target = jk as JKClass
is JKUniverseFieldSymbol -> it.target = jk as JKVariable
is JKUniverseMethodSymbol -> it.target = jk as JKMethod
}
symbolsByJK[jk] = it
}
fun provideUniverseSymbol(psi: PsiElement): JKSymbol = symbolsByPsi.getOrPut(psi) {
when (psi) {
is PsiField, is PsiParameter, is PsiLocalVariable -> JKUniverseFieldSymbol()
is PsiMethod -> JKUniverseMethodSymbol(this)
is PsiClass -> JKUniverseClassSymbol()
else -> TODO()
}
}
fun transferSymbol(to: JKDeclaration, from: JKDeclaration) = symbolsByJK[from]!!.let {
it as JKUniverseSymbol<*>
it.target = to
symbolsByJK[to] = it
}
fun provideUniverseSymbol(jk: JKClass): JKClassSymbol = symbolsByJK.getOrPut(jk) {
JKUniverseClassSymbol().also { it.target = jk }
} as JKClassSymbol
fun provideUniverseSymbol(jk: JKVariable): JKFieldSymbol = symbolsByJK.getOrPut(jk) {
JKUniverseFieldSymbol().also { it.target = jk }
} as JKFieldSymbol
fun provideUniverseSymbol(jk: JKMethod): JKMethodSymbol = symbolsByJK.getOrPut(jk) {
JKUniverseMethodSymbol(this).also { it.target = jk }
} as JKMethodSymbol
internal inline fun <reified T : JKSymbol> provideByFqName(
classId: ClassId,
multiResolve: Boolean = false,
context: PsiElement = symbolsByPsi.keys.first()
): T {
val fqName = classId.asSingleFqName().asString().replace('/', '.')
if (fqName in symbolsByFqName) {
return symbolsByFqName[fqName] as T
}
val resolved =
if (multiResolve) multiResolveFqName(classId, context).firstOrNull()
else resolveFqName(classId, context)
val symbol = resolved?.let(::provideDirectSymbol).safeAs<T>()
return symbol ?: when {
isAssignable<T, JKUnresolvedMethod>() -> JKUnresolvedMethod(fqName)
isAssignable<T, JKUnresolvedField>() -> JKUnresolvedField(fqName, this)
else -> JKUnresolvedClassSymbol(fqName)
} as T
}
@Deprecated("", ReplaceWith("provideByFqName(fqName, true, context)"))
internal inline fun <reified T : JKSymbol> provideByFqNameMulti(fqName: String, context: PsiElement = symbolsByPsi.keys.first()): T =
provideByFqName(ClassId.fromString(fqName), true, context)
internal inline fun <reified T : JKSymbol> provideByFqName(
fqName: String,
multiResolve: Boolean = false,
context: PsiElement = symbolsByPsi.keys.first()
): T =
provideByFqName(ClassId.fromString(fqName), multiResolve, context)
internal inline fun <reified T : JKSymbol> provideByFqName(
fqName: FqName,
multiResolve: Boolean = false,
context: PsiElement = symbolsByPsi.keys.first()
): T =
provideByFqName(fqName.asString(), multiResolve, context)
internal inline fun <reified T : JKSymbol> provideByFqName(
fqName: FqNameUnsafe,
multiResolve: Boolean = false,
context: PsiElement = symbolsByPsi.keys.first()
): T =
provideByFqName(fqName.asString(), multiResolve, context)
private inner class ElementVisitor : JavaElementVisitor() {
override fun visitClass(aClass: PsiClass) {
provideUniverseSymbol(aClass)
aClass.acceptChildren(this)
}
override fun visitField(field: PsiField) {
provideUniverseSymbol(field)
}
override fun visitMethod(method: PsiMethod) {
provideUniverseSymbol(method)
}
override fun visitEnumConstant(enumConstant: PsiEnumConstant) {
provideUniverseSymbol(enumConstant)
}
override fun visitFile(file: PsiFile) {
file.acceptChildren(this)
}
}
internal inline fun <reified A, reified B> isAssignable(): Boolean = A::class.java.isAssignableFrom(B::class.java)
}
@@ -1,782 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k
import com.intellij.lang.jvm.JvmAnnotatedElement
import com.intellij.psi.*
import com.intellij.psi.JavaTokenType.SUPER_KEYWORD
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
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.idea.j2k.content
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
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class JavaToJKTreeBuilder(
var symbolProvider: JKSymbolProvider,
private val converterServices: NewJavaToKotlinServices
) {
private val expressionTreeMapper = ExpressionTreeMapper()
val referenceSearcher: ReferenceSearcher = converterServices.oldServices.referenceSearcher
private val declarationMapper = DeclarationMapper(expressionTreeMapper)
private fun PsiJavaFile.toJK(): JKFile =
JKFileImpl(
packageStatement?.toJK() ?: JKPackageDeclarationImpl(JKNameIdentifierImpl("")),
importList?.importStatements?.map { it.toJK() }.orEmpty(),
with(declarationMapper) { classes.map { it.toJK() } }
)
private fun PsiPackageStatement.toJK(): JKPackageDeclaration =
JKPackageDeclarationImpl(JKNameIdentifierImpl(packageName))
private fun PsiImportStatement.toJK(): JKImportStatementImpl {
val target = resolve()
val rawName = text.substringAfter("import").substringBeforeLast(";").trim()
val name =
if (target is KtLightClassForFacade) rawName.replaceAfterLast('.', "*")
else rawName
return JKImportStatementImpl(JKNameIdentifierImpl(name))
}
private inner class ExpressionTreeMapper {
fun PsiExpression?.toJK(): JKExpression {
return when (this) {
null -> JKStubExpressionImpl()
is PsiBinaryExpression -> toJK()
is PsiPrefixExpression -> toJK()
is PsiPostfixExpression -> toJK()
is PsiLiteralExpression -> toJK()
is PsiMethodCallExpression -> toJK()
is PsiReferenceExpression -> toJK()
is PsiNewExpression -> toJK()
is PsiArrayAccessExpression -> toJK()
is PsiTypeCastExpression -> toJK()
is PsiParenthesizedExpression -> toJK()
is PsiAssignmentExpression -> toJK()
is PsiInstanceOfExpression -> toJK()
is PsiThisExpression ->
JKThisExpressionImpl(
qualifier?.referenceName?.let { JKLabelTextImpl(JKNameIdentifierImpl(it)) } ?: JKLabelEmptyImpl()
)
is PsiSuperExpression ->
JKSuperExpressionImpl(
qualifier?.referenceName?.let { JKLabelTextImpl(JKNameIdentifierImpl(it)) } ?: JKLabelEmptyImpl()
)
is PsiConditionalExpression -> JKIfElseExpressionImpl(
condition.toJK(), thenExpression.toJK(), elseExpression.toJK()
)
is PsiPolyadicExpression -> JKJavaPolyadicExpressionImpl(
operands.map { it.toJK() },
Array(operands.lastIndex) { getTokenBeforeOperand(operands[it + 1]) }.map { it?.tokenType?.toJK() ?: TODO() }
)
is PsiArrayInitializerExpression -> toJK()
is PsiLambdaExpression -> toJK()
is PsiClassObjectAccessExpressionImpl -> toJK()
else -> {
throw RuntimeException("Not supported: ${this::class}")
}
}.also {
if (this != null) (it as PsiOwner).psi = this
}
}
fun PsiClassObjectAccessExpressionImpl.toJK(): JKClassLiteralExpression {
val type = operand.type.toJK(symbolProvider).updateNullabilityRecursively(Nullability.NotNull)
return JKClassLiteralExpressionImpl(
JKTypeElementImpl(type),
when (type) {
is JKJavaPrimitiveType -> JKClassLiteralExpression.LiteralType.JAVA_PRIMITIVE_CLASS
is JKJavaVoidType -> JKClassLiteralExpression.LiteralType.JAVA_VOID_TYPE
else -> JKClassLiteralExpression.LiteralType.JAVA_CLASS
}
)
}
fun PsiInstanceOfExpression.toJK(): JKKtIsExpression =
JKKtIsExpressionImpl(operand.toJK(), JKTypeElementImpl(checkType?.type?.toJK(symbolProvider) ?: JKNoTypeImpl))
fun PsiAssignmentExpression.toJK(): JKJavaAssignmentExpression {
return JKJavaAssignmentExpressionImpl(
lExpression.toJK() as? JKAssignableExpression ?: error("Its possible? ${lExpression.toJK().prettyDebugPrintTree()}"),
rExpression.toJK(),
operationSign.tokenType.toJK()
)
}
fun PsiBinaryExpression.toJK(): JKExpression {
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 {
require(this is PsiLiteralExpressionImpl)
return when (this.literalElementType) {
JavaTokenType.NULL_KEYWORD -> JKNullLiteral()
JavaTokenType.TRUE_KEYWORD -> JKBooleanLiteral(true)
JavaTokenType.FALSE_KEYWORD -> JKBooleanLiteral(false)
JavaTokenType.STRING_LITERAL -> JKJavaLiteralExpressionImpl(text, STRING)
JavaTokenType.CHARACTER_LITERAL -> JKJavaLiteralExpressionImpl(text, CHAR)
JavaTokenType.INTEGER_LITERAL -> JKJavaLiteralExpressionImpl(text, INT)
JavaTokenType.LONG_LITERAL -> JKJavaLiteralExpressionImpl(text, LONG)
JavaTokenType.FLOAT_LITERAL -> JKJavaLiteralExpressionImpl(text, FLOAT)
JavaTokenType.DOUBLE_LITERAL -> JKJavaLiteralExpressionImpl(text, DOUBLE)
else -> error("Unknown literal element type: ${this.literalElementType}")
}
}
fun IElementType.toJK(): JKOperator = JKJavaOperatorImpl.tokenToOperator[this] ?: error("Unsupported token-type: $this")
fun PsiPrefixExpression.toJK(): JKExpression {
return JKPrefixExpressionImpl(operand.toJK(), operationSign.tokenType.toJK()).let {
if (it.operator.token in listOf(JavaTokenType.PLUS, JavaTokenType.MINUS)
&& it.expression is JKLiteralExpression
) {
JKJavaLiteralExpressionImpl(
it.operator.token.text + (it.expression as JKLiteralExpression).literal,
(it.expression as JKLiteralExpression).type
)
} else it
}
}
fun PsiPostfixExpression.toJK(): JKExpression {
return JKPostfixExpressionImpl(operand.toJK(), operationSign.tokenType.toJK())
}
fun PsiLambdaExpression.toJK(): JKExpression {
return JKLambdaExpressionImpl(
body.let {
when (it) {
is PsiExpression -> JKExpressionStatementImpl(it.toJK())
is PsiCodeBlock -> JKBlockStatementImpl(with(declarationMapper) { it.toJK() })
else -> JKBlockStatementImpl(JKBodyStub)
}
},
with(declarationMapper) { parameterList.parameters.map { it.toJK() } }
)
}
private fun JKExpression.qualified(qualifier: JKExpression?) =
if (qualifier != null && qualifier !is JKStubExpression) {
JKQualifiedExpressionImpl(qualifier, JKJavaQualifierImpl.DOT, this)
} else this
//TODO mostly copied from old j2k, refactor
fun PsiMethodCallExpression.toJK(): JKExpression {
val arguments = argumentList
val typeArguments = typeArgumentList.toJK()
val qualifier = methodExpression.qualifierExpression?.toJK()
val target = methodExpression.resolve()
val symbol = target?.let {
symbolProvider.provideDirectSymbol(it)
} ?: JKUnresolvedMethod(methodExpression)
return when {
methodExpression.referenceNameElement is PsiKeyword -> {
val callee = when ((methodExpression.referenceNameElement as PsiKeyword).tokenType) {
SUPER_KEYWORD -> JKSuperExpressionImpl()
THIS_KEYWORD -> JKThisExpressionImpl(JKLabelEmptyImpl())
else -> error("Unknown keyword in callee position")
}
JKDelegationConstructorCallImpl(symbol as JKMethodSymbol, callee, arguments.toJK())
}
target is KtLightMethod -> {
val origin = target.kotlinOrigin
when (origin) {
is KtNamedFunction -> {
if (origin.isExtensionDeclaration()) {
val receiver = arguments.expressions.firstOrNull()?.toJK()?.parenthesizeIfBinaryExpression()
JKJavaMethodCallExpressionImpl(
symbolProvider.provideDirectSymbol(origin) as JKMethodSymbol,
arguments.expressions.drop(1).map { it.toJK() }.toExpressionList(),
typeArguments
).qualified(receiver)
} else {
JKJavaMethodCallExpressionImpl(
symbolProvider.provideDirectSymbol(origin) as JKMethodSymbol,
arguments.expressions.map { it.toJK() }.toExpressionList(),
typeArguments
).qualified(qualifier)
}
}
is KtProperty, is KtPropertyAccessor, is KtParameter -> {
val property =
if (origin is KtPropertyAccessor) origin.parent as KtProperty
else origin as KtNamedDeclaration
val parameterCount = target.parameterList.parameters.size
val propertyAccessExpression =
JKFieldAccessExpressionImpl(symbolProvider.provideDirectSymbol(property) as JKFieldSymbol)
val isExtension = property.isExtensionDeclaration()
val isTopLevel = origin.getStrictParentOfType<KtClassOrObject>() == null
val propertyAccess = if (isTopLevel) {
if (isExtension) JKQualifiedExpressionImpl(
arguments.expressions.first().toJK(),
JKJavaQualifierImpl.DOT,
propertyAccessExpression
)
else propertyAccessExpression
} else propertyAccessExpression.qualified(qualifier) as JKAssignableExpression
when (if (isExtension) parameterCount - 1 else parameterCount) {
0 /* getter */ ->
propertyAccess
1 /* setter */ -> {
val argument = (arguments.expressions[if (isExtension) 1 else 0]).toJK()
JKJavaAssignmentExpressionImpl(
propertyAccess,
argument,
JKJavaOperatorImpl.tokenToOperator[JavaTokenType.EQ]!!
)
}
else -> TODO()
}
}
else -> TODO()
}
}
symbol is JKMethodSymbol ->
JKJavaMethodCallExpressionImpl(symbol, arguments.toJK(), typeArguments)
.qualified(qualifier)
symbol is JKFieldSymbol ->
JKFieldAccessExpressionImpl(symbol).qualified(qualifier)
else -> TODO(text)
}
}
fun PsiReferenceExpression.toJK(): JKExpression {
val target = resolve()
if (target is KtLightClassForFacade) return JKStubExpressionImpl()
if (target is KtLightField
&& target.name == "INSTANCE"
&& target.containingClass.kotlinOrigin is KtObjectDeclaration
) {
return qualifierExpression?.toJK() ?: JKStubExpressionImpl()
}
val symbol = symbolProvider.provideSymbol(this)
return when (symbol) {
is JKClassSymbol -> JKClassAccessExpressionImpl(symbol)
is JKFieldSymbol -> JKFieldAccessExpressionImpl(symbol)
else -> TODO()
}.qualified(qualifierExpression?.toJK())
}
fun PsiArrayInitializerExpression.toJK(): JKExpression {
return JKJavaNewArrayImpl(
initializers.map { it.toJK() },
JKTypeElementImpl(type?.toJK(symbolProvider).safeAs<JKJavaArrayType>()?.type ?: JKContextType)
)
}
fun PsiNewExpression.toJK(): JKExpression {
require(this is PsiNewExpressionImpl)
val newExpression =
if (findChildByRole(ChildRole.LBRACKET) != null) {
arrayInitializer?.toJK() ?: run {
val dimensions = mutableListOf<PsiExpression?>()
var child = firstChild
while (child != null) {
if (child.node.elementType == JavaTokenType.LBRACKET) {
child = child.nextSibling
dimensions += if (child.node.elementType == JavaTokenType.RBRACKET) {
null
} else {
child as PsiExpression? //TODO
}
}
child = child.nextSibling
}
JKJavaNewEmptyArrayImpl(
dimensions.map { it?.toJK() ?: JKStubExpressionImpl() },
JKTypeElementImpl(generateSequence(type?.toJK(symbolProvider)) { it.safeAs<JKJavaArrayType>()?.type }.last())
).also {
it.psi = this
}
}
} else {
val classSymbol =
classOrAnonymousClassReference?.resolve()?.let {
symbolProvider.provideDirectSymbol(it) as JKClassSymbol
} ?: JKUnresolvedClassSymbol(classOrAnonymousClassReference?.referenceName!!)
val typeArgumentList =
this.typeArgumentList.toJK()
.takeIf { it.typeArguments.isNotEmpty() }
?: classOrAnonymousClassReference
?.typeParameters
?.let { typeParameters ->
JKTypeArgumentListImpl(typeParameters.map { JKTypeElementImpl(it.toJK(symbolProvider)) })
} ?: JKTypeArgumentListImpl()
JKJavaNewExpressionImpl(
classSymbol,
argumentList.toJK(),
typeArgumentList,
with(declarationMapper) { anonymousClass?.createClassBody() } ?: JKEmptyClassBodyImpl()
)
}
return qualifier?.let { JKQualifiedExpressionImpl(it.toJK(), JKJavaQualifierImpl.DOT, newExpression) } ?: newExpression
}
fun PsiReferenceParameterList.toJK(): JKTypeArgumentList =
JKTypeArgumentListImpl(this.typeArguments.map { JKTypeElementImpl(it.toJK(symbolProvider)) })
fun PsiArrayAccessExpression.toJK(): JKExpression {
return JKArrayAccessExpressionImpl(arrayExpression.toJK(), indexExpression?.toJK() ?: TODO())
}
fun PsiTypeCastExpression.toJK(): JKExpression {
return JKTypeCastExpressionImpl(operand?.toJK() ?: TODO(), castType?.type?.toJK(symbolProvider)?.asTypeElement() ?: TODO())
}
fun PsiParenthesizedExpression.toJK(): JKExpression {
return JKParenthesizedExpressionImpl(expression?.toJK() ?: TODO())
}
fun PsiExpressionList?.toJK(): JKExpressionList {
return JKExpressionListImpl(this?.expressions?.map { it.toJK() } ?: emptyList())
}
}
private inner class DeclarationMapper(val expressionTreeMapper: ExpressionTreeMapper) {
fun PsiTypeParameterList.toJK(): JKTypeParameterList =
JKTypeParameterListImpl(typeParameters.map { it.toJK() })
fun PsiTypeParameter.toJK(): JKTypeParameter =
JKTypeParameterImpl(JKNameIdentifierImpl(name!!),
extendsListTypes.map { JKTypeElementImpl(it.toJK(symbolProvider, Nullability.Default)) })
fun PsiClass.toJK(): JKClass {
val classKind: JKClass.ClassKind = when {
isAnnotationType -> JKClass.ClassKind.ANNOTATION
isEnum -> JKClass.ClassKind.ENUM
isInterface -> JKClass.ClassKind.INTERFACE
else -> JKClass.ClassKind.CLASS
}
fun PsiReferenceList.mapTypes() =
this.referencedTypes.map { with(expressionTreeMapper) { JKTypeElementImpl(it.toJK(symbolProvider, Nullability.Default)) } }
val implTypes = this.implementsList?.mapTypes().orEmpty()
val extensionType = this.extendsList?.mapTypes().orEmpty()
return JKClassImpl(
JKNameIdentifierImpl(name!!),
JKInheritanceInfoImpl(extensionType, implTypes),
classKind,
typeParameterList?.toJK() ?: JKTypeParameterListImpl(),
createClassBody(),
annotationList(),
modifiers(),
visibility(),
modality()
).also { jkClassImpl ->
jkClassImpl.psi = this
symbolProvider.provideUniverseSymbol(this, jkClassImpl)
}
}
fun PsiClass.createClassBody() =
JKClassBodyImpl(
children.mapNotNull {
when (it) {
is PsiEnumConstant -> it.toJK()
is PsiClass -> it.toJK()
is PsiAnnotationMethod -> it.toJK()
is PsiMethod -> it.toJK()
is PsiField -> it.toJK()
is PsiClassInitializer -> it.toJK()
else -> null
}
}
)
fun PsiClassInitializer.toJK() =
JKKtInitDeclarationImpl(body.toJK())
fun PsiEnumConstant.toJK(): JKEnumConstant =
JKEnumConstantImpl(
JKNameIdentifierImpl(name),
with(expressionTreeMapper) { argumentList.toJK() },
initializingClass?.createClassBody() ?: JKEmptyClassBodyImpl(),
JKTypeElementImpl(JKClassTypeImpl(symbolProvider.provideDirectSymbol(containingClass!!) as JKClassSymbol, emptyList()))
).also {
symbolProvider.provideUniverseSymbol(this, it)
it.psi = this
}
fun PsiMember.modality() =
when {
modifierList == null -> Modality.OPEN
hasModifierProperty(PsiModifier.FINAL) -> Modality.FINAL
hasModifierProperty(PsiModifier.ABSTRACT) -> Modality.ABSTRACT
else -> Modality.OPEN
}
fun PsiMember.visibility() =
when {
modifierList == null -> Visibility.PACKAGE_PRIVATE
hasModifierProperty(PsiModifier.PACKAGE_LOCAL) -> Visibility.PACKAGE_PRIVATE
hasModifierProperty(PsiModifier.PRIVATE) -> Visibility.PRIVATE
hasModifierProperty(PsiModifier.PROTECTED) -> handleProtectedVisibility()
hasModifierProperty(PsiModifier.PUBLIC) -> Visibility.PUBLIC
else -> Visibility.PACKAGE_PRIVATE
}
private fun PsiMember.handleProtectedVisibility(): Visibility {
val originalClass = containingClass ?: return Visibility.PROTECTED
// Search for usages only in Java because java-protected member cannot be used in Kotlin from same package
val usages = referenceSearcher.findUsagesForExternalCodeProcessing(this, true, false)
return if (usages.any { !allowProtected(it.element, this, originalClass) })
Visibility.PUBLIC
else Visibility.PROTECTED
}
private fun allowProtected(element: PsiElement, member: PsiMember, originalClass: PsiClass): Boolean {
if (element.parent is PsiNewExpression && member is PsiMethod && member.isConstructor) {
// calls to for protected constructors are allowed only within same class or as super calls
return element.parentsWithSelf.contains(originalClass)
}
return element.parentsWithSelf.filterIsInstance<PsiClass>().any { accessContainingClass ->
if (!InheritanceUtil.isInheritorOrSelf(accessContainingClass, originalClass, true)) return@any false
if (element !is PsiReferenceExpression) return@any true
val qualifierExpression = element.qualifierExpression ?: return@any true
// super.foo is allowed if 'foo' is protected
if (qualifierExpression is PsiSuperExpression) return@any true
val receiverType = qualifierExpression.type ?: return@any true
val resolvedClass = PsiUtil.resolveGenericsClassInType(receiverType).element ?: return@any true
// receiver type should be subtype of containing class
InheritanceUtil.isInheritorOrSelf(resolvedClass, accessContainingClass, true)
}
}
fun PsiMember.modifiers() =
if (modifierList == null) emptyList()
else
PsiModifier.MODIFIERS
.filter { this.modifierList!!.hasExplicitModifier(it) }
.mapNotNull {
when (it) {
PsiModifier.NATIVE -> ExtraModifier.NATIVE
PsiModifier.STATIC -> ExtraModifier.STATIC
PsiModifier.STRICTFP -> ExtraModifier.STRICTFP
PsiModifier.SYNCHRONIZED -> ExtraModifier.SYNCHRONIZED
PsiModifier.TRANSIENT -> ExtraModifier.TRANSIENT
PsiModifier.VOLATILE -> ExtraModifier.VOLATILE
PsiModifier.PROTECTED -> null
PsiModifier.PUBLIC -> null
PsiModifier.PRIVATE -> null
PsiModifier.FINAL -> null
PsiModifier.ABSTRACT -> null
else -> TODO("Not yet supported")
}
}
fun PsiField.toJK(): JKJavaField {
return JKJavaFieldImpl(
JKTypeElementImpl(type.toJK(symbolProvider)),
JKNameIdentifierImpl(name),
with(expressionTreeMapper) { initializer.toJK() },
annotationList(),
modifiers(),
visibility(),
modality(),
Mutability.UNKNOWN
).also {
symbolProvider.provideUniverseSymbol(this, it)
it.psi = this
}
}
fun <T> T.annotationList(): JKAnnotationList where T : JvmAnnotatedElement, T : PsiDocCommentOwner {
val plainAnnotations = annotations.map { it.toJK() }
val deprecatedAnnotation = docComment?.deprecatedAnnotation() ?: return JKAnnotationListImpl(plainAnnotations)
return JKAnnotationListImpl(
plainAnnotations.mapNotNull { annotation ->
if (annotation.classSymbol.fqName == "java.lang.Deprecated") null else annotation
} + deprecatedAnnotation
)
}
fun PsiAnnotation.toJK(): JKAnnotation =
JKAnnotationImpl(
symbolProvider.provideSymbol(nameReferenceElement!!),
parameterList.attributes.map { parameter ->
if (parameter.nameIdentifier != null) {
JKAnnotationNameParameterImpl(
parameter.value?.toJK() ?: JKStubExpressionImpl(),
JKNameIdentifierImpl(parameter.name!!)
)
} else {
JKAnnotationParameterImpl(
parameter.value?.toJK() ?: JKStubExpressionImpl()
)
}
}
)
fun PsiDocComment.deprecatedAnnotation(): JKAnnotation? =
findTagByName("deprecated")?.let { tag ->
JKAnnotationImpl(
symbolProvider.provideByFqName("kotlin.Deprecated"),
listOf(
JKAnnotationParameterImpl(stringLiteral(tag.content(), symbolProvider))
)
)
}
private fun PsiAnnotationMemberValue.toJK(): JKAnnotationMemberValue =
when (this) {
is PsiExpression -> with(expressionTreeMapper) { toJK() }
is PsiAnnotation -> toJK()
is PsiArrayInitializerMemberValue ->
JKKtAnnotationArrayInitializerExpressionImpl(
initializers.map { it.toJK() }
)
else -> TODO(this::class.toString())
}
fun PsiAnnotationMethod.toJK(): JKJavaAnnotationMethod =
JKJavaAnnotationMethodImpl(
returnType?.toJK(symbolProvider)?.asTypeElement()
?: JKTypeElementImpl(JKJavaVoidType).takeIf { isConstructor }
?: TODO(),
JKNameIdentifierImpl(name),
defaultValue?.toJK() ?: JKStubExpressionImpl()
).also {
it.psi = this
symbolProvider.provideUniverseSymbol(this, it)
}
fun PsiMethod.toJK(): JKJavaMethod {
return JKJavaMethodImpl(
returnType?.toJK(symbolProvider)?.asTypeElement()
?: JKTypeElementImpl(JKJavaVoidType).takeIf { isConstructor }
?: TODO(),
JKNameIdentifierImpl(name),
parameterList.parameters.map { it.toJK() },
body?.toJK() ?: JKBodyStub,
typeParameterList?.toJK() ?: JKTypeParameterListImpl(),
annotationList(),
throwsList.referencedTypes.map { JKTypeElementImpl(it.toJK(symbolProvider)) },
modifiers(),
visibility(),
modality()
).also {
it.psi = this
symbolProvider.provideUniverseSymbol(this, it)
}
}
fun PsiParameter.toJK(): JKParameter {
val rawType = type.toJK(symbolProvider)
val type =
if (isVarArgs && rawType is JKJavaArrayType) JKTypeElementImpl(rawType.type)
else rawType.asTypeElement()
return JKParameterImpl(
type,
JKNameIdentifierImpl(name!!),
isVarArgs
).also {
symbolProvider.provideUniverseSymbol(this, it)
it.psi = this
}
}
fun PsiCodeBlock.toJK(): JKBlock {
return JKBlockImpl(statements.map { it.toJK() })
}
fun PsiLocalVariable.toJK(): JKLocalVariable =
JKLocalVariableImpl(
JKTypeElementImpl(type.toJK(symbolProvider)),
JKNameIdentifierImpl(this.name ?: TODO()),
with(expressionTreeMapper) { initializer.toJK() },
if (hasModifierProperty(PsiModifier.FINAL)) Mutability.IMMUTABLE else Mutability.UNKNOWN
).also { i ->
symbolProvider.provideUniverseSymbol(this, i)
i.psi = this
}
fun PsiStatement?.toJK(): JKStatement {
return when (this) {
null -> JKExpressionStatementImpl(JKStubExpressionImpl())
is PsiExpressionStatement -> JKExpressionStatementImpl(with(expressionTreeMapper) { expression.toJK() })
is PsiReturnStatement -> JKReturnStatementImpl(with(expressionTreeMapper) { returnValue.toJK() })
is PsiDeclarationStatement ->
JKDeclarationStatementImpl(declaredElements.map {
when (it) {
is PsiClass -> it.toJK()
is PsiLocalVariable -> it.toJK()
else -> TODO(it::class.java.toString())
}
})
is PsiAssertStatement ->
JKJavaAssertStatementImpl(
with(expressionTreeMapper) { assertCondition.toJK() },
with(expressionTreeMapper) { assertDescription?.toJK() } ?: JKStubExpressionImpl())
is PsiIfStatement ->
if (elseElement == null)
JKIfStatementImpl(with(expressionTreeMapper) { condition.toJK() }, thenBranch.toJK())
else
JKIfElseStatementImpl(with(expressionTreeMapper) { condition.toJK() }, thenBranch.toJK(), elseBranch.toJK())
is PsiForStatement -> JKJavaForLoopStatementImpl(
initialization.toJK(),
with(expressionTreeMapper) { condition.toJK() },
when (update) {
is PsiExpressionListStatement ->
(update as PsiExpressionListStatement).expressionList.expressions.map {
JKExpressionStatementImpl(with(expressionTreeMapper) { it.toJK() })
}
else -> listOf(update.toJK())
},
body.toJK()
)
is PsiForeachStatement ->
JKForInStatementImpl(
iterationParameter.toJK(),
with(expressionTreeMapper) { iteratedValue?.toJK() ?: JKStubExpressionImpl() },
body?.toJK() ?: blockStatement()
)
is PsiBlockStatement -> JKBlockStatementImpl(codeBlock.toJK())
is PsiWhileStatement -> JKWhileStatementImpl(with(expressionTreeMapper) { condition.toJK() }, body.toJK())
is PsiDoWhileStatement -> JKDoWhileStatementImpl(body.toJK(), with(expressionTreeMapper) { condition.toJK() })
is PsiSwitchStatement -> {
val cases = mutableListOf<JKJavaSwitchCase>()
for (statement in body?.statements.orEmpty()) {
when (statement) {
is PsiSwitchLabelStatement ->
cases += if (statement.isDefaultCase)
JKJavaDefaultSwitchCaseImpl(emptyList())
else
JKJavaLabelSwitchCaseImpl(
with(expressionTreeMapper) { statement.caseValue.toJK() },
emptyList()
)
else ->
//TODO Handle case then there is no last case
cases.lastOrNull()?.also { it.statements = it.statements + statement.toJK() }
}
}
JKJavaSwitchStatementImpl(with(expressionTreeMapper) { expression.toJK() }, cases)
}
is PsiBreakStatement -> {
if (labelIdentifier != null)
JKBreakWithLabelStatementImpl(JKNameIdentifierImpl(labelIdentifier!!.text))
else
JKBreakStatementImpl()
}
is PsiContinueStatement -> {
val label = labelIdentifier?.let {
JKLabelTextImpl(JKNameIdentifierImpl(it.text))
} ?: JKLabelEmptyImpl()
JKContinueStatementImpl(label)
}
is PsiLabeledStatement -> {
val (labels, statement) = collectLabels()
JKLabeledStatementImpl(statement.toJK(), labels.map { JKNameIdentifierImpl(it.text) })
}
is PsiEmptyStatement -> JKEmptyStatementImpl()
is PsiThrowStatement ->
JKJavaThrowStatementImpl(with(expressionTreeMapper) { exception.toJK() })
is PsiTryStatement ->
JKJavaTryStatementImpl(
resourceList?.toList()?.map { (it as PsiLocalVariable).toJK() }.orEmpty(),
tryBlock?.toJK() ?: JKBodyStub,
finallyBlock?.toJK() ?: JKBodyStub,
catchSections.map { it.toJK() }
)
is PsiSynchronizedStatement ->
JKJavaSynchronizedStatementImpl(
with(expressionTreeMapper) { lockExpression?.toJK() } ?: JKStubExpressionImpl(),
body?.toJK() ?: JKBodyStub
)
else -> TODO("for ${this::class}")
}.also {
if (this != null) (it as PsiOwner).psi = this
}
}
fun PsiCatchSection.toJK(): JKJavaTryCatchSection =
JKJavaTryCatchSectionImpl(parameter?.toJK()!!, catchBlock?.toJK() ?: JKBodyStub)
.also { it.psi = this }
}
//TODO better way than generateSequence.last??
fun PsiLabeledStatement.collectLabels(): Pair<List<PsiIdentifier>, PsiStatement> =
generateSequence(emptyList<PsiIdentifier>() to this as PsiStatement) { (labels, statement) ->
if (statement !is PsiLabeledStatementImpl) return@generateSequence null
(labels + statement.labelIdentifier) to statement.statement!!
}.last()
fun buildTree(psi: PsiElement): JKTreeElement? =
when (psi) {
is PsiJavaFile -> psi.toJK()
else -> error("Cannot convert non-java file")
}
}
@@ -1,893 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k
import org.jetbrains.kotlin.j2k.NewCodeBuilder.ParenthesisKind.*
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.conversions.parentOfType
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitorVoid
import org.jetbrains.kotlin.lexer.KtKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
class NewCodeBuilder {
val builder = StringBuilder()
val printer = Printer(builder)
private fun classKindString(kind: JKClass.ClassKind): String = when (kind) {
JKClass.ClassKind.ANNOTATION -> "annotation class"
JKClass.ClassKind.CLASS -> "class"
JKClass.ClassKind.ENUM -> "enum class"
JKClass.ClassKind.INTERFACE -> "interface"
JKClass.ClassKind.OBJECT -> "object"
JKClass.ClassKind.COMPANION -> "companion object"
}
inner class Visitor : JKVisitorVoid {
private fun renderExtraTypeParametersUpperBounds(typeParameterList: JKTypeParameterList) {
val extraTypeBounds = typeParameterList.typeParameters
.filter { it.upperBounds.size > 1 }
if (extraTypeBounds.isNotEmpty()) {
printer.printWithNoIndent(" where ")
val typeParametersWithBoudnds =
extraTypeBounds.flatMap { typeParameter ->
typeParameter.upperBounds.map { bound ->
typeParameter.name to bound
}
}
renderList(typeParametersWithBoudnds) { (name, bound) ->
name.accept(this)
printer.printWithNoIndent(" : ")
bound.accept(this)
}
}
}
override fun visitTreeElement(treeElement: JKTreeElement) {
printer.print("/* !!! Hit visitElement for element type: ${treeElement::class} !!! */")
}
override fun visitKtTryExpression(ktTryExpression: JKKtTryExpression) {
printer.printWithNoIndent("try ")
if (ktTryExpression.tryBlock != JKBodyStub) {
printer.block { ktTryExpression.tryBlock.accept(this) }
}
ktTryExpression.catchSections.forEach { it.accept(this) }
if (ktTryExpression.finallyBlock != JKBodyStub) {
printer.printWithNoIndent("finally ")
printer.block { ktTryExpression.finallyBlock.accept(this) }
}
}
override fun visitKtTryCatchSection(ktTryCatchSection: JKKtTryCatchSection) {
printer.printWithNoIndent("catch ")
printer.par {
ktTryCatchSection.parameter.accept(this)
}
if (ktTryCatchSection.block != JKBodyStub) {
printer.block { ktTryCatchSection.block.accept(this) }
}
}
override fun visitForInStatement(forInStatement: JKForInStatement) {
printer.printWithNoIndent("for (")
forInStatement.declaration.accept(this)
printer.printWithNoIndent(" in ")
forInStatement.iterationExpression.accept(this)
printer.printWithNoIndent(") ")
if (forInStatement.body.isEmpty()) {
printer.printWithNoIndent(";")
} else {
forInStatement.body.accept(this)
}
}
override fun visitKtThrowExpression(ktThrowExpression: JKKtThrowExpression) {
printer.printWithNoIndent("throw ")
ktThrowExpression.exception.accept(this)
}
override fun visitDoWhileStatement(doWhileStatement: JKDoWhileStatement) {
printer.printWithNoIndent("do ")
doWhileStatement.body.accept(this)
printer.printWithNoIndent(" while (")
doWhileStatement.condition.accept(this)
printer.printWithNoIndent(")")
}
override fun visitClassAccessExpression(classAccessExpression: JKClassAccessExpression) {
printer.printWithNoIndent(classAccessExpression.identifier.displayName().escaped())
}
override fun visitFile(file: JKFile) {
if (file.packageDeclaration.packageName.value.isNotEmpty()) {
file.packageDeclaration.accept(this)
}
file.importList.forEach { it.accept(this) }
file.declarationList.forEach { it.accept(this) }
}
private fun String.escapedAsQualifiedName(): String =
split('.')
.map { it.escaped() }
.joinToString(".") { it }
override fun visitPackageDeclaration(packageDeclaration: JKPackageDeclaration) {
printer.printWithNoIndent("package ")
val packageNameEscaped =
packageDeclaration.packageName.value.escapedAsQualifiedName()
printer.printlnWithNoIndent(packageNameEscaped)
}
override fun visitImportStatement(importStatement: JKImportStatement) {
printer.printWithNoIndent("import ")
val importNameEscaped =
importStatement.name.value.escapedAsQualifiedName()
printer.printlnWithNoIndent(importNameEscaped)
}
override fun visitBreakStatement(breakStatement: JKBreakStatement) {
printer.printWithNoIndent("break")
}
override fun visitBreakWithLabelStatement(breakWithLabelStatement: JKBreakWithLabelStatement) {
printer.printWithNoIndent("break@")
breakWithLabelStatement.label.accept(this)
}
private fun renderModifiersList(modifiersList: JKModifiersListOwner) {
renderList(modifiersList.modifiers(), " ") {
printer.printWithNoIndent(it.text)
}
}
private inline fun <T> renderList(list: List<T>, separator: String = ", ", renderElement: (T) -> Unit) =
renderList(list, { printer.printWithNoIndent(separator) }, renderElement)
private inline fun <T> renderList(list: List<T>, separator: () -> Unit, renderElement: (T) -> Unit) {
val (head, tail) = list.headTail()
head?.let(renderElement) ?: return
tail?.forEach {
separator()
renderElement(it)
}
}
override fun visitClass(klass: JKClass) {
klass.annotationList.accept(this)
if (klass.annotationList.annotations.isNotEmpty()) {
printer.println()
}
renderModifiersList(klass)
builder.append(" ")
printer.print(classKindString(klass.classKind))
builder.append(" ")
klass.name.accept(this)
klass.typeParameterList.accept(this)
printer.printWithNoIndent(" ")
val primaryConstructor = klass.primaryConstructor()
primaryConstructor?.accept(this)
if (klass.inheritance.present()) {
printer.printWithNoIndent(" : ")
klass.inheritance.accept(this)
}
//TODO should it be here?
renderExtraTypeParametersUpperBounds(klass.typeParameterList)
klass.classBody.accept(this)
}
override fun visitInheritanceInfo(inheritanceInfo: JKInheritanceInfo) {
val parentClass = inheritanceInfo.parentOfType<JKClass>()!!
val isInInterface = parentClass.classKind == JKClass.ClassKind.INTERFACE
val extendTypes = inheritanceInfo.extends.map { it.type.updateNullability(Nullability.NotNull) }
val implementTypes = inheritanceInfo.implements.map { it.type.updateNullability(Nullability.NotNull) }
if (isInInterface) {
renderList(extendTypes) { renderType(it) }
} else {
extendTypes.singleOrNull()?.also { superType ->
renderType(superType)
val primaryConstructor = parentClass.primaryConstructor()
val delegationCall =
primaryConstructor
?.delegationCall
?.let { it as? JKDelegationConstructorCall }
if (delegationCall != null) {
printer.par { delegationCall.arguments.accept(this) }
} else if (!superType.isInterface()) {
printer.printWithNoIndent("()")
}
}
}
if (implementTypes.isNotEmpty() && extendTypes.size == 1) {
printer.printWithNoIndent(", ")
}
renderList(implementTypes) { renderType(it) }
}
private fun renderEnumConstants(enumConstants: List<JKEnumConstant>) {
renderList(enumConstants) {
it.accept(this)
}
}
private fun renderNonEnumClassDeclarations(declarations: List<JKDeclaration>) {
renderList(declarations, { printer.println() }) {
it.accept(this)
}
}
override fun visitKtProperty(ktProperty: JKKtProperty) {
ktProperty.annotationList.accept(this)
if (ktProperty.annotationList.annotations.isNotEmpty()) {
printer.println()
}
renderModifiersList(ktProperty)
printer.printWithNoIndent(" ")
ktProperty.name.accept(this)
if (ktProperty.type.present()) {
printer.printWithNoIndent(":")
ktProperty.type.accept(this)
}
if (ktProperty.initializer !is JKStubExpression) {
printer.printWithNoIndent(" = ")
ktProperty.initializer.accept(this)
}
if (ktProperty.getter !is JKKtEmptyGetterOrSetter) {
printer.printlnWithNoIndent()
ktProperty.getter.accept(this)
}
if (ktProperty.setter !is JKKtEmptyGetterOrSetter) {
printer.printlnWithNoIndent()
ktProperty.setter.accept(this)
}
}
override fun visitEnumConstant(enumConstant: JKEnumConstant) {
enumConstant.name.accept(this)
if (enumConstant.arguments.expressions.isNotEmpty()) {
printer.par {
enumConstant.arguments.accept(this)
}
}
if (enumConstant.body !is JKEmptyClassBody) {
enumConstant.body.accept(this)
}
}
override fun visitKtInitDeclaration(ktInitDeclaration: JKKtInitDeclaration) {
if (ktInitDeclaration.block.statements.isNotEmpty()) {
printer.print("init ")
printer.block(multiline = true) {
ktInitDeclaration.block.accept(this)
}
}
}
override fun visitKtIsExpression(ktIsExpression: JKKtIsExpression) {
ktIsExpression.expression.accept(this)
printer.printWithNoIndent(" is ")
ktIsExpression.type.accept(this)
}
override fun visitParameter(parameter: JKParameter) {
renderModifiersList(parameter)
printer.printWithNoIndent(" ")
if (parameter.isVarArgs) {
printer.printWithNoIndent("vararg ")
}
if (parameter.parent is JKKtPrimaryConstructor
&& (parameter.parent?.parent?.parent as? JKClass)?.classKind == JKClass.ClassKind.ANNOTATION
) {//TODO get rid of
printer.print(" val ")
}
parameter.name.accept(this)
if (parameter.type.present() && parameter.type.type !is JKContextType) {
printer.printWithNoIndent(":")
parameter.type.accept(this)
}
if (parameter.initializer !is JKStubExpression) {
printer.printWithNoIndent(" = ")
parameter.initializer.accept(this)
}
}
override fun visitKtAnnotationArrayInitializerExpression(ktAnnotationArrayInitializerExpression: JKKtAnnotationArrayInitializerExpression) {
printer.print("[")
renderList(ktAnnotationArrayInitializerExpression.initializers) {
it.accept(this)
}
printer.print("]")
}
override fun visitForLoopVariable(forLoopVariable: JKForLoopVariable) {
forLoopVariable.name.accept(this)
if (forLoopVariable.type.present() && forLoopVariable.type.type !is JKContextType) {
printer.printWithNoIndent(": ")
forLoopVariable.type.accept(this)
}
}
override fun visitKtFunction(ktFunction: JKKtFunction) {
printer.printIndent()
if (ktFunction.annotationList.annotations.isNotEmpty()) {
ktFunction.annotationList.accept(this)
printer.printlnWithNoIndent(" ")
}
renderModifiersList(ktFunction)
printer.printWithNoIndent(" fun ")
ktFunction.typeParameterList.accept(this)
ktFunction.name.accept(this)
printer.printWithNoIndent("(")
renderList(ktFunction.parameters) {
it.accept(this)
}
printer.printWithNoIndent(")", ": ")
ktFunction.returnType.accept(this)
renderExtraTypeParametersUpperBounds(ktFunction.typeParameterList)
if (ktFunction.block !== JKBodyStub) {
printer.block(multiline = ktFunction.block.statements.isNotEmpty()) {
ktFunction.block.accept(this)
}
}
}
override fun visitIfElseExpression(ifElseExpression: JKIfElseExpression) {
printer.printWithNoIndent("if (")
ifElseExpression.condition.accept(this)
printer.printWithNoIndent(")")
ifElseExpression.thenBranch.accept(this)
printer.printWithNoIndent(" else ")
ifElseExpression.elseBranch.accept(this)
}
override fun visitIfStatement(ifStatement: JKIfStatement) {
printer.printWithNoIndent("if (")
ifStatement.condition.accept(this)
printer.printWithNoIndent(")")
if (ifStatement.thenBranch.isEmpty()) {
printer.printWithNoIndent(";")
} else {
renderStatementOrBlock(ifStatement.thenBranch)
}
}
override fun visitIfElseStatement(ifElseStatement: JKIfElseStatement) {
visitIfStatement(ifElseStatement)
printer.printWithNoIndent(" else ")
renderStatementOrBlock(ifElseStatement.elseBranch)
}
private fun renderStatementOrBlock(statement: JKStatement, multiline: Boolean = false) {
if (statement is JKBlockStatement) {
printer.block(multiline) {
statement.block.accept(this)
}
} else {
statement.accept(this)
}
}
override fun visitKtGetterOrSetter(ktGetterOrSetter: JKKtGetterOrSetter) {
printer.indented {
renderModifiersList(ktGetterOrSetter)
printer.printWithNoIndent(" ")
when (ktGetterOrSetter.kind) {
JKKtGetterOrSetter.Kind.GETTER -> printer.printWithNoIndent("get")
JKKtGetterOrSetter.Kind.SETTER -> printer.printWithNoIndent("set")
}
if (!ktGetterOrSetter.body.isEmpty()) {
when (ktGetterOrSetter.kind) {
JKKtGetterOrSetter.Kind.GETTER -> printer.printWithNoIndent("() ")
JKKtGetterOrSetter.Kind.SETTER -> printer.printWithNoIndent("(value) ")
}
ktGetterOrSetter.body.accept(this)
}
}
printer.printlnWithNoIndent()
}
override fun visitKtEmptyGetterOrSetter(ktEmptyGetterOrSetter: JKKtEmptyGetterOrSetter) {
}
override fun visitBinaryExpression(binaryExpression: JKBinaryExpression) {
binaryExpression.left.accept(this)
printer.printWithNoIndent(" ")
printer.printWithNoIndent(binaryExpression.operator.token.text)
printer.printWithNoIndent(" ")
binaryExpression.right.accept(this)
}
override fun visitTypeParameterList(typeParameterList: JKTypeParameterList) {
if (typeParameterList.typeParameters.isNotEmpty()) {
printer.par(ANGLE) {
renderList(typeParameterList.typeParameters) {
it.accept(this)
}
}
}
}
override fun visitTypeParameter(typeParameter: JKTypeParameter) {
typeParameter.name.accept(this)
if (typeParameter.upperBounds.size == 1) {
printer.printWithNoIndent(" : ")
typeParameter.upperBounds.single().accept(this)
}
}
override fun visitLiteralExpression(literalExpression: JKLiteralExpression) {
printer.printWithNoIndent(literalExpression.literal)
}
override fun visitPrefixExpression(prefixExpression: JKPrefixExpression) {
printer.printWithNoIndent(prefixExpression.operator.token.text)
prefixExpression.expression.accept(this)
}
override fun visitThisExpression(thisExpression: JKThisExpression) {
printer.printWithNoIndent("this")
thisExpression.qualifierLabel.accept(this)
}
override fun visitSuperExpression(superExpression: JKSuperExpression) {
printer.printWithNoIndent("super")
superExpression.qualifierLabel.accept(this)
}
override fun visitContinueStatement(continueStatement: JKContinueStatement) {
printer.printWithNoIndent("continue")
continueStatement.label.accept(this)
printer.printlnWithNoIndent(" ")
}
override fun visitLabelEmpty(labelEmpty: JKLabelEmpty) {
}
override fun visitLabelText(labelText: JKLabelText) {
printer.printWithNoIndent("@")
labelText.label.accept(this)
printer.printWithNoIndent(" ")
}
override fun visitLabeledStatement(labeledStatement: JKLabeledStatement) {
for (label in labeledStatement.labels) {
label.accept(this)
printer.printWithNoIndent("@")
}
labeledStatement.statement.accept(this)
}
override fun visitNameIdentifier(nameIdentifier: JKNameIdentifier) {
printer.printWithNoIndent(nameIdentifier.value.escaped())
}
override fun visitPostfixExpression(postfixExpression: JKPostfixExpression) {
postfixExpression.expression.accept(this)
printer.printWithNoIndent(postfixExpression.operator.token.text)
}
override fun visitQualifiedExpression(qualifiedExpression: JKQualifiedExpression) {
qualifiedExpression.receiver.accept(this)
printer.printWithNoIndent(
when (qualifiedExpression.operator) {
is JKJavaQualifierImpl.DOT /*<-remove this TODO!*/, is JKKtQualifierImpl.DOT -> "."
is JKKtQualifierImpl.SAFE -> "?."
else -> TODO()
}
)
qualifiedExpression.selector.accept(this)
}
override fun visitExpressionList(expressionList: JKExpressionList) {
renderList(expressionList.expressions) { it.accept(this) }
}
override fun visitMethodCallExpression(methodCallExpression: JKMethodCallExpression) {
printer.printWithNoIndent(FqName(methodCallExpression.identifier.fqName).shortName().asString().escaped())
methodCallExpression.typeArgumentList.accept(this)
printer.par {
methodCallExpression.arguments.accept(this)
}
}
override fun visitTypeArgumentList(typeArgumentList: JKTypeArgumentList) {
if (typeArgumentList.typeArguments.isNotEmpty()) {
printer.par(ANGLE) {
renderList(typeArgumentList.typeArguments) {
it.accept(this)
}
}
}
}
override fun visitParenthesizedExpression(parenthesizedExpression: JKParenthesizedExpression) {
printer.par {
parenthesizedExpression.expression.accept(this)
}
}
override fun visitDeclarationStatement(declarationStatement: JKDeclarationStatement) {
renderList(declarationStatement.declaredStatements, { printer.println() }) {
it.accept(this)
}
}
override fun visitTypeCastExpression(typeCastExpression: JKTypeCastExpression) {
typeCastExpression.expression.accept(this)
printer.printWithNoIndent(" as ")
typeCastExpression.type.accept(this)
}
override fun visitWhileStatement(whileStatement: JKWhileStatement) {
printer.print("while(")
whileStatement.condition.accept(this)
printer.printWithNoIndent(")")
if (whileStatement.body.isEmpty()) {
printer.printWithNoIndent(";")
} else {
renderStatementOrBlock(whileStatement.body, multiline = true)
}
}
override fun visitLocalVariable(localVariable: JKLocalVariable) {
renderModifiersList(localVariable)
printer.printWithNoIndent(" ")
localVariable.name.accept(this)
if (localVariable.type.present() && localVariable.type.type != JKContextType) {
printer.printWithNoIndent(": ")
localVariable.type.accept(this)
}
if (localVariable.initializer !is JKStubExpression) {
printer.printWithNoIndent(" = ")
localVariable.initializer.accept(this)
}
}
override fun visitEmptyStatement(emptyStatement: JKEmptyStatement) {
}
override fun visitStubExpression(stubExpression: JKStubExpression) {
}
override fun visitKtConvertedFromForLoopSyntheticWhileStatement(
ktConvertedFromForLoopSyntheticWhileStatement: JKKtConvertedFromForLoopSyntheticWhileStatement
) {
ktConvertedFromForLoopSyntheticWhileStatement.variableDeclaration.accept(this)
printer.printlnWithNoIndent()
ktConvertedFromForLoopSyntheticWhileStatement.whileStatement.accept(this)
}
private fun renderType(type: JKType) {
if (type is JKNoTypeImpl) return
when (type) {
is JKClassType -> printer.printWithNoIndent(type.classReference.displayName().escapedAsQualifiedName())
is JKContextType -> return
is JKStarProjectionType ->
printer.printWithNoIndent("*")
is JKTypeParameterType ->
printer.printWithNoIndent(type.name)
is JKVarianceTypeParameterType -> {
when (type.variance) {
JKVarianceTypeParameterType.Variance.IN -> printer.printWithNoIndent("in ")
JKVarianceTypeParameterType.Variance.OUT -> printer.printWithNoIndent("out ")
}
renderType(type.boundType)
}
else -> printer.printWithNoIndent("Unit /* TODO: ${type::class} */")
}
if (type is JKParametrizedType && type.parameters.isNotEmpty()) {
printer.par(ANGLE) {
renderList(type.parameters, renderElement = ::renderType)
}
}
when (type.nullability) {
Nullability.Nullable -> printer.printWithNoIndent("?")
Nullability.Default -> printer.printWithNoIndent("?")// /* TODO: Default */")
else -> {
}
}
}
override fun visitJavaNewExpression(javaNewExpression: JKJavaNewExpression) {
if (javaNewExpression.isAnonymousClass()) {
printer.printWithNoIndent("object : ")
}
printer.printWithNoIndent(javaNewExpression.classSymbol.displayName().escapedAsQualifiedName())
javaNewExpression.typeArgumentList.accept(this)
if (!javaNewExpression.classSymbol.isInterface()) {
printer.par(ROUND) {
javaNewExpression.arguments.accept(this)
}
}
if (javaNewExpression.isAnonymousClass()) {
javaNewExpression.classBody.accept(this)
}
}
override fun visitClassBody(classBody: JKClassBody) {
val declarationsToPrint = classBody.declarations.filterNot { it is JKKtPrimaryConstructor }
printer.block(multiline = true) {
val enumConstants = declarationsToPrint.filterIsInstance<JKEnumConstant>()
val otherDeclarations = declarationsToPrint.filterNot { it is JKEnumConstant }
renderEnumConstants(enumConstants)
if ((classBody.parent as? JKClass)?.classKind == JKClass.ClassKind.ENUM
&& otherDeclarations.isNotEmpty()
) {
printer.printlnWithNoIndent(";")
}
if (enumConstants.isNotEmpty() && otherDeclarations.isNotEmpty()) {
printer.println()
}
renderNonEnumClassDeclarations(otherDeclarations)
}
}
override fun visitEmptyClassBody(emptyClassBody: JKEmptyClassBody) {}
override fun visitTypeElement(typeElement: JKTypeElement) {
renderType(typeElement.type)
}
override fun visitBlock(block: JKBlock) {
renderList(block.statements, { printer.println() }) {
it.accept(this)
}
}
override fun visitBlockStatementWithoutBrackets(blockStatementWithoutBrackets: JKBlockStatementWithoutBrackets) {
blockStatementWithoutBrackets.block.accept(this)
}
override fun visitExpressionStatement(expressionStatement: JKExpressionStatement) {
printer.printIndent()
expressionStatement.expression.accept(this)
}
override fun visitReturnStatement(returnStatement: JKReturnStatement) {
printer.print("return ")
returnStatement.expression.accept(this)
}
override fun visitFieldAccessExpression(fieldAccessExpression: JKFieldAccessExpression) {
printer.printWithNoIndent(fieldAccessExpression.identifier.name.escaped())
}
override fun visitArrayAccessExpression(arrayAccessExpression: JKArrayAccessExpression) {
arrayAccessExpression.expression.accept(this)
printer.par(SQUARE) { arrayAccessExpression.indexExpression.accept(this) }
}
override fun visitDelegationConstructorCall(delegationConstructorCall: JKDelegationConstructorCall) {
delegationConstructorCall.expression.accept(this)
printer.par {
delegationConstructorCall.arguments.accept(this)
}
}
private fun renderParameterList(parameters: List<JKParameter>) {
printer.par(ROUND) {
renderList(parameters) {
it.accept(this)
}
}
}
override fun visitKtConstructor(ktConstructor: JKKtConstructor) {
ktConstructor.annotationList.accept(this)
if (ktConstructor.annotationList.annotations.isNotEmpty()) {
printer.println()
}
renderModifiersList(ktConstructor)
printer.print(" constructor")
renderParameterList(ktConstructor.parameters)
if (ktConstructor.delegationCall !is JKStubExpression) {
builder.append(" : ")
ktConstructor.delegationCall.accept(this)
}
if (ktConstructor.block !== JKBodyStub) {
printer.block(multiline = true) {
ktConstructor.block.accept(this)
}
}
}
override fun visitKtPrimaryConstructor(ktPrimaryConstructor: JKKtPrimaryConstructor) {
ktPrimaryConstructor.annotationList.accept(this)
printer.printWithNoIndent(" ")
renderModifiersList(ktPrimaryConstructor)
printer.printWithNoIndent(" constructor ")
if (ktPrimaryConstructor.parameters.isNotEmpty()) {
renderParameterList(ktPrimaryConstructor.parameters)
} else {
printer.print("()")
}
}
private inline fun Printer.indented(block: () -> Unit) {
this.pushIndent()
block()
this.popIndent()
}
private inline fun Printer.block(multiline: Boolean = false, crossinline body: () -> Unit) {
par(CURVED) {
if (multiline) printer.printWithNoIndent("\n")
indented(body)
}
}
private inline fun Printer.par(kind: ParenthesisKind = ParenthesisKind.ROUND, body: () -> Unit) {
this.printWithNoIndent(kind.open)
body()
this.printWithNoIndent(kind.close)
}
override fun visitLambdaExpression(lambdaExpression: JKLambdaExpression) {
printer.par(CURVED) {
if (lambdaExpression.statement.statements.size > 1)
printer.println()
lambdaExpression.parameters.firstOrNull()?.accept(this)
lambdaExpression.parameters.asSequence().drop(1).forEach { printer.printWithNoIndent(", "); it.accept(this) }
if (lambdaExpression.parameters.isNotEmpty()) {
printer.printWithNoIndent(" -> ")
}
val statement = lambdaExpression.statement
if (statement is JKBlockStatement) {
statement.block.accept(this)
} else {
statement.accept(this)
}
if (lambdaExpression.statement.statements.size > 1)
printer.println()
}
}
override fun visitBlockStatement(blockStatement: JKBlockStatement) {
printer.par(CURVED) {
blockStatement.block.accept(this)
}
}
override fun visitKtAssignmentStatement(ktAssignmentStatement: JKKtAssignmentStatement) {
ktAssignmentStatement.field.accept(this)
printer.printWithNoIndent(" ")
printer.printWithNoIndent(ktAssignmentStatement.operator.token.text)
printer.printWithNoIndent(" ")
ktAssignmentStatement.expression.accept(this)
}
override fun visitKtWhenStatement(ktWhenStatement: JKKtWhenStatement) {
printer.printWithNoIndent("when(")
ktWhenStatement.expression.accept(this)
printer.printWithNoIndent(")")
printer.block(multiline = true) {
renderList(ktWhenStatement.cases, { printer.printlnWithNoIndent() }) {
it.accept(this)
}
}
}
override fun visitAnnotationList(annotationList: JKAnnotationList) {
renderList(annotationList.annotations, " ") {
it.accept(this)
}
}
override fun visitAnnotation(annotation: JKAnnotation) {
printer.printWithNoIndent("@")
printer.printWithNoIndent(annotation.classSymbol.displayName().escapedAsQualifiedName())
if (annotation.arguments.isNotEmpty()) {
printer.par {
renderList(annotation.arguments) { it.accept(this) }
}
}
}
override fun visitAnnotationNameParameter(annotationNameParameter: JKAnnotationNameParameter) {
annotationNameParameter.name.accept(this)
printer.print(" = ")
annotationNameParameter.value.accept(this)
}
override fun visitAnnotationParameter(annotationParameter: JKAnnotationParameter) {
annotationParameter.value.accept(this)
}
override fun visitClassLiteralExpression(classLiteralExpression: JKClassLiteralExpression) {
if (classLiteralExpression.literalType == JKClassLiteralExpression.LiteralType.JAVA_VOID_TYPE) {
printer.printWithNoIndent("Void.TYPE")
} else {
renderType(classLiteralExpression.classType.type)
printer.printWithNoIndent("::")
when (classLiteralExpression.literalType) {
JKClassLiteralExpression.LiteralType.KOTLIN_CLASS -> printer.printWithNoIndent("class")
JKClassLiteralExpression.LiteralType.JAVA_CLASS -> printer.printWithNoIndent("class.java")
JKClassLiteralExpression.LiteralType.JAVA_PRIMITIVE_CLASS -> printer.printWithNoIndent("class.javaPrimitiveType")
}
}
}
override fun visitKtWhenCase(ktWhenCase: JKKtWhenCase) {
renderList(ktWhenCase.labels, ", ") {
it.accept(this)
}
printer.printWithNoIndent(" -> ")
ktWhenCase.statement.accept(this)
}
override fun visitKtElseWhenLabel(ktElseWhenLabel: JKKtElseWhenLabel) {
printer.printWithNoIndent("else")
}
override fun visitKtValueWhenLabel(ktValueWhenLabel: JKKtValueWhenLabel) {
ktValueWhenLabel.expression.accept(this)
}
}
private enum class ParenthesisKind(val open: String, val close: String) {
ROUND("(", ")"), SQUARE("[", "]"), CURVED("{", "}"), CURVED_MULTILINE("{\n", "}\n"), INLINE_COMMENT("/*", "*/"), ANGLE("<", ">")
}
fun printCodeOut(root: JKTreeElement): String {
Visitor().also { root.accept(it) }
return builder.toString()
}
}
private inline fun <T> List<T>.headTail(): Pair<T?, List<T>?> {
val head = this.firstOrNull()
val tail = if (size <= 1) null else subList(1, size)
return head to tail
}
private inline fun JKDelegationConstructorCall.isCallOfConstructorOf(type: JKType): Boolean {
return when (type) {
is JKClassType -> {
val symbol = type.classReference as? JKClassSymbol ?: return false
this.identifier.name == symbol.name && this.identifier.declaredIn == symbol
}
else -> false
}
}
private val KEYWORDS = KtTokens.KEYWORDS.types.map { (it as KtKeywordToken).value }.toSet()
private fun String.escaped() =
if (this in KEYWORDS || '$' in this) "`$this`"
else this
@@ -1,62 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k
import com.intellij.openapi.progress.EmptyProgressIndicator
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiJavaFile
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
import org.jetbrains.kotlin.j2k.tree.prettyDebugPrintTree
class NewJavaToKotlinConverter(
val project: Project,
val settings: ConverterSettings,
val converterServices: NewJavaToKotlinServices
) {
private fun List<JKTreeElement>.prettyPrintTrees() = buildString {
for (tree in this@prettyPrintTrees) {
appendln()
appendln(tree.prettyDebugPrintTree())
appendln()
}
}
fun filesToKotlin(files: List<PsiJavaFile>, progressIndicator: ProgressIndicator = EmptyProgressIndicator()): List<String> {
val symbolProvider = JKSymbolProvider()
symbolProvider.preBuildTree(files)
val treeBuilder = JavaToJKTreeBuilder(symbolProvider, converterServices)
val fileTrees = files.mapNotNull(treeBuilder::buildTree)
// println(fileTrees.prettyPrintTrees())
val context = ConversionContext(
symbolProvider,
this,
{ it: PsiElement -> it.containingFile in files }
)
ConversionsRunner.doApply(fileTrees, context)
// val resultTree = fileTrees.prettyPrintTrees()
// println(resultTree)
return fileTrees.map { NewCodeBuilder().run { printCodeOut(it) } }
}
}
@@ -1,10 +0,0 @@
/*
* Copyright 2010-2018 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
interface NewJavaToKotlinServices {
val oldServices: JavaToKotlinConverterServices
}
@@ -1,22 +0,0 @@
/*
* Copyright 2010-2018 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 org.jetbrains.kotlin.j2k.tree.JKElement
import org.jetbrains.kotlin.j2k.tree.impl.JKElementBase
fun <T : JKElement> T.copyTree(): T =
when (this) {
is JKElementBase ->
this.copy() as T
else -> TODO("Not supported+$this.toString()")
}
fun <T : JKElement> T.copyTreeAndDetach(): T =
this.copyTree().also {
if (it.parent != null) it.detach(it.parent!!)
}
@@ -1,12 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.tree.JKElement
inline fun <reified T : JKElement> JKElement.parentOfType(): T? {
return generateSequence(parent) { it.parent }.filterIsInstance<T>().firstOrNull()
}
@@ -1,57 +0,0 @@
/*
* 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.toExpression
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class AnnotationClassConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKClass) return recurse(element)
if (element.classKind != JKClass.ClassKind.ANNOTATION) return recurse(element)
val javaAnnotationMethods =
element.classBody.declarations
.filterIsInstance<JKJavaAnnotationMethod>()
val constructor = JKKtPrimaryConstructorImpl(
JKNameIdentifierImpl(""),
javaAnnotationMethods.map { it.asKotlinAnnotationParameter() },
JKStubExpressionImpl(),
JKAnnotationListImpl(),
emptyList(),
Visibility.PUBLIC,
Modality.FINAL
)
element.modality = Modality.FINAL
element.classBody.declarations += constructor
element.classBody.declarations -= javaAnnotationMethods
return recurse(element)
}
private fun JKJavaAnnotationMethod.asKotlinAnnotationParameter(): JKParameterImpl {
val type = returnType.type
.updateNullabilityRecursively(Nullability.NotNull)
.replaceJavaClassWithKotlinClassType(context.symbolProvider)
val initializer = this::defaultValue.detached().toExpression(context.symbolProvider)
val isVarArgs = type is JKJavaArrayType && name.value == "value"
return JKParameterImpl(
JKTypeElementImpl(
if (!isVarArgs) type else (type as JKJavaArrayType).type
),
JKNameIdentifierImpl(name.value),
isVarArgs = isVarArgs,
initializer =
if (type.isArrayType()
&& initializer !is JKKtAnnotationArrayInitializerExpression
&& initializer !is JKStubExpression
) {
JKKtAnnotationArrayInitializerExpressionImpl(initializer)
} else initializer
)
}
}
@@ -1,56 +0,0 @@
/*
* 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.isVarargsArgument
import org.jetbrains.kotlin.j2k.primaryConstructor
import org.jetbrains.kotlin.j2k.toExpression
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.JKAnnotationNameParameterImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKAnnotationParameterImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKUniverseClassSymbol
class AnnotationConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKAnnotation) return recurse(element)
fixVarargsInvocation(element)
for (parameter in element.arguments) {
parameter.value = parameter.value.toExpression(context.symbolProvider)
}
return recurse(element)
}
private fun fixVarargsInvocation(annotation: JKAnnotation) {
val newParameters =
annotation.arguments.withIndex()
.flatMap { (index, annotationParameter) ->
when {
annotationParameter !is JKAnnotationNameParameter
&& annotation.isVarargsArgument(index)
&& annotationParameter.value is JKKtAnnotationArrayInitializerExpression ->
(annotationParameter.value as JKKtAnnotationArrayInitializerExpression)::initializers
.detached()
.map { JKAnnotationParameterImpl(it) }
annotationParameter is JKAnnotationNameParameterImpl ->
listOf(
JKAnnotationNameParameterImpl(
annotationParameter::value.detached(),
annotationParameter::name.detached()
)
)
else -> listOf(
JKAnnotationParameterImpl(
annotationParameter::value.detached()
)
)
}
}
annotation.arguments = newParameters
}
}
@@ -1,86 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.resolve.CollectionLiteralResolver
class ArrayInitializerConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
var newElement = element
if (element is JKJavaNewArray) {
val arrayType = element.type.type as? JKJavaPrimitiveType
val arrayConstructorName =
if (arrayType != null)
CollectionLiteralResolver.PRIMITIVE_TYPE_TO_ARRAY[PrimitiveType.valueOf(arrayType.jvmPrimitiveType.name)]!!.asString()
else
CollectionLiteralResolver.ARRAY_OF_FUNCTION.asString()
newElement = JKJavaMethodCallExpressionImpl(
context.symbolProvider.provideByFqName("kotlin.$arrayConstructorName"),
JKExpressionListImpl(element.initializer.also { element.initializer = emptyList() })
)
} else if (element is JKJavaNewEmptyArray) {
newElement = buildArrayInitializer(
element.initializer.also { element.initializer = emptyList() }, element.type.type
)
}
return recurse(newElement)
}
private fun buildArrayInitializer(dimensions: List<JKExpression>, type: JKType): JKExpression {
if (dimensions.size == 1) {
return if (type !is JKJavaPrimitiveType) {
JKJavaMethodCallExpressionImpl(
context.symbolProvider.provideByFqName("kotlin/arrayOfNulls"),
JKExpressionListImpl(dimensions[0]),
JKTypeArgumentListImpl(listOf(JKTypeElementImpl(type.updateNullability(Nullability.NotNull))))
)
} else {
JKJavaNewExpressionImpl(
context.symbolProvider.provideByFqName(type.arrayFqName()),
JKExpressionListImpl(dimensions[0]),
JKTypeArgumentListImpl(emptyList())
)
}
}
if (dimensions[1] !is JKStubExpression) {
return JKJavaMethodCallExpressionImpl(
context.symbolProvider.provideByFqName("kotlin.Array"),
JKExpressionListImpl(
dimensions[0],
JKLambdaExpressionImpl(
JKExpressionStatementImpl(buildArrayInitializer(dimensions.subList(1, dimensions.size), type)),
emptyList()
)
)
)
}
var resultType = JKClassTypeImpl(
context.symbolProvider.provideByFqName(type.arrayFqName()),
if (type is JKJavaPrimitiveType) emptyList() else listOf(type),
Nullability.Default
)
for (i in 0 until dimensions.size - 2) {
resultType = JKClassTypeImpl(
context.symbolProvider.provideByFqName(KotlinBuiltIns.FQ_NAMES.array.asString()),
listOf(resultType),
Nullability.NotNull
)
}
return JKJavaMethodCallExpressionImpl(
context.symbolProvider.provideByFqName("kotlin/arrayOfNulls"),
JKExpressionListImpl(dimensions[0]),
JKTypeArgumentListImpl(listOf(JKTypeElementImpl(resultType)))
)
}
}
@@ -1,35 +0,0 @@
/*
* Copyright 2010-2018 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.
*/
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.JKExpressionStatementImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKFieldAccessExpressionImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKFieldSymbol
import org.jetbrains.kotlin.j2k.tree.impl.JKKtThrowExpressionImpl
class ArrayOperationsConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKQualifiedExpression) return recurse(element)
val selector = element.selector as? JKFieldAccessExpression ?: return recurse(element)
if (element.receiver.type(context.symbolProvider) !is JKJavaArrayType) return recurse(element)
if (selector.identifier.name == "length") {
val sizeCall =
JKFieldAccessExpressionImpl(
context.symbolProvider.provideByFqName("kotlin/Array.size")
)
element.selector = sizeCall
}
return recurse(element)
}
}
@@ -1,35 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.*
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.JKExpressionStatementImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKJavaOperatorImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKLambdaExpressionImpl
import org.jetbrains.kotlin.j2k.tree.impl.toKtToken
class AssertStatementConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKJavaAssertStatement) return recurse(element)
val messageExpression =
if (element.description is JKStubExpression) null
else JKLambdaExpressionImpl(
JKExpressionStatementImpl(element::description.detached()),
emptyList()
)
return recurse(
JKExpressionStatementImpl(
kotlinAssert(
element::condition.detached(),
messageExpression,
context.symbolProvider
)
)
)
}
}
@@ -1,39 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.utils.addToStdlib.cast
class AssignmentAsExpressionToAlsoConversion(val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKJavaAssignmentExpression) return recurse(element)
element.invalidate()
val alsoExpression = JKKtAlsoCallExpressionImpl(
JKBlockStatementImpl(
JKBlockImpl(listOf(JKKtAssignmentStatementImpl(element.field, JKStubExpressionImpl(), element.operator)))
), context.symbolProvider.provideByFqName("kotlin/also")
).also {
it.statement.cast<JKBlockStatement>().block.statements.first().cast<JKKtAssignmentStatement>().expression =
JKFieldAccessExpressionImpl(
context.symbolProvider.provideUniverseSymbol(
JKParameterImpl(JKTypeElementImpl(JKContextType), JKNameIdentifierImpl("it"))
)
)//TODO introduce symbol
}
return recurse(
JKQualifiedExpressionImpl(
element.expression,
JKKtQualifierImpl.DOT,
alsoExpression
)
)
}
}
@@ -1,43 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import com.intellij.psi.JavaTokenType
import org.jetbrains.kotlin.j2k.copyTreeAndDetach
import org.jetbrains.kotlin.j2k.tree.JKKtAssignmentStatement
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
import org.jetbrains.kotlin.j2k.tree.detached
import org.jetbrains.kotlin.j2k.tree.impl.*
class AssignmentStatementOperatorConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKKtAssignmentStatement) return recurse(element)
val operator = element.operator as? JKJavaOperatorImpl ?: return recurse(element)
operator.token.correnspondingBinaryOperation()
?.apply {
val expression = element.expression.copyTreeAndDetach()
element.expression =
JKBinaryExpressionImpl(
element.field.copyTreeAndDetach(),
expression,
this
)
element.operator = JKJavaOperatorImpl.tokenToOperator[JavaTokenType.EQ]!!
}
return recurse(element)
}
private fun JKJavaOperatorToken.correnspondingBinaryOperation() =
when (psiToken) {
JavaTokenType.OREQ -> JavaTokenType.OR
JavaTokenType.ANDEQ -> JavaTokenType.AND
JavaTokenType.LTLTEQ -> JavaTokenType.LTLT
JavaTokenType.GTGTEQ -> JavaTokenType.GTGT
JavaTokenType.GTGTGTEQ -> JavaTokenType.GTGTGT
JavaTokenType.XOREQ -> JavaTokenType.XOR
else -> null
}?.let { JKJavaOperatorImpl.tokenToOperator[it] }
}
@@ -1,29 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.JKExpressionStatementImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKStubExpressionImpl
class AssignmentStatementSimplifyAlsoConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKExpressionStatement) return recurse(element)
val qualifiedExpression = element.expression as? JKQualifiedExpression ?: return recurse(element)
val alsoCall = qualifiedExpression.selector as? JKKtAlsoCallExpression ?: return recurse(element)
return recurse(if (alsoCall.statement !is JKBlockStatement) alsoCall.statement.also {
alsoCall.statement = JKExpressionStatementImpl(JKStubExpressionImpl())
inlineVal(it, qualifiedExpression.receiver.also { qualifiedExpression.receiver = JKStubExpressionImpl() })
} else element)
}
private fun inlineVal(statement: JKStatement, expression: JKExpression) {
if (statement is JKKtAssignmentStatement) {
(statement.expression as? JKBinaryExpression)?.right = expression
if (statement.expression !is JKBinaryExpression) statement.expression = expression
}
}
}
@@ -1,45 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.JKStubExpressionImpl
class AssignmentStatementSimplifyValConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKKtAlsoCallExpression) return recurse(element)
val codeBlock = (element.statement as? JKBlockStatement)?.block ?: return recurse(element)
if (codeBlock.statements.size > 1) {
val assignment = codeBlock.statements[1] as? JKKtAssignmentStatement ?: return recurse(element)
val declaration = codeBlock.statements[0] as? JKDeclarationStatement ?: return recurse(element)
when (declaration.declaredStatements.size) {
1 -> if (assignment.expression !is JKBinaryExpression) {
codeBlock.statements = listOf(assignment)
(assignment.field as JKQualifiedExpression).receiver = declaration.extractInitializerByIndex(0)
} else {
}
2 -> if (assignment.expression !is JKBinaryExpression) {
codeBlock.statements = listOf(assignment)
val arrayAccess = assignment.field as JKArrayAccessExpression
arrayAccess.expression = declaration.extractInitializerByIndex(0)
arrayAccess.indexExpression = declaration.extractInitializerByIndex(1)
} else {
}
}
}
if (codeBlock.statements.size == 1) {
element.statement = codeBlock.statements.first().also { codeBlock.statements = emptyList() }
}
return recurse(element)
}
private fun JKDeclarationStatement.extractInitializerByIndex(i: Int): JKExpression {
val variable = (declaredStatements[i] as JKLocalVariable)
return variable.initializer.also { variable.initializer = JKStubExpressionImpl() }
}
}
@@ -1,78 +0,0 @@
/*
* 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.conversions
import org.jetbrains.kotlin.j2k.copyTreeAndDetach
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class AssignmentStatementSplitAlsoConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
return recurse(
when (element) {
is JKBlock -> element.splitAssignmentExpressions()
is JKStatement ->
element.splitAsAssignmentExpressions()?.let { JKBlockStatementImpl(JKBlockImpl(it)) }
else -> null
} ?: element)
}
private fun JKBlock.splitAssignmentExpressions(): JKBlock? {
val newStatements = statements.map { it.splitAsAssignmentExpressions() ?: listOf(it) }
return if (newStatements.any { it.size > 1 }) {
JKBlockImpl(
newStatements.flatMap { statements ->
if (statements.size == 1) statements.map { it.detached(this) }
else statements
}
)
} else null
}
private fun JKStatement.splitAsAssignmentExpressions(): List<JKStatement>? {
val expression = when (this) {
is JKKtAssignmentStatement -> expression
is JKDeclarationStatementImpl -> (declaredStatements.singleOrNull() as? JKLocalVariableImpl)?.initializer
else -> null
} ?: return null
val qualifiedExpression = expression as? JKQualifiedExpression ?: return null
val alsoCall = qualifiedExpression.selector as? JKKtAlsoCallExpression ?: return null
val innerAssignmentStatement = alsoCall.statement as? JKKtAssignmentStatement ?: return null
val secondAssignment = when (this) {
is JKKtAssignmentStatement ->
JKKtAssignmentStatementImpl(
::field.detached(),
innerAssignmentStatement.field.copyTreeAndDetach(),
operator
)
is JKDeclarationStatement -> {
val variable = declaredStatements.single() as JKLocalVariableImpl
JKDeclarationStatementImpl(
listOf(
JKLocalVariableImpl(
variable::type.detached(),
variable::name.detached(),
innerAssignmentStatement.field.copyTreeAndDetach(),
variable.mutability
)
)
)
}
else -> error("expression should be either JKKtAssignmentStatement or JKDeclarationStatementImpl")
}
return listOf(
JKKtAssignmentStatementImpl(
innerAssignmentStatement::field.detached(),
qualifiedExpression::receiver.detached(),
innerAssignmentStatement.operator
),
secondAssignment
)
}
}
@@ -1,67 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class AssignmentStatementValCreationConversion(val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKKtAlsoCallExpression) return recurse(element)
val codeBlock = (element.statement as? JKBlockStatement)?.block ?: return recurse(element)
val assignableExpr = (codeBlock.statements.first() as? JKKtAssignmentStatement)?.field ?: return recurse(element)
when (assignableExpr) {
is JKArrayAccessExpression -> {
val ex1 = assignableExpr.expression
val ex2 = assignableExpr.indexExpression
assignableExpr.expression = JKStubExpressionImpl()
assignableExpr.indexExpression = JKStubExpressionImpl()
codeBlock.statements = listOf(
JKDeclarationStatementImpl(
listOf(
JKLocalVariableImpl(
JKTypeElementImpl(JKJavaVoidType/*TODO*/),
JKNameIdentifierImpl("arr"),
ex1,
Mutability.IMMUTABLE
).also {
assignableExpr.expression = JKFieldAccessExpressionImpl(context.symbolProvider.provideUniverseSymbol(it))
}, JKLocalVariableImpl(
JKTypeElementImpl(JKJavaVoidType/*TODO*/),
JKNameIdentifierImpl("i"),
ex2,
Mutability.UNKNOWN
).also {
assignableExpr.indexExpression =
JKFieldAccessExpressionImpl(context.symbolProvider.provideUniverseSymbol(it))
}
)
)
) + codeBlock.statements
}
is JKQualifiedExpression -> {
val ex = assignableExpr.receiver
assignableExpr.receiver = JKStubExpressionImpl()
codeBlock.statements = listOf(
JKDeclarationStatementImpl(
listOf(
JKLocalVariableImpl(
JKTypeElementImpl(JKJavaVoidType/*TODO*/),
JKNameIdentifierImpl("arg"),
ex,
Mutability.UNKNOWN
).also {
assignableExpr.receiver = JKFieldAccessExpressionImpl(context.symbolProvider.provideUniverseSymbol(it))
}
)
)
) + codeBlock.statements
}
}
return recurse(element)
}
}
@@ -1,32 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
interface BatchBaseConversion {
fun runConversion(treeRoots: List<JKTreeElement>, context: ConversionContext): Boolean
}
interface SequentialBaseConversion : BatchBaseConversion {
fun runConversion(treeRoot: JKTreeElement, context: ConversionContext): Boolean
override fun runConversion(treeRoots: List<JKTreeElement>, context: ConversionContext): Boolean {
return treeRoots.asSequence().map { runConversion(it, context) }.max() ?: false
}
}
@@ -1,36 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.JKBlock
import org.jetbrains.kotlin.j2k.tree.JKBlockStatement
import org.jetbrains.kotlin.j2k.tree.JKDeclaration
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.name.ClassId
class BlockToRunConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKBlockStatement) return recurse(element)
if (element.parent !is JKBlock) return recurse(element)
val parentDeclaration = element.parentOfType<JKDeclaration>() ?: return recurse(element)
val psiContext = parentDeclaration.psi ?: return recurse(element)
element.invalidate()
val lambda = JKLambdaExpressionImpl(
JKBlockStatementImpl(element.block),
emptyList()
)
val call = JKKtCallExpressionImpl(context.symbolProvider.provideByFqName("kotlin.run", true), JKExpressionListImpl(listOf(lambda)))
return recurse(JKExpressionStatementImpl(call))
}
}
@@ -1,63 +0,0 @@
/*
* 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.JKExpressionListImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKKtCallExpressionImpl
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
class BoxedTypeOperationsConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
return recurse(
when (element) {
is JKMethodCallExpression ->
convertBoxedTypeUnwrapping(element)
is JKJavaNewExpression -> convertCreationOfBoxedType(element)
else -> null
} ?: element
)
}
private fun convertCreationOfBoxedType(newExpression: JKJavaNewExpression): JKExpression? {
if (newExpression.classSymbol.fqName !in boxedTypeFqNames) return null
val singleArgument = newExpression.arguments.expressions.singleOrNull() ?: return null
return singleArgument.detached(newExpression.arguments)
}
private fun convertBoxedTypeUnwrapping(methodCallExpression: JKMethodCallExpression): JKExpression? {
val (boxedJavaType, operationType) =
primitiveTypeUnwrapRegexp.matchEntire(methodCallExpression.identifier.fqName)
?.groupValues
?.let {
it[1] to it[2]
} ?: return null
val primitiveTypeName = boxedTypeToPrimitiveType[boxedJavaType] ?: return null
if (operationType !in primitiveTypeNames) return null
return JKKtCallExpressionImpl(
context.symbolProvider.provideByFqName(
"kotlin.${primitiveTypeName.capitalize()}.to${operationType.capitalize()}"
),
JKExpressionListImpl()
)
}
companion object {
private val boxedTypeFqNames =
primitiveTypes.map { it.wrapperFqName.asString() }
private val boxedTypeToPrimitiveType =
primitiveTypes.map { it.wrapperFqName.asString() to it.javaKeywordName }.toMap()
private val primitiveTypeNames =
primitiveTypes.map { it.javaKeywordName }
private val primitiveTypeUnwrapRegexp =
"""([\w.]+)\.(\w+)Value""".toRegex()
}
}
@@ -1,196 +0,0 @@
/*
* 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.parenthesizeIfBinaryExpression
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class BuiltinMembersConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKExpression) return recurse(element)
return recurse(element.convert() ?: element)
}
private fun JKExpression.convert(): JKExpression? {
val selector = when (this) {
is JKQualifiedExpression -> selector
else -> this
}
val conversion = selector.getConversion() ?: return null
val newSelector = conversion.createBuilder().build(selector)
return when (conversion.replaceType) {
ReplaceType.REPLACE_SELECTOR -> {
if (this is JKQualifiedExpression) {
this.selector = newSelector
this
} else newSelector
}
ReplaceType.FULL_REPLACE -> newSelector
}
}
private fun JKExpression.getConversion(): Conversion? = when (this) {
is JKMethodCallExpression ->
conversions[identifier.deepestFqName()]?.firstOrNull() { conversion ->
conversion.from is Method && conversion.byArgumentsFilter?.invoke(arguments.expressions) ?: true
}
is JKFieldAccessExpression ->
conversions[identifier.deepestFqName()]?.firstOrNull { conversion -> conversion.from is Field }
else -> null
}
private interface ResultBuilder {
fun build(from: JKExpression): JKExpression
}
private inner class MethodBuilder(
private val fqName: String,
private val argumentsProvider: (JKExpressionList) -> JKExpressionList
) : ResultBuilder {
override fun build(from: JKExpression): JKExpression =
when (from) {
is JKMethodCallExpression ->
JKKtCallExpressionImpl(
context.symbolProvider.provideByFqNameMulti(fqName),
argumentsProvider(from::arguments.detached()),
from::typeArgumentList.detached()
)
is JKFieldAccessExpression ->
JKKtCallExpressionImpl(
context.symbolProvider.provideByFqNameMulti(fqName),
JKExpressionListImpl(),
JKTypeArgumentListImpl()
)
else -> error("Bad conversion")
}
}
private inner class FieldBuilder(
private val fqName: String
) : ResultBuilder {
override fun build(from: JKExpression): JKExpression =
when (from) {
is JKMethodCallExpression ->
JKFieldAccessExpressionImpl(
context.symbolProvider.provideByFqNameMulti(fqName)
)
is JKFieldAccessExpression ->
JKFieldAccessExpressionImpl(
context.symbolProvider.provideByFqNameMulti(fqName)
)
else -> error("Bad conversion")
}
}
private inner class ExtensionMethodBuilder(
private val fqName: String
) : ResultBuilder {
override fun build(from: JKExpression): JKExpression =
when (from) {
is JKMethodCallExpression -> {
val arguments = from.arguments::expressions.detached()
JKQualifiedExpressionImpl(
arguments.first().parenthesizeIfBinaryExpression(),
JKKtQualifierImpl.DOT,
JKKtCallExpressionImpl(
context.symbolProvider.provideByFqNameMulti(fqName),
JKExpressionListImpl(arguments.drop(1)),
from::typeArgumentList.detached()
)
)
}
else -> error("Bad conversion")
}
}
private fun Conversion.createBuilder(): ResultBuilder =
when (to) {
is Method -> MethodBuilder(to.fqName, argumentsProvider ?: { it })
is Field -> FieldBuilder(to.fqName)
is ExtensionMethod -> ExtensionMethodBuilder(to.fqName)
else -> error("Bad conversion")
}
private enum class ReplaceType {
REPLACE_SELECTOR, FULL_REPLACE
}
private interface Info {
val fqName: String
}
private data class Method(override val fqName: String) : Info
private data class Field(override val fqName: String) : Info
private data class ExtensionMethod(override val fqName: String) : Info
private data class Conversion(
val from: Info,
val to: Info,
val replaceType: ReplaceType = ReplaceType.REPLACE_SELECTOR,
val byArgumentsFilter: ((List<JKExpression>) -> Boolean)? = null,
val argumentsProvider: ((JKExpressionList) -> JKExpressionList)? = null
)
private infix fun Info.convertTo(to: Info) =
Conversion(this, to)
private infix fun Conversion.withReplaceType(replaceType: ReplaceType) =
copy(replaceType = replaceType)
private infix fun Conversion.withByArgumentsFilter(filter: (List<JKExpression>) -> Boolean) =
copy(byArgumentsFilter = filter)
private infix fun Conversion.withArgumentsProvider(argumentsProvider: (JKExpressionList) -> JKExpressionList) =
copy(argumentsProvider = argumentsProvider)
private val conversions: Map<String, List<Conversion>> =
listOf(
Method("java.lang.Integer.intValue") convertTo Method("kotlin.Int.toInt"),//TODO do not list all variants
Method("java.lang.Object.getClass") convertTo Field("kotlin.jvm.javaClass"),
Method("java.util.Map.entrySet") convertTo Field("kotlin.collections.Map.entries"),
Method("java.util.Map.keySet") convertTo Field("kotlin.collections.Map.keys"),
Method("java.util.Map.size") convertTo Field("kotlin.collections.Map.size"),
Method("java.util.Map.values") convertTo Field("kotlin.collections.Map.values"),
Method("java.util.Collection.size") convertTo Field("kotlin.collections.Collection.size"),
Method("java.util.Collection.remove") convertTo Method("kotlin.collections.MutableCollection.remove"),
Method("java.util.List.remove") convertTo Method("kotlin.collections.MutableCollection.removeAt"),
Method("java.util.Map.Entry.getKey") convertTo Field("kotlin.collections.Map.Entry.key"),
Method("java.util.Map.Entry.getValue") convertTo Field("kotlin.collections.Map.Entry.value"),
Method("java.lang.Enum.name") convertTo Field("kotlin.Enum.name"),
Method("java.lang.Enum.ordinal") convertTo Field("kotlin.Enum.ordinal"),
Method("java.lang.Throwable.getCause") convertTo Field("kotlin.Throwable.cause"),
Method("java.lang.Throwable.getMessage") convertTo Field("kotlin.Throwable.message"),
Method("java.lang.CharSequence.length") convertTo Field("kotlin.String.length"),
Method("java.lang.CharSequence.charAt") convertTo Method("kotlin.String.get"),
Method("java.lang.String.valueOf")
convertTo ExtensionMethod("kotlin.Any.toString")
withReplaceType ReplaceType.FULL_REPLACE
withByArgumentsFilter { it.isNotEmpty() && it.first().type(context.symbolProvider)?.isArrayType() == false },
Method("java.util.Collections.singletonList") convertTo Method("kotlin.collections.listOf")
withReplaceType ReplaceType.FULL_REPLACE,
Method("java.util.Collections.singleton") convertTo Method("kotlin.collections.setOf")
withReplaceType ReplaceType.FULL_REPLACE,
Method("java.util.Collections.emptyList")
convertTo Method("kotlin.collections.emptyList") withReplaceType ReplaceType.FULL_REPLACE,
Method("java.util.Collections.emptySet")
convertTo Method("kotlin.collections.emptySet") withReplaceType ReplaceType.FULL_REPLACE,
Method("java.util.Collections.emptyMap")
convertTo Method("kotlin.collections.emptyMap") withReplaceType ReplaceType.FULL_REPLACE
).groupBy { it.from.fqName }
}
@@ -1,65 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
class ClassToObjectPromotionConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element is JKClass && element.classKind == JKClass.ClassKind.CLASS) {
val companion =
element.declarationList.firstIsInstanceOrNull<JKClass>()
?.takeIf { it.classKind == JKClass.ClassKind.COMPANION }
?: return recurse(element)
val allDeclarationsMatches = element.declarationList.all {
when (it) {
is JKKtPrimaryConstructor -> it.parameters.isEmpty() && it.block.statements.isEmpty()
is JKClass -> it.classKind == JKClass.ClassKind.COMPANION
else -> false
}
}
if (allDeclarationsMatches && !element.hasInheritors()) {
companion.invalidate()
element.invalidate()
return recurse(
JKClassImpl(
element.name,
element.inheritance,
JKClass.ClassKind.OBJECT,
element.typeParameterList,
companion.classBody.also {
it.handleDeclarationsModifiers()
},
JKAnnotationListImpl(),
element.extraModifiers,
element.visibility,
Modality.FINAL
)
)
}
}
return recurse(element)
}
private fun JKClassBody.handleDeclarationsModifiers() {
for (declaration in declarations) {
if (declaration !is JKVisibilityOwner) continue
if (declaration.visibility == Visibility.PROTECTED) {
//in old j2k it is internal. should it be private instead?
declaration.visibility = Visibility.INTERNAL
}
}
}
private fun JKClass.hasInheritors() =
context.converter.converterServices.oldServices.referenceSearcher.hasInheritors(psi()!!)
}
@@ -1,62 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
class BatchPipelineConversion(val conversions: List<BatchBaseConversion>) : BatchBaseConversion {
override fun runConversion(treeRoots: List<JKTreeElement>, context: ConversionContext): Boolean {
return conversions.asSequence().map { it.runConversion(treeRoots, context) }.max() ?: false
}
}
class SequentialPipelineConversion(val conversions: List<SequentialBaseConversion>) : SequentialBaseConversion {
override fun runConversion(treeRoot: JKTreeElement, context: ConversionContext): Boolean {
return conversions.asSequence().map { it.runConversion(treeRoot, context) }.max() ?: false
}
}
class BatchRepeatConversion(val conversion: BatchBaseConversion) : BatchBaseConversion {
override fun runConversion(treeRoots: List<JKTreeElement>, context: ConversionContext): Boolean {
return true in generateSequence { conversion.runConversion(treeRoots, context) }.takeWhile { it }
}
}
class SequentialRepeatConversion(val conversion: SequentialBaseConversion) : SequentialBaseConversion {
override fun runConversion(treeRoot: JKTreeElement, context: ConversionContext): Boolean {
return true in generateSequence { conversion.runConversion(treeRoot, context) }.takeWhile { it }
}
}
class PipelineConversionBuilder<T : BatchBaseConversion> {
val conversions = mutableListOf<T>()
operator fun T.unaryPlus() {
conversions += this
}
}
internal inline fun sequentialPipe(crossinline configure: PipelineConversionBuilder<SequentialBaseConversion>.() -> Unit): SequentialPipelineConversion {
return SequentialPipelineConversion(
PipelineConversionBuilder<SequentialBaseConversion>().apply(configure).conversions
)
}
internal inline fun batchPipe(crossinline configure: PipelineConversionBuilder<BatchBaseConversion>.() -> Unit): BatchPipelineConversion {
return BatchPipelineConversion(
PipelineConversionBuilder().apply(configure).conversions
)
}
internal inline fun batchRepeat(batchBaseConversion: BatchBaseConversion): BatchRepeatConversion {
return BatchRepeatConversion(batchBaseConversion)
}
internal inline fun sequentialRepeat(sequentialBaseConversion: SequentialBaseConversion): SequentialRepeatConversion {
return SequentialRepeatConversion(sequentialBaseConversion)
}
@@ -1,43 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class ConstructorConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKJavaMethod) return recurse(element)
val outerClass = element.parentOfType<JKClass>() ?: return recurse(element)
if (element.name.value != outerClass.name.value) return recurse(element)
element.invalidate()
val delegationCall = lookupDelegationCall(element.block) ?: JKStubExpressionImpl()
return JKKtConstructorImpl(
element.name,
element.parameters,
element.block,
delegationCall,
element.annotationList,
element.extraModifiers,
element.visibility,
element.modality
).also {
context.symbolProvider.transferSymbol(it, element)
}
}
private fun lookupDelegationCall(block: JKBlock): JKDelegationConstructorCall? {
val firstStatement = block.statements.firstOrNull() ?: return null
val expressionStatement = firstStatement as? JKExpressionStatement ?: return null
val expression = expressionStatement.expression as? JKDelegationConstructorCall ?: return null
block.statements -= expressionStatement
expressionStatement.invalidate()
return expression
}
}
@@ -1,116 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.jvmAnnotation
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.JKFieldAccessExpressionImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKUniverseMethodSymbol
import org.jetbrains.kotlin.j2k.tree.impl.psi
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class DefaultArgumentsConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
private fun JKMethod.canNotBeMerged(): Boolean =
modality == Modality.ABSTRACT ||
modality == Modality.OVERRIDE ||
context.converter.converterServices.oldServices.referenceSearcher.hasOverrides(psi()!!) ||
annotationList.annotations.isNotEmpty()
override fun applyToElement(element: JKTreeElement): JKTreeElement {
// TODO: Declaration list owner
if (element !is JKClass) return recurse(element)
val methods = element.declarationList.filterIsInstance<JKMethod>().sortedBy { it.parameters.size }
checkMethod@ for (method in methods) {
val block = method.block as? JKBlock ?: continue
val singleStatement = block.statements.singleOrNull() ?: continue
if (method.canNotBeMerged()) continue
val call = lookupCall(singleStatement) ?: continue
val callee = call.identifier as? JKUniverseMethodSymbol ?: continue
val calledMethod = callee.target
if (calledMethod.parent != method.parent
|| callee.name != method.name.value
|| calledMethod.returnType.type != method.returnType.type
|| call.arguments.expressions.size <= method.parameters.size
) {
continue
}
// TODO: Filter by annotations, visibility, modality, modifiers like synchronized
if (calledMethod.visibility != method.visibility) continue@checkMethod
if (calledMethod.canNotBeMerged()) continue
for (i in method.parameters.indices) {
val parameter = method.parameters[i]
val targetParameter = calledMethod.parameters[i]
val argument = call.arguments.expressions[i]
if (parameter.name.value != targetParameter.name.value) continue@checkMethod
// if (parameter.type.type != targetParameter.type.type) continue@checkMethod
// if (argument !is JKFieldAccessExpression || argument.identifier.target != parameter) continue@checkMethod
}
call.arguments.invalidate()
val defaults = call.arguments.expressions
.zip(calledMethod.parameters)
.drop(method.parameters.size)
for ((defaultValue, parameter) in defaults) {
fun remapParameterSymbol(on: JKTreeElement): JKTreeElement {
if (on is JKFieldAccessExpression) {
val target = on.identifier.target
if (target is JKParameter) {
val newSymbol =
context.symbolProvider.provideUniverseSymbol(calledMethod.parameters[method.parameters.indexOf(target)])
return JKFieldAccessExpressionImpl(newSymbol)
}
}
return applyRecursive(on, ::remapParameterSymbol)
}
parameter.initializer = remapParameterSymbol(defaultValue) as JKExpression
}
element.classBody.declarations -= method
}
for (method in element.declarationList) {
if (method !is JKJavaMethod) continue
if (method.hasParametersWithDefaultValues() && (method.visibility == Visibility.PUBLIC || method.visibility == Visibility.INTERNAL)) {
method.annotationList.annotations += jvmAnnotation("JvmOverloads", context.symbolProvider)
}
}
return recurse(element)
}
private fun JKMethod.hasParametersWithDefaultValues() =
parameters.any { it.initializer !is JKStubExpression }
private fun lookupCall(statement: JKStatement): JKMethodCallExpression? {
val expression = when (statement) {
is JKExpressionStatement -> statement.expression
is JKReturnStatement -> statement.expression
else -> null
}
return when (expression) {
is JKMethodCallExpression -> expression
is JKQualifiedExpression -> {
if (expression.receiver !is JKThisExpression) return null
expression.selector.safeAs()
}
else -> null
}
}
}
@@ -1,20 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.JKTypeElementImpl
class DefaultNullabilityToNullableConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKTypeElementImpl) return recurse(element)
if (element.type.nullability != Nullability.Default) return recurse(element)
return recurse(
JKTypeElementImpl(element.type.updateNullability(Nullability.Nullable))
)
}
}
@@ -1,36 +0,0 @@
/*
* 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.conversions
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.equalsExpression
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.lexer.KtTokens
class EqualsOperatorConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKQualifiedExpression) return recurse(element)
if (element.receiver is JKSuperExpression) return recurse(element)
val selector = element.selector as? JKMethodCallExpression ?: return (element)
val argument = selector.arguments.expressions.singleOrNull() ?: return recurse(element)
if (selector.identifier.deepestFqName() == "java.lang.Object.equals") {
return recurse(
JKParenthesizedExpressionImpl(
equalsExpression(
element::receiver.detached(),
argument.detached(selector.arguments),
context.symbolProvider
)
)
)
}
return recurse(element)
}
}
@@ -1,35 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class FieldToPropertyConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKJavaField) return recurse(element)
element.invalidate()
val mutability =
if (element.modality == Modality.FINAL) Mutability.IMMUTABLE
else Mutability.MUTABLE
return recurse(
JKKtPropertyImpl(
element.type,
element.name,
element.initializer,
JKKtEmptyGetterOrSetterImpl(),
JKKtEmptyGetterOrSetterImpl(),
element.annotationList,
element.extraModifiers,
element.visibility,
Modality.FINAL,
mutability
).also {
it.psi = element.psi
}
)
}
}
@@ -1,314 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import com.intellij.psi.*
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.j2k.*
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.ClassId
class ForConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
private val referenceSearcher: ReferenceSearcher
get() = context.converter.converterServices.oldServices.referenceSearcher
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKJavaForLoopStatement) return recurse(element)
convertToForeach(element)?.also { return recurse(it) }
convertToWhile(element)?.also { return recurse(it) }
return recurse(element)
}
private fun convertToWhile(loopStatement: JKJavaForLoopStatement): JKStatement? {
val whileBody = createWhileBody(loopStatement)
val condition =
if (loopStatement.condition !is JKStubExpression) loopStatement::condition.detached()
else JKBooleanLiteral(true)
val whileStatement = JKWhileStatementImpl(condition, whileBody)
if (loopStatement.initializer is JKEmptyStatement) return whileStatement
val convertedFromForLoopSyntheticWhileStatement =
JKKtConvertedFromForLoopSyntheticWhileStatementImpl(
loopStatement::initializer.detached(),
whileStatement
)
val notNeedParentBlock = loopStatement.parent is JKBlock
|| loopStatement.parent is JKLabeledStatement && loopStatement.parent?.parent is JKBlock
return when {
loopStatement.hasNameConflict() ->
JKExpressionStatementImpl(
runExpression(
convertedFromForLoopSyntheticWhileStatement,
context.symbolProvider
)
)
!notNeedParentBlock -> blockStatement(convertedFromForLoopSyntheticWhileStatement)
else -> convertedFromForLoopSyntheticWhileStatement
}
}
private fun createWhileBody(loopStatement: JKJavaForLoopStatement): JKStatement {
if (loopStatement.updaters.singleOrNull() is JKEmptyStatement) return loopStatement::body.detached()
val continueStatementConverter = object : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKContinueStatement) return recurse(element)
val elementPsi = element.psi<PsiContinueStatement>()!!
if (elementPsi.findContinuedStatement()?.toContinuedLoop() != loopStatement.psi<PsiForStatement>()) return recurse(element)
val statements = loopStatement.updaters.map { it.copyTreeAndDetach() } + element.copyTreeAndDetach()
return if (element.parent is JKBlock)
JKBlockStatementWithoutBracketsImpl(JKBlockImpl(statements))
else JKBlockStatementImpl(JKBlockImpl(statements))
}
}
val body = continueStatementConverter.applyToElement(loopStatement::body.detached())
if (body is JKBlockStatement) {
val initializer = loopStatement.initializer
val hasNameConflict =
initializer is JKDeclarationStatement && initializer.declaredStatements.any { loopVar ->
loopVar is JKLocalVariable && body.statements.any { statement ->
statement is JKDeclarationStatement && statement.declaredStatements.any {
it is JKLocalVariable && it.name.value == loopVar.name.value
}
}
}
val statements =
if (hasNameConflict) {
listOf(JKExpressionStatementImpl(runExpression(body, context.symbolProvider))) + loopStatement::updaters.detached()
} else {
body.block::statements.detached() + loopStatement::updaters.detached()
}
return JKBlockStatementImpl(JKBlockImpl(statements))
} else {
val statements =
listOf(body as JKStatement) + loopStatement::updaters.detached()
return JKBlockStatementImpl(JKBlockImpl(statements))
}
}
private fun convertToForeach(loopStatement: JKJavaForLoopStatement): JKForInStatement? {
val loopVar =
(loopStatement.initializer as? JKDeclarationStatement)?.declaredStatements?.singleOrNull() as? JKLocalVariable ?: return null
val loopVarPsi = loopVar.psi<PsiLocalVariable>() ?: return null
val condition = loopStatement.condition as? JKBinaryExpression ?: return null
if (!loopVarPsi.hasWriteAccesses(referenceSearcher, loopStatement.body.psi())
&& !loopVarPsi.hasWriteAccesses(referenceSearcher, loopStatement.condition.psi())
) {
val left = condition.left as? JKFieldAccessExpression ?: return null
val right = condition::right.detached()
if (right.psi<PsiExpression>()?.type in listOf(PsiType.DOUBLE, PsiType.FLOAT, PsiType.CHAR)) return null
if (left.identifier.target != loopVar) return null
val start = loopVar::initializer.detached()
val operationType =
(loopStatement.updaters.singleOrNull() as? JKExpressionStatement)?.expression?.isVariableIncrementOrDecrement(loopVar)
val reversed = when (operationType?.token?.text) {
"++" -> false
"--" -> true
else -> return null
}
val operatorToken =
((condition.operator as? JKKtOperatorImpl)?.token as? JKKtSingleValueOperatorToken)?.psiToken
val inclusive = when (operatorToken) {
KtTokens.LT -> if (reversed) return null else false
KtTokens.LTEQ -> if (reversed) return null else true
KtTokens.GT -> if (reversed) false else return null
KtTokens.GTEQ -> if (reversed) true else return null
KtTokens.EXCLEQ -> false
else -> return null
}
val range = forIterationRange(start, right, reversed, inclusive, loopVarPsi)
val explicitType =
if (context.converter.settings.specifyLocalVariableTypeByDefault)
JKJavaPrimitiveTypeImpl.INT
else JKNoTypeImpl
val loopVarDeclaration =
JKForLoopVariableImpl(
JKTypeElementImpl(explicitType),
loopVar::name.detached(),
JKStubExpressionImpl()
)
return JKForInStatementImpl(
loopVarDeclaration,
range,
loopStatement::body.detached()
)
}
return null
}
private fun PsiStatement.toContinuedLoop(): PsiLoopStatement? {
return when (this) {
is PsiLoopStatement -> this
is PsiLabeledStatement -> statement?.toContinuedLoop()
else -> null
}
}
private fun forIterationRange(
start: JKExpression,
bound: JKExpression,
reversed: Boolean,
inclusiveComparison: Boolean,
psiContext: PsiElement
): JKExpression {
indicesIterationRange(start, bound, reversed, inclusiveComparison)?.also { return it }
return when {
reversed -> downToExpression(
start,
convertBound(bound, if (inclusiveComparison) 0 else +1),
context,
psiContext
)
bound !is JKKtLiteralExpression && !inclusiveComparison ->
untilToExpression(
start,
convertBound(bound, 0),
context,
psiContext
)
else -> kotlinBinaryExpression(
start,
convertBound(bound, if (inclusiveComparison) 0 else -1),
JKKtSingleValueOperatorToken(KtTokens.RANGE),
context.symbolProvider
)!!
}
}
private fun convertBound(bound: JKExpression, correction: Int): JKExpression {
if (correction == 0) return bound
if (bound is JKLiteralExpression && bound.type == JKLiteralExpression.LiteralType.INT) {
val value = bound.literal.toInt()
return JKKtLiteralExpressionImpl((value + correction).toString(), bound.type)
}
val sign = if (correction > 0) KtTokens.PLUS else KtTokens.MINUS
return kotlinBinaryExpression(
bound,
JKKtLiteralExpressionImpl(Math.abs(correction).toString(), JKLiteralExpression.LiteralType.INT),
JKKtSingleValueOperatorToken(sign),
context.symbolProvider
)!!
}
private fun indicesIterationRange(
start: JKExpression,
bound: JKExpression,
reversed: Boolean,
inclusiveComparison: Boolean
): JKExpression? {
val collectionSizeExpression =
if (reversed) {
if (!inclusiveComparison) return null
if ((bound as? JKLiteralExpression)?.literal?.toIntOrNull() != 0) return null
if (start !is JKBinaryExpression) return null
if (start.operator.token.text != "-") return null
if ((start.right as? JKLiteralExpression)?.literal?.toIntOrNull() != 1) return null
start.left
} else {
if (inclusiveComparison) return null
if ((start as? JKLiteralExpression)?.literal?.toIntOrNull() != 0) return null
bound
} as? JKQualifiedExpression ?: return null
val indices = indicesByCollectionSize(collectionSizeExpression)
?: indicesByArrayLength(collectionSizeExpression)
?: return null
val psiContext = collectionSizeExpression.psi<PsiExpression>() ?: return null
return if (reversed) {
val reversedSymbol = context.symbolProvider.provideDirectSymbol(
multiResolveFqName(ClassId.fromString("kotlin/collections/reversed"), psiContext).first()
) as JKMethodSymbol
JKQualifiedExpressionImpl(
indices,
JKKtQualifierImpl.DOT,
JKJavaMethodCallExpressionImpl(reversedSymbol, JKExpressionListImpl())
)
} else indices
}
private fun indicesByCollectionSize(javaSizeCall: JKQualifiedExpression): JKQualifiedExpression? {
val methodCall = javaSizeCall.selector as? JKMethodCallExpression ?: return null
return if (methodCall.identifier.deepestFqName() == "java.util.Collection.size"
&& methodCall.arguments.expressions.isEmpty()
) toIndicesCall(javaSizeCall) else null
}
private fun indicesByArrayLength(javaSizeCall: JKQualifiedExpression): JKQualifiedExpression? {
val methodCall = javaSizeCall.selector as? JKFieldAccessExpression ?: return null
val receiverType = javaSizeCall.receiver.type(context.symbolProvider)
if (methodCall.identifier.name == "length" && receiverType is JKJavaArrayType) {
return toIndicesCall(javaSizeCall)
}
return null
}
private fun toIndicesCall(javaSizeCall: JKQualifiedExpression): JKQualifiedExpression? {
val psiContext = javaSizeCall.psi ?: return null
val indiciesSymbol = context.symbolProvider.provideDirectSymbol(
multiResolveFqName(ClassId.fromString("kotlin/collections/indices"), psiContext).first()
) as JKMultiversePropertySymbol
val selector = JKFieldAccessExpressionImpl(indiciesSymbol)
return JKQualifiedExpressionImpl(javaSizeCall::receiver.detached(), javaSizeCall.operator, selector)
}
private fun JKJavaForLoopStatement.hasNameConflict(): Boolean {
val names = initializer.declaredVariableNames()
if (names.isEmpty()) return false
val factory = PsiElementFactory.SERVICE.getInstance(context.project)
for (name in names) {
val refExpr = try {
factory.createExpressionFromText(name, psi) as? PsiReferenceExpression ?: return true
} catch (e: IncorrectOperationException) {
return true
}
if (refExpr.resolve() != null) return true
}
return (parent as? JKBlock)
?.statements
?.takeLastWhile { it != this }
?.any {
it.declaredVariableNames().any { it in names }
} == true
}
private fun JKStatement.declaredVariableNames(): Collection<String> =
when (this) {
is JKDeclarationStatement ->
declaredStatements.filterIsInstance<JKVariable>().map { it.name.value }
is JKJavaForLoopStatement -> initializer.declaredVariableNames()
else -> emptyList()
}
private fun JKExpression.isVariableIncrementOrDecrement(variable: JKLocalVariable): JKOperator? {
val pair = when (this) {
is JKPostfixExpression -> operator to expression
is JKPrefixExpression -> operator to expression
else -> return null
}
if ((pair.second as? JKFieldAccessExpression)?.identifier?.target != variable) return null
return pair.first
}
}
@@ -1,29 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import com.intellij.psi.*
import org.jetbrains.kotlin.j2k.*
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.ClassId
class ForInConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKForInStatement) return recurse(element)
val parameterDeclaration = element.declaration as? JKVariable
if (parameterDeclaration != null
&& !context.converter.settings.specifyLocalVariableTypeByDefault
) {
parameterDeclaration.type = JKTypeElementImpl(JKNoTypeImpl)
}
return recurse(element)
}
}
@@ -1,186 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.*
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
class ImplicitCastsConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
when (element) {
is JKVariable -> convertVariable(element)
is JKForInStatement -> convertForInStatement(element)
is JKMethodCallExpression -> convertMethodCallExpression(element)
is JKBinaryExpression -> return recurse(convertBinaryExpression(element))
is JKKtAssignmentStatement -> convertAssignmentStatement(element)
}
return recurse(element)
}
private fun convertBinaryExpression(binaryExpression: JKBinaryExpression): JKExpression {
fun JKBinaryExpression.addBangBang(): JKBinaryExpression {
fun JKType.isAcceptable() = asPrimitiveType() != null
if (operator.isEquals()) return this
val leftType = left.type(context.symbolProvider) ?: return this
val rightType = right.type(context.symbolProvider) ?: return this
return if (leftType.isAcceptable()
&& rightType.isAcceptable()
&& (leftType.isNullable() || rightType.isNullable())
&& (operator.isArithmetic() || operator.isLessOrGreater())
) {
JKBinaryExpressionImpl(
::left.detached().bangedBangedExpr(context.symbolProvider),
::right.detached().bangedBangedExpr(context.symbolProvider),
operator
)
} else this
}
fun JKBinaryExpression.convertComparationExpression(): JKBinaryExpression {
if (!operator.isComparationOperator()) return this
val leftType = left.type(context.symbolProvider)?.asPrimitiveType() ?: return this
val rightType = right.type(context.symbolProvider)?.asPrimitiveType() ?: return this
val leftOperandCastedCasted by lazy {
JKBinaryExpressionImpl(
::left.detached().let { it.castTo(rightType, strict = true) ?: it },
::right.detached(),
operator
)
}
val rightOperandCastedCasted by lazy {
JKBinaryExpressionImpl(
::left.detached(),
::right.detached().let { it.castTo(leftType, strict = true) ?: it },
operator
)
}
println()
return when {
leftType.jvmPrimitiveType == rightType.jvmPrimitiveType -> this
leftType.jvmPrimitiveType == JvmPrimitiveType.CHAR -> leftOperandCastedCasted
rightType.jvmPrimitiveType == JvmPrimitiveType.CHAR -> rightOperandCastedCasted
operator.isEquals() ->
if (rightType isStrongerThan leftType) leftOperandCastedCasted
else rightOperandCastedCasted
else -> this
}
}
return binaryExpression.convertComparationExpression().addBangBang()
}
private fun convertVariable(variable: JKVariable) {
if (variable.initializer is JKStubExpression) return
variable.initializer.castTo(variable.type.type)?.also {
variable.initializer = it
}
}
private fun convertForInStatement(forInStatement: JKForInStatement) {
val notNullType = forInStatement.iterationExpression.type(context.symbolProvider)?.updateNullability(Nullability.NotNull) ?: return
forInStatement.iterationExpression.addBangBang(notNullType)?.also {
forInStatement.iterationExpression = it
}
}
private fun convertAssignmentStatement(statement: JKKtAssignmentStatement) {
val expressionType = statement.field.type(context.symbolProvider) ?: return
statement.expression.castTo(expressionType)?.also {
statement.expression = it
}
}
private fun convertMethodCallExpression(expression: JKMethodCallExpression) {
if (expression.identifier.isUnresolved()) return
val parameterTypes = expression.identifier.parameterTypesWithUnfoldedVarargs() ?: return
val newArguments =
(expression.arguments.expressions.asSequence() zip parameterTypes)
.map { (expression, toType) ->
expression.castTo(toType)
}.toList()
val needUpdate = newArguments.any { it != null }
if (needUpdate) {
expression.arguments = JKExpressionListImpl(
(newArguments zip expression.arguments.expressions)
.map { (newArgument, oldArgument) ->
(newArgument ?: oldArgument).copyTreeAndDetach()
}
)
}
}
private fun JKExpression.addBangBang(toType: JKType): JKExpression? {
if (this is JKJavaNewExpression) return null
val expressionType = type(context.symbolProvider) as? JKClassType ?: return null
if (toType !is JKClassType) return null
if (expressionType.classReference == toType.classReference
&& expressionType.isNullable() && !toType.isNullable()
) {
return this.copyTreeAndDetach().bangedBangedExpr(context.symbolProvider)
}
return null
}
private fun JKExpression.castToAsPrimitiveTypes(toType: JKType, strict: Boolean): JKExpression? {
if (this is JKPrefixExpression
&& (operator.token.text == "+" || operator.token.text == "-")
) {
val casted = expression.castToAsPrimitiveTypes(toType, strict) ?: return null
return JKPrefixExpressionImpl(casted, operator)
}
val expressionTypeAsPrimitive = type(context.symbolProvider)?.asPrimitiveType() ?: return null
val toTypeAsPrimitive = toType.asPrimitiveType() ?: return null
if (toTypeAsPrimitive == expressionTypeAsPrimitive) return null
if (this is JKLiteralExpression) {
if (!strict
&& expressionTypeAsPrimitive == JKJavaPrimitiveTypeImpl.INT
&& (toTypeAsPrimitive == JKJavaPrimitiveTypeImpl.LONG ||
toTypeAsPrimitive == JKJavaPrimitiveTypeImpl.SHORT ||
toTypeAsPrimitive == JKJavaPrimitiveTypeImpl.BYTE)
) return null
val expectedType = toTypeAsPrimitive.toLiteralType() ?: JKLiteralExpression.LiteralType.INT
if (expressionTypeAsPrimitive.isNumberType() && toTypeAsPrimitive.isNumberType()) {
return JKJavaLiteralExpressionImpl(
literal,
expectedType
).fixLiteral(expectedType)
}
}
val initialTypeName = expressionTypeAsPrimitive.jvmPrimitiveType.javaKeywordName.capitalize()
val conversionFunctionName = "to${toTypeAsPrimitive.jvmPrimitiveType.javaKeywordName.capitalize()}"
return JKQualifiedExpressionImpl(
this.copyTreeAndDetach(),
JKKtQualifierImpl.DOT,
JKJavaMethodCallExpressionImpl(
context.symbolProvider.provideByFqName("kotlin.$initialTypeName.$conversionFunctionName"),
JKExpressionListImpl()
)
)
}
private fun JKExpression.castTo(toType: JKType, strict: Boolean = false): JKExpression? {
val expressionType = type(context.symbolProvider)
if (expressionType == toType) return null
castToAsPrimitiveTypes(toType, strict)?.also { return it }
return addBangBang(toType)
}
}
@@ -1,115 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.findUsages
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class ImplicitInitializerConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
enum class InitializationState {
INITIALIZED_IN_ALL_CONSTRUCTORS,
INITIALIZED_IN_SOME_CONSTRUCTORS,
NON_INITIALIZED
}
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKJavaField) return recurse(element)
if (element.initializer !is JKStubExpression) return recurse(element)
val initializationState = element.initializationState()
when {
initializationState == InitializationState.INITIALIZED_IN_ALL_CONSTRUCTORS ->
return recurse(element)
initializationState == InitializationState.INITIALIZED_IN_SOME_CONSTRUCTORS
&& element.modality == Modality.FINAL ->
return recurse(element)
}
val fieldType = element.type.type
val newInitializer = when (fieldType) {
is JKClassType -> JKNullLiteral()
is JKJavaPrimitiveType -> createPrimitiveTypeInitializer(fieldType)
else -> null
}
newInitializer?.also {
element.initializer = it
}
return element
}
private fun JKJavaField.initializationState(): InitializationState {
val fieldSymbol = context.symbolProvider.provideUniverseSymbol(this)
val containingClass = parentOfType<JKClass>() ?: return InitializationState.NON_INITIALIZED
val symbolToConstructor = containingClass.declarationList
.filterIsInstance<JKKtConstructor>()
.map { context.symbolProvider.provideUniverseSymbol(it) to it }
.toMap()
fun JKMethodSymbol.parentConstructor(): JKMethodSymbol? =
(symbolToConstructor[this]!!.delegationCall as? JKDelegationConstructorCall)
?.identifier
val constructors = containingClass.declarationList
.filterIsInstance<JKKtConstructor>()
.map { context.symbolProvider.provideUniverseSymbol(it) to false }
.toMap()
.toMutableMap()
val constructorsWithInitializers = findUsages(parentOfType<JKClass>()!!, context).mapNotNull { usage ->
val parent = usage.parent
val assignmentStatement =
when {
parent is JKKtAssignmentStatement -> parent
parent is JKQualifiedExpression && parent.receiver is JKThisExpression ->
parent.parent as? JKKtAssignmentStatement
else -> null
} ?: return@mapNotNull null
val constructor =
(assignmentStatement.parent as? JKBlock)?.parent as? JKKtConstructor ?: return@mapNotNull null
val isInitializer = when (parent) {
is JKKtAssignmentStatement -> (parent.field as? JKFieldAccessExpression)?.identifier == fieldSymbol
is JKQualifiedExpression -> (parent.selector as? JKFieldAccessExpression)?.identifier == fieldSymbol
else -> false
}
if (!isInitializer) return@mapNotNull null
constructor
}
for (constructor in constructorsWithInitializers) {
constructors[context.symbolProvider.provideUniverseSymbol(constructor)] = true
}
for ((constructor, initialized) in constructors) {
if (initialized) continue
val parentConstructors =
generateSequence(constructor) { it.parentConstructor() }
if (parentConstructors.any { constructors[it]!! }) {
parentConstructors.forEach { constructors[it] = true }
}
}
val initializedInConstructorsCount = constructors.values.count { it }
return when (initializedInConstructorsCount) {
0 -> InitializationState.NON_INITIALIZED
constructors.size -> InitializationState.INITIALIZED_IN_ALL_CONSTRUCTORS
else -> InitializationState.INITIALIZED_IN_SOME_CONSTRUCTORS
}
}
private fun createPrimitiveTypeInitializer(primitiveType: JKJavaPrimitiveType): JKLiteralExpression =
when (primitiveType) {
is JKJavaPrimitiveTypeImpl.BOOLEAN ->
JKBooleanLiteral(false)
else ->
JKJavaLiteralExpressionImpl("0", JKLiteralExpression.LiteralType.INT)
}
}
@@ -1,117 +0,0 @@
/*
* Copyright 2010-2018 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.
*/
/*
* Copyright 2010-2018 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.conversions
import com.intellij.psi.CommonClassNames
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.JKImportStatementImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKNameIdentifierImpl
import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitorVoid
class ImportStatementConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKFile) return recurse(element)
for (import in element.declarationList.collectImports()) {
if (!element.importList.containsImport(import)) {
element.importList += JKImportStatementImpl(JKNameIdentifierImpl(import))
}
}
element.importList = element.importList.filter { it.name.value !in importExceptionList }
return recurse(element)
}
private val importExceptionList =
listOf(
CommonClassNames.JAVA_UTIL_ARRAY_LIST,
CommonClassNames.JAVA_UTIL_LIST,
CommonClassNames.JAVA_UTIL_HASH_SET,
CommonClassNames.JAVA_UTIL_HASH_MAP,
CommonClassNames.JAVA_UTIL_COLLECTION,
CommonClassNames.JAVA_UTIL_ITERATOR,
"java.util.LinkedHashMap",
"java.util.LinkedHashSet"
)
private fun importIsInPackage(import: String, packageName: String) =
'.' !in import.substringAfter(packageName)
private fun List<JKImportStatement>.containsImport(import: String) =
asSequence()
.map { it.name.value }
.any {
it == import ||
it.endsWith("*") && import.substringBeforeLast(".") == it.substringBeforeLast(".*")
}
private fun List<JKDeclaration>.collectImports(): List<String> {
val collectImportsVisitor = CollectImportsVisitor()
forEach {
it.accept(collectImportsVisitor)
}
return collectImportsVisitor.collectedFqNames
}
private class CollectImportsVisitor : JKVisitorVoid {
private val unfilteredCollectedFqNames = mutableSetOf<String>()
private val defaultImports =
listOf(
"kotlin",
"kotlin.annotation",
"kotlin.collections",
"kotlin.comparisons",
"kotlin.io",
"kotlin.ranges",
"kotlin.sequences",
"kotlin.text",
"java.lang",
"kotlin.jvm"
)
val collectedFqNames
get() = unfilteredCollectedFqNames.filter {
it.substringBeforeLast(".") !in defaultImports && it.contains(".")
}
override fun visitTreeElement(treeElement: JKTreeElement) {
treeElement.acceptChildren(this)
}
override fun visitJavaNewExpression(javaNewExpression: JKJavaNewExpression) {
unfilteredCollectedFqNames += javaNewExpression.classSymbol.fqName!!
javaNewExpression.acceptChildren(this)
}
override fun visitTypeElement(typeElement: JKTypeElement, data: Nothing?) {
val classType = typeElement.type as? JKClassType ?: return
unfilteredCollectedFqNames += classType.classReference.fqName!!
}
override fun visitFieldAccessExpression(fieldAccessExpression: JKFieldAccessExpression) {
unfilteredCollectedFqNames += fieldAccessExpression.identifier.fqName
}
override fun visitMethodCallExpression(methodCallExpression: JKMethodCallExpression) {
unfilteredCollectedFqNames += methodCallExpression.identifier.fqName
}
override fun visitClassLiteralExpression(classLiteralExpression: JKClassLiteralExpression) {
val type = classLiteralExpression.classType.type
if (type is JKClassType) {
unfilteredCollectedFqNames += type.classReference.fqName!!
}
classLiteralExpression.acceptChildren(this)
}
}
}
@@ -1,35 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.tree.*
class InnerClassConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKClass) return recurse(element)
return recurseArmed(element, element)
}
private fun recurseArmed(element: JKTreeElement, outer: JKClass): JKTreeElement {
return applyRecursive(element, outer, ::applyArmed)
}
private fun applyArmed(element: JKTreeElement, outer: JKClass): JKTreeElement {
if (element !is JKClass) return recurseArmed(element, outer)
if (element.isLocalClass()) return recurseArmed(element, outer)
val static = element.extraModifiers.find { it == ExtraModifier.STATIC }
if (static != null) {
element.extraModifiers -= static
} else if (element.classKind != JKClass.ClassKind.INTERFACE &&
outer.classKind != JKClass.ClassKind.INTERFACE &&
element.classKind != JKClass.ClassKind.ENUM
) {
element.extraModifiers += ExtraModifier.INNER
}
return recurseArmed(element, element)
}
}
@@ -1,53 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class InsertDefaultPrimaryConstructorConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKClass) return recurse(element)
if (element.classKind != JKClass.ClassKind.CLASS) return recurse(element)
if (element.declarationList.any { it is JKKtConstructor }) return recurse(element)
val constructor = JKKtPrimaryConstructorImpl(
JKNameIdentifierImpl(element.name.value),
emptyList(),
JKStubExpressionImpl(),
JKAnnotationListImpl(),
emptyList(),
Visibility.PUBLIC,
Modality.FINAL
)
element.classBody.declarations += constructor
val superClassSymbol =
(element.inheritance.extends.singleOrNull() as? JKClassType)?.classReference
if (superClassSymbol is JKUniverseClassSymbol) {
val superClass = recurse(superClassSymbol.target)
val superConstructor = context.symbolProvider.provideUniverseSymbol(
superClass.declarationList.singleOrNull { it is JKKtConstructor && it.parameters.isEmpty() } as? JKMethod ?: return recurse(
element
)
)
constructor.delegationCall = JKDelegationConstructorCallImpl(superConstructor, JKSuperExpressionImpl(), JKExpressionListImpl())
}
return recurse(element)
}
private val JKClassSymbol.kind
get() = when (this) {
is JKUniverseClassSymbol -> target.classKind
else -> null
}
}
@@ -1,31 +0,0 @@
/*
* 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.conversions
import org.jetbrains.kotlin.j2k.*
import org.jetbrains.kotlin.j2k.tree.*
class InterfaceWithFieldConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKClass) return recurse(element)
if (element.classKind != JKClass.ClassKind.INTERFACE
&& element.classKind != JKClass.ClassKind.ANNOTATION
) return recurse(element)
val fieldsToMoveToCompanion = element.declarationList
.filterIsInstance<JKField>()
.filter { field ->
field.modality == Modality.FINAL || element.classKind == JKClass.ClassKind.ANNOTATION
}
if (fieldsToMoveToCompanion.isNotEmpty()) {
element.classBody.declarations -= fieldsToMoveToCompanion
val companion = element.getOrCreateCompainonObject()
companion.classBody.declarations += fieldsToMoveToCompanion
}
return recurse(element)
}
}
@@ -1,24 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.tree.*
class InternalClassConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKVisibilityOwner || element !is JKModalityOwner) return recurse(element)
val containingClass = element.parentOfType<JKClass>() ?: return recurse(element)
if (containingClass.visibility == Visibility.INTERNAL
&& element.visibility == Visibility.INTERNAL
&& element.modality == Modality.FINAL
&& (element is JKMethod || element is JKField)
) {
element.visibility = Visibility.PUBLIC
}
return recurse(element)
}
}
@@ -1,73 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.JKAnnotationParameterImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKFieldAccessExpressionImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKKtLiteralExpressionImpl
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class JavaAnnotationsConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKAnnotation) return recurse(element)
if (element.classSymbol.name == "Deprecated" && element.arguments.isEmpty()) {
element.arguments +=
JKAnnotationParameterImpl(JKKtLiteralExpressionImpl("\"\"", JKLiteralExpression.LiteralType.STRING))
}
if (element.classSymbol.fqName == "java.lang.annotation.Target") {
element.classSymbol = context.symbolProvider.provideByFqName("kotlin.annotation.Target")
val arguments = element.arguments.singleOrNull()?.let { parameter ->
val value = parameter.value
when (value) {
is JKKtAnnotationArrayInitializerExpression -> value.initializers
else -> listOf(value)
}
}
if (arguments != null) {
val newArguments =
arguments.flatMap { value ->
value.fieldAccessFqName()
?.let { targetMappings[it] }
?.map { fqName ->
JKFieldAccessExpressionImpl(context.symbolProvider.provideByFqName(fqName))
} ?: listOf(value)
}
element.arguments = newArguments.map { JKAnnotationParameterImpl(it) }
}
}
return recurse(element)
}
private fun JKAnnotationMemberValue.fieldAccessFqName(): String? =
(safeAs<JKQualifiedExpression>()?.selector ?: this)
.safeAs<JKFieldAccessExpression>()
?.identifier
?.fqName
companion object {
private val targetMappings =
listOf(
"ANNOTATION_TYPE" to listOf("ANNOTATION_CLASS"),
"CONSTRUCTOR" to listOf("CONSTRUCTOR"),
"FIELD" to listOf("FIELD"),
"LOCAL_VARIABLE" to listOf("LOCAL_VARIABLE"),
"METHOD" to listOf("FUNCTION", "PROPERTY_GETTER", "PROPERTY_SETTER"),
"PACKAGE" to listOf("FILE"),
"PARAMETER" to listOf("VALUE_PARAMETER"),
"TYPE_PARAMETER" to listOf("TYPE_PARAMETER"),
"TYPE" to listOf("ANNOTATION_CLASS", "CLASS"),
"TYPE_USE" to listOf("TYPE_USE")
).map { (java, kotlins) ->
"java.lang.annotation.ElementType.$java" to kotlins.map { "kotlin.annotation.AnnotationTarget.$it" }
}.toMap()
}
}
@@ -1,70 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.throwAnnotation
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.JKKtFunctionImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKTypeElementImpl
import org.jetbrains.kotlin.j2k.tree.impl.psi
class JavaMethodToKotlinFunctionConversion(private val context: ConversionContext) : TransformerBasedConversion() {
override fun visitTreeElement(element: JKTreeElement) {
element.acceptChildren(this, null)
}
override fun visitClassBody(classBody: JKClassBody) {
somethingChanged = true
classBody.declarations = classBody.declarations.map { declaration ->
if (declaration is JKJavaMethod) {
declaration.invalidate()
JKKtFunctionImpl(
if (declaration.returnType.type.nullability != Nullability.NotNull)
JKTypeElementImpl(
declaration.returnType.type
.updateNullability(declaration.returnTypeNullability(context))
) else declaration.returnType,
declaration.name,
declaration.parameters,
declaration.block,
declaration.typeParameterList,
declaration.annotationList.also {
if (declaration.throwsList.isNotEmpty()) {
it.annotations +=
throwAnnotation(
declaration.throwsList.map { it.type.updateNullabilityRecursively(Nullability.NotNull) },
context.symbolProvider
)
}
},
declaration.extraModifiers,
declaration.visibility,
declaration.modality
).also {
it.psi = declaration.psi
}
} else {
declaration
}
}
classBody.acceptChildren(this)
}
}
@@ -1,55 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.annotationByFqName
import org.jetbrains.kotlin.j2k.jvmAnnotation
import org.jetbrains.kotlin.j2k.tree.*
class JavaModifiersConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element is JKVisibilityOwner) {
if (element.visibility == Visibility.PACKAGE_PRIVATE) {
if (element is JKClass && element.isLocalClass()) {
element.visibility = Visibility.PUBLIC
} else {
element.visibility = Visibility.INTERNAL
}
}
}
if (element is JKModalityOwner && element is JKAnnotationListOwner) {
val overrideAnnotation = element.annotationList.annotationByFqName("java.lang.Override")
if (overrideAnnotation != null) {
element.annotationList.annotations -= overrideAnnotation
//TODO change modality to OVERRIDE???
}
}
if (element is JKExtraModifiersOwner && element is JKAnnotationListOwner) {
if (ExtraModifier.VOLATILE in element.extraModifiers) {
element.extraModifiers -= ExtraModifier.VOLATILE
element.annotationList.annotations += jvmAnnotation("Volatile", context.symbolProvider)
}
if (ExtraModifier.TRANSIENT in element.extraModifiers) {
element.extraModifiers -= ExtraModifier.TRANSIENT
element.annotationList.annotations += jvmAnnotation("Transient", context.symbolProvider)
}
if (ExtraModifier.STRICTFP in element.extraModifiers) {
element.extraModifiers -= ExtraModifier.STRICTFP
element.annotationList.annotations += jvmAnnotation("Strictfp", context.symbolProvider)
}
if (ExtraModifier.SYNCHRONIZED in element.extraModifiers) {
element.extraModifiers -= ExtraModifier.SYNCHRONIZED
element.annotationList.annotations += jvmAnnotation("Synchronized", context.symbolProvider)
}
if (ExtraModifier.NATIVE in element.extraModifiers) {
element.extraModifiers -= ExtraModifier.NATIVE
element.extraModifiers += ExtraModifier.EXTERNAL
}
}
return recurse(element)
}
}
@@ -1,65 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class JavaStandartMethodsConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKClass) return recurse(element)
for (declaration in element.classBody.declarations) {
if (declaration !is JKJavaMethodImpl) continue
if (fixToStringMethod(declaration)) continue
if (fixFinalizeMethod(declaration, element)) continue
if (fixCloneMethod(declaration)) {
element.inheritance.implements +=
JKTypeElementImpl(
JKClassTypeImpl(
JKUnresolvedClassSymbol("Cloneable"),
emptyList(), Nullability.NotNull
)
)
continue
}
}
return recurse(element)
}
private fun fixToStringMethod(method: JKJavaMethodImpl): Boolean {
if (method.name.value != "toString") return false
if (method.parameters.isNotEmpty()) return false
val type = (method.returnType.type as? JKClassType)
?.takeIf { it.classReference.name == "String" }
?.updateNullability(Nullability.NotNull) ?: return false
method.returnType = JKTypeElementImpl(type)
return true
}
private fun fixCloneMethod(method: JKJavaMethodImpl): Boolean {
if (method.name.value != "clone") return false
if (method.parameters.isNotEmpty()) return false
val type = (method.returnType.type as? JKClassType)
?.takeIf { it.classReference.name == "Object" }
?.updateNullability(Nullability.NotNull) ?: return false
method.returnType = JKTypeElementImpl(type)
return true
}
private fun fixFinalizeMethod(method: JKJavaMethodImpl, containingClass: JKClass): Boolean {
if (method.name.value != "finalize") return false
if (method.parameters.isNotEmpty()) return false
if (method.returnType.type != JKJavaVoidType) return false
if (method.modality == Modality.OVERRIDE) {
method.modality =
if (containingClass.modality == Modality.OPEN) Modality.OPEN
else Modality.FINAL
}
return true
}
}
@@ -1,53 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.JKTypeElementImpl
class JetbrainsNullableAnnotationsConverter(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKAnnotationListOwner) return recurse(element)
val nullableAnnotationSymbol =
context.symbolProvider.provideByFqName("org.jetbrains.annotations.Nullable")
val notNullAnnotationSymbol =
context.symbolProvider.provideByFqName("org.jetbrains.annotations.NotNull")
val nullableAnnotation =
element.annotationList.annotations.firstOrNull { it.classSymbol == nullableAnnotationSymbol }
val notNullAnnotation =
element.annotationList.annotations.firstOrNull { it.classSymbol == notNullAnnotationSymbol }
when (element) {
is JKField -> {
if (nullableAnnotation != null) {
element.annotationList.annotations -= nullableAnnotation
element.type =
JKTypeElementImpl(element.type.type.updateNullability(Nullability.Nullable))
}
if (notNullAnnotation != null) {
element.annotationList.annotations -= notNullAnnotation
element.type =
JKTypeElementImpl(element.type.type.updateNullability(Nullability.NotNull))
}
}
is JKMethod -> {
if (nullableAnnotation != null) {
element.annotationList.annotations -= nullableAnnotation
element.returnType =
JKTypeElementImpl(element.returnType.type.updateNullability(Nullability.Nullable))
}
if (notNullAnnotation != null) {
element.annotationList.annotations -= notNullAnnotation
element.returnType =
JKTypeElementImpl(element.returnType.type.updateNullability(Nullability.NotNull))
}
}
}
return recurse(element)
}
}
@@ -1,27 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.blockStatement
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class LabeledStatementConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKLabeledStatement) return recurse(element)
val statement = element.statement as? JKKtConvertedFromForLoopSyntheticWhileStatementImpl ?: return recurse(element)
return recurse(
JKBlockStatementWithoutBracketsImpl(
JKBlockImpl(
statement::variableDeclaration.detached(),
JKLabeledStatementImpl(statement::whileStatement.detached(), element::labels.detached())
)
)
)
}
}
@@ -1,17 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.fixLiteral
import org.jetbrains.kotlin.j2k.tree.JKJavaLiteralExpression
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
class LiteralConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKJavaLiteralExpression) return recurse(element)
return element.fixLiteral(element.type)
}
}
@@ -1,56 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.JKFieldSymbol
import org.jetbrains.kotlin.j2k.tree.impl.JKTypeElementImpl
class LowerNullabilityInFunctionParametersConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKMethod) return recurse(element)
val scopes =
listOfNotNull(
element.block,
(element as? JKKtConstructor)?.delegationCall
) + element.parameters.mapNotNull {
if (it.initializer !is JKStubExpression) it.initializer else null
}
for (parameter in element.parameters) {
if (parameter.type.type.nullability != Nullability.Default) continue
if (parameter.hasNotNullUsages(scopes)) {
parameter.type = JKTypeElementImpl(parameter.type.type.updateNullability(Nullability.NotNull))
}
}
return recurse(element)
}
private fun JKParameter.hasNotNullUsages(scopes: List<JKTreeElement>): Boolean =
scopes.any {
val searcher = HasNotNullUsagesSearcher(context.symbolProvider.provideUniverseSymbol(this))
scopes.any { searcher.runConversion(it, context) }
searcher.found
}
private inner class HasNotNullUsagesSearcher(private val parameterSymbol: JKFieldSymbol) : RecursiveApplicableConversionBase() {
var found: Boolean = false
override fun applyToElement(element: JKTreeElement): JKTreeElement {
when (element) {
is JKQualifiedExpression -> {
val receiver = element.receiver as? JKFieldAccessExpression ?: return recurse(element)
if (receiver.identifier == parameterSymbol) {
found = true
return element
}
}
}
return recurse(element)
}
}
}
@@ -1,44 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.util.collectionUtils.concatInOrder
//TODO temporary
class MainFunctionConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKMethod) return recurse(element)
if (element.isMainFunctionDeclaration()) {
element.parameters.single().apply {
val oldType = type.type as JKJavaArrayType
val oldTypeParameter = oldType.type as JKClassType
val newType =
JKJavaArrayTypeImpl(
oldTypeParameter.updateNullability(Nullability.NotNull),
Nullability.NotNull
)
type = JKTypeElementImpl(newType)
}
element.annotationList.annotations +=
JKAnnotationImpl(
context.symbolProvider.provideByFqName("kotlin.jvm.JvmStatic"),
emptyList()
)
}
return recurse(element)
}
private fun JKMethod.isMainFunctionDeclaration(): Boolean {
val type = parameters.singleOrNull()?.type?.type as? JKJavaArrayType ?: return false
val typeArgument = type.type as? JKClassType ?: return false
return name.value == "main" && typeArgument.classReference.name == "String"
}
}
@@ -1,45 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
import org.jetbrains.kotlin.j2k.tree.impl.JKBranchElementBase
abstract class MatchBasedConversion : SequentialBaseConversion {
fun <R : JKTreeElement, T> applyRecursive(element: R, data: T, func: (JKTreeElement, T) -> JKTreeElement): R =
org.jetbrains.kotlin.j2k.tree.applyRecursive(element, data, ::onElementChanged, func)
inline fun <R : JKTreeElement> applyRecursive(element: R, crossinline func: (JKTreeElement) -> JKTreeElement): R {
return applyRecursive(element, null) { it, _ -> func(it) }
}
private inline fun <T> applyRecursiveToList(
element: JKTreeElement,
child: List<JKTreeElement>,
iter: MutableListIterator<Any>,
data: T,
func: (JKTreeElement, T) -> JKTreeElement
): List<JKTreeElement> {
val newChild = child.map {
func(it, data)
}
child.forEach { it.detach(element) }
iter.set(child)
newChild.forEach { it.attach(element) }
newChild.zip(child).forEach { (old, new) ->
if (old !== new) {
onElementChanged(new, old)
}
}
return newChild
}
abstract fun onElementChanged(new: JKTreeElement, old: JKTreeElement)
}
@@ -1,52 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.psi
class ModalityConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
when (element) {
is JKClass -> processClass(element)
is JKJavaMethod -> processMethod(element)
}
return recurse(element)
}
private fun processClass(klass: JKClass) {
klass.modality = when {
klass.classKind == JKClass.ClassKind.ENUM -> Modality.FINAL
klass.modality == Modality.OPEN
&& context.converter.settings.openByDefault -> Modality.OPEN
klass.modality == Modality.OPEN
&& context.converter.settings.openByDefault -> Modality.OPEN
klass.modality == Modality.OPEN
&& !context.converter.converterServices.oldServices.referenceSearcher.hasInheritors(klass.psi as PsiClass) ->
Modality.FINAL
else -> klass.modality
}
}
private fun processMethod(method: JKJavaMethod) {
val psi = method.psi<PsiMethod>()!!
method.modality = when {
method.modality != Modality.ABSTRACT
&& (method.psi!! as PsiMethod).findSuperMethods().isNotEmpty() -> Modality.OVERRIDE
method.modality == Modality.OPEN
&& context.converter.settings.openByDefault
&& method.visibility != Visibility.PRIVATE -> Modality.OPEN
method.modality == Modality.OPEN
&& !context.converter.converterServices.oldServices.referenceSearcher.hasOverrides(psi) -> Modality.FINAL
else -> method.modality
}
}
}
@@ -1,41 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.bangedBangedExpr
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class NullableQualifierConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKQualifiedExpression) return recurse(element)
if (element.isSystemCall()) return recurse(element)// we don't want to have `System.err!!.println()` like expressions :)
if (element.receiver.type(context.symbolProvider)?.nullability in listOf(Nullability.Nullable, Nullability.Default)
&& element.operator == JKJavaQualifierImpl.DOT || element.operator == JKKtQualifierImpl.DOT
) {
return recurse(
JKQualifiedExpressionImpl(
element::receiver.detached().bangedBangedExpr(context.symbolProvider),
element.operator,
element::selector.detached()
)
)
}
return recurse(element)
}
private fun JKQualifiedExpression.isSystemCall(): Boolean {
val deepestQualifiedExpression = generateSequence(this) { expression ->
expression.receiver as? JKQualifiedExpression
}.last()
return (deepestQualifiedExpression.receiver as? JKClassAccessExpression)
?.identifier
?.fqName
?.startsWith("java.") == true
}
}
@@ -1,78 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import com.intellij.psi.JavaTokenType
import org.jetbrains.kotlin.j2k.*
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.lexer.KtTokens
class OperatorExpressionConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKOperatorExpression) return recurse(element)
val operator = element.operator as? JKJavaOperatorImpl ?: return recurse(element)
return when (element) {
is JKBinaryExpression -> {
val operatorToken = operator.token.toKtToken()
val left = applyToElement(element::left.detached()) as JKExpression
val right = applyToElement(element::right.detached()) as JKExpression
recurse(convertBinaryExpression(left, right, operatorToken))
}
is JKPrefixExpression -> {
val operand = applyToElement(element::expression.detached()) as JKExpression
recurse(convertPrefixExpression(operand, operator))
}
is JKPostfixExpression -> {
val operatorToken = operator.token.toKtToken()
val operand = applyToElement(element::expression.detached()) as JKExpression
recurse(kotlinPostfixExpression(operand, operatorToken, context.symbolProvider))
}
else -> TODO(element.javaClass.toString())
} ?: recurse(element)
}
private fun convertPrefixExpression(operand: JKExpression, javaOperator: JKJavaOperatorImpl) =
convertTildeExpression(operand, javaOperator)
?: kotlinPrefixExpression(operand, javaOperator.token.toKtToken(), context.symbolProvider)
private fun convertTildeExpression(operand: JKExpression, javaOperator: JKJavaOperatorImpl): JKExpression? =
if (javaOperator.token.psiToken == JavaTokenType.TILDE) {
val invCall =
JKKtCallExpressionImpl(
context.symbolProvider.provideByFqName("kotlin.Int.inv"),//TODO check if Long
JKExpressionListImpl()
)
JKQualifiedExpressionImpl(
JKParenthesizedExpressionImpl(operand),
JKKtQualifierImpl.DOT,
invCall
)
} else null
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
}
@@ -1,33 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.asAssignmentFromTarget
import org.jetbrains.kotlin.j2k.findUsages
import org.jetbrains.kotlin.j2k.hasWritableUsages
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class ParameterModificationInMethodCallsConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKMethod) return recurse(element)
val newVariables =
element.parameters.mapNotNull { parameter ->
if (parameter.hasWritableUsages(element.block, context)) {
JKLocalVariableImpl(
JKTypeElementImpl(parameter.type.type),
JKNameIdentifierImpl(parameter.name.value),
JKFieldAccessExpressionImpl(context.symbolProvider.provideUniverseSymbol(parameter)),
Mutability.MUTABLE
)
} else null
}
element.block.statements = listOf(JKDeclarationStatementImpl(newVariables)) + element.block.statements
return recurse(element)
}
}
@@ -1,42 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.kotlinBinaryExpression
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 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 {
return if (operators.isEmpty())
operands.first()
else {
val operator = operators.maxBy { it.precedence }
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))
JKBinaryExpressionImpl(left, right, operator)
}
}
}
@@ -1,68 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.JKKtInitDeclarationImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKKtPrimaryConstructorImpl
class PrimaryConstructorDetectConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element is JKClass &&
(element.classKind == JKClass.ClassKind.CLASS || element.classKind == JKClass.ClassKind.ENUM)
) {
processClass(element)
}
return recurse(element)
}
private fun <T> List<T>.replace(element: T, replacer: T): List<T> {
val mutableList = toMutableList()
val index = indexOf(element)
mutableList[index] = replacer
return mutableList
}
private fun processClass(element: JKClass) {
val constructors = element.declarationList.filterIsInstance<JKKtConstructor>()
if (constructors.any { it is JKKtPrimaryConstructor }) return
val primaryConstructorCandidate = detectPrimaryConstructor(constructors) ?: return
val delegationCall = primaryConstructorCandidate.delegationCall as? JKDelegationConstructorCall
if (delegationCall?.expression is JKThisExpression) return
primaryConstructorCandidate.invalidate()
if (primaryConstructorCandidate.block.statements.isNotEmpty()) {
val initDeclaration = JKKtInitDeclarationImpl(primaryConstructorCandidate.block)
element.classBody.declarations =
element.classBody.declarations.replace(primaryConstructorCandidate, initDeclaration)
} else {
element.classBody.declarations -= primaryConstructorCandidate
}
val primaryConstructor =
JKKtPrimaryConstructorImpl(
primaryConstructorCandidate.name,
primaryConstructorCandidate.parameters,
primaryConstructorCandidate.delegationCall,
primaryConstructorCandidate.annotationList,
primaryConstructorCandidate.extraModifiers,
primaryConstructorCandidate.visibility,
primaryConstructorCandidate.modality
)
context.symbolProvider.transferSymbol(primaryConstructor, primaryConstructorCandidate)
element.classBody.declarations += primaryConstructor
}
private fun detectPrimaryConstructor(constructors: List<JKKtConstructor>): JKKtConstructor? {
val constructorsWithoutOtherConstructorCall =
constructors.filterNot { (it.delegationCall as? JKDelegationConstructorCall)?.expression is JKThisExpression }
return constructorsWithoutOtherConstructorCall.singleOrNull()
}
}
@@ -1,47 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.JKKtCallExpressionImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKMethodSymbol
import org.jetbrains.kotlin.j2k.tree.impl.psi
import org.jetbrains.kotlin.name.ClassId
// TODO: Full special methods conversion
class PrintlnConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
return if (element is JKQualifiedExpression) {
recurse(processQualified(element))
} else {
recurse(element)
}
}
private fun processQualified(element: JKQualifiedExpression): JKExpression {
val receiver = element.receiver as? JKQualifiedExpression ?: return element
val classReference = receiver.receiver as? JKClassAccessExpression ?: return element
if (classReference.identifier.fqName != "java.lang.System") return element
val fieldReference = receiver.selector as? JKFieldAccessExpression ?: return element
if (fieldReference.identifier.name != "out") return element
val selector = element.selector as? JKMethodCallExpression ?: return element
val functionName = selector.identifier.name
if (functionName != "println" && functionName != "print") return element
val contextElement = element.parentOfType<JKClass>() ?: return element
val targetElements = multiResolveFqName(ClassId.fromString("kotlin/io/$functionName"), contextElement.psi!!)
if (targetElements.isEmpty()) return element
selector.invalidate()
return JKKtCallExpressionImpl(
context.symbolProvider.provideDirectSymbol(targetElements.first()) as JKMethodSymbol,
selector.arguments
)
}
}
@@ -1,29 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
abstract class RecursiveApplicableConversionBase : MatchBasedConversion() {
override fun onElementChanged(new: JKTreeElement, old: JKTreeElement) {
somethingChanged = true
}
override fun runConversion(treeRoot: JKTreeElement, context: ConversionContext): Boolean {
val root = applyToElement(treeRoot)
assert(root === treeRoot)
return somethingChanged
}
protected var somethingChanged = false
abstract fun applyToElement(element: JKTreeElement): JKTreeElement
inline fun <T : JKTreeElement> recurse(element: T): T {
return applyRecursive(element, ::applyToElement)
}
}
@@ -1,18 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.tree.*
//TODO temporary
class SortClassMembersConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKClass) return recurse(element)
element.classBody.declarations = element.declarationList
.sortedByDescending { it is JKVariable }
return recurse(element)
}
}
@@ -1,30 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.getOrCreateCompainonObject
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class StaticsToCompanionExtractConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKClass) return recurse(element)
if (element.classKind == JKClass.ClassKind.COMPANION || element.classKind == JKClass.ClassKind.OBJECT) return element
val statics = element.declarationList.filter { declaration ->
declaration is JKExtraModifiersOwner &&
declaration.extraModifiers.any { it == ExtraModifier.STATIC }
}
if (statics.isEmpty()) return recurse(element)
val companion = element.getOrCreateCompainonObject()
element.classBody.declarations -= statics
companion.classBody.declarations += statics.onEach { declaration ->
(declaration as JKExtraModifiersOwner)
declaration.extraModifiers -= ExtraModifier.STATIC
}
return recurse(element)
}
}
@@ -1,133 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import com.intellij.psi.PsiElement
import com.intellij.psi.controlFlow.ControlFlowFactory
import com.intellij.psi.controlFlow.ControlFlowUtil
import com.intellij.psi.controlFlow.LocalsOrMyInstanceFieldsControlFlowPolicy
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.blockStatement
import org.jetbrains.kotlin.j2k.copyTreeAndDetach
import org.jetbrains.kotlin.j2k.runExpression
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class SwitchStatementConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKJavaSwitchStatementImpl) return recurse(element)
element.invalidate()
element.cases.forEach { case ->
case.statements.forEach { it.detach(case) }
if (case is JKJavaLabelSwitchCase) {
case.label.detach(case)
}
}
val cases = switchCasesToWhenCases(element.cases).moveElseCaseToTheEnd()
val whenStatement = JKKtWhenStatementImpl(element.expression, cases)
return recurse(whenStatement)
}
private fun List<JKKtWhenCase>.moveElseCaseToTheEnd(): List<JKKtWhenCase> =
sortedBy { it.labels.any { it is JKKtElseWhenLabel } }
private fun switchCasesToWhenCases(cases: List<JKJavaSwitchCase>): List<JKKtWhenCase> =
if (cases.isEmpty()) emptyList()
else {
val statements = cases
.takeWhileInclusive { it.statements.fallsThrough() }
.flatMap { it.statements }
.takeWhileInclusive { it.singleListOrBlockStatements().none { isSwitchBreak(it) } }
.mapNotNull { statement ->
when {
statement is JKBlockStatement ->
blockStatement(
statement.block.statements
.takeWhile { !isSwitchBreak(it) }
.map { it.copyTreeAndDetach() }
)
isSwitchBreak(statement) -> null
else -> statement.copyTreeAndDetach()
}
}
val javaLabels = cases
.takeWhileInclusive { it.statements.isEmpty() }
val statementLabels = javaLabels
.filterIsInstance<JKJavaLabelSwitchCase>()
.map { JKKtValueWhenLabelImpl(it.label) }
val elseLabel = javaLabels
.find { it is JKJavaDefaultSwitchCaseImpl }
?.let { JKKtElseWhenLabelImpl() }
val elseWhenCase = elseLabel?.let { label ->
JKKtWhenCaseImpl(listOf(label), statements.map { it.copyTreeAndDetach() }.singleBlockOrWrapToRun())
}
val mainWhenCase =
if (statementLabels.isNotEmpty()) {
JKKtWhenCaseImpl(statementLabels, statements.singleBlockOrWrapToRun())
} else null
listOfNotNull(mainWhenCase) +
listOfNotNull(elseWhenCase) +
switchCasesToWhenCases(cases.drop(javaLabels.size))
}
private fun <T> List<T>.takeWhileInclusive(predicate: (T) -> Boolean): List<T> =
takeWhile(predicate) + listOfNotNull(find { !predicate(it) })
private fun List<JKStatement>.singleBlockOrWrapToRun(): JKStatement =
singleOrNull()
?: JKBlockStatementImpl(
JKBlockImpl(map { statement ->
when (statement) {
is JKBlockStatement ->
JKExpressionStatementImpl(
runExpression(statement, context.symbolProvider)
)
else -> statement
}
})
)
private fun JKStatement.singleListOrBlockStatements(): List<JKStatement> =
when (this) {
is JKBlockStatement -> block.statements
else -> listOf(this)
}
private fun isSwitchBreak(statement: JKStatement) =
statement is JKBreakStatement && statement !is JKBreakWithLabelStatement
private fun List<JKStatement>.fallsThrough(): Boolean =
all { it.fallsThrough() }
private fun JKStatement.fallsThrough(): Boolean =
when {
this.isThrowStatement() ||
this is JKBreakStatement ||
this is JKReturnStatement ||
this is JKContinueStatement -> false
this is JKBlockStatement -> block.statements.fallsThrough()
this is JKIfStatement ||
this is JKJavaSwitchStatement ||
this is JKKtWhenStatement ->
this.psi!!.canCompleteNormally()
else -> true
}
private fun JKStatement.isThrowStatement(): Boolean =
(this as? JKExpressionStatement)?.expression is JKKtThrowExpression
private fun PsiElement.canCompleteNormally(): Boolean {
val controlFlow =
ControlFlowFactory.getInstance(project).getControlFlow(this, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance())
val startOffset = controlFlow.getStartOffset(this)
val endOffset = controlFlow.getEndOffset(this)
return startOffset == -1 || endOffset == -1 || ControlFlowUtil.canCompleteNormally(controlFlow, startOffset, endOffset)
}
}
@@ -1,32 +0,0 @@
/*
* 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.conversions
import org.jetbrains.kotlin.j2k.*
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class SynchronizedStatementConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKJavaSynchronizedStatement) return recurse(element)
element.invalidate()
val lambdaBody = JKLambdaExpressionImpl(
JKBlockStatementImpl(element.body),
emptyList()
)
val synchronizedCall =
JKKtCallExpressionImpl(
context.symbolProvider.provideByFqNameMulti("kotlin.synchronized"),
JKExpressionListImpl(
element.lockExpression,
lambdaBody
)
)
return recurse(JKExpressionStatementImpl(synchronizedCall))
}
}
@@ -1,22 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.tree.JKExpressionStatement
import org.jetbrains.kotlin.j2k.tree.JKJavaThrowStatement
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
import org.jetbrains.kotlin.j2k.tree.detached
import org.jetbrains.kotlin.j2k.tree.impl.JKExpressionStatementImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKKtThrowExpressionImpl
class ThrowStatementConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKJavaThrowStatement) return recurse(element)
val throwExpression = JKKtThrowExpressionImpl(element::exception.detached())
return recurse(JKExpressionStatementImpl(throwExpression))
}
}
@@ -1,31 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitorVoid
abstract class TransformerBasedConversion : SequentialBaseConversion, JKVisitorVoid {
protected var somethingChanged = false
override fun runConversion(treeRoot: JKTreeElement, context: ConversionContext): Boolean {
somethingChanged = false
treeRoot.accept(this, null)
return somethingChanged
}
}
@@ -1,80 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.*
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class TryStatementConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKJavaTryStatement) return recurse(element)
return if (element.resourceDeclarations.isEmpty())
recurse(convertNoResourcesTryStatement(element))
else recurse(convertTryStatementWithResources(element))
}
private fun convertNoResourcesTryStatement(tryStatement: JKJavaTryStatement): JKStatement =
JKExpressionStatementImpl(
JKKtTryExpressionImpl(
tryStatement::tryBlock.detached(),
tryStatement::finallyBlock.detached(),
tryStatement.catchSections.flatMap(::convertCatchSection)
)
)
private fun convertTryStatementWithResources(tryStatement: JKJavaTryStatement): JKStatement {
val body =
resourceDeclarationsToUseExpression(
tryStatement.resourceDeclarations,
JKBlockStatementImpl(tryStatement::tryBlock.detached())
)
return if (tryStatement.finallyBlock !is JKBodyStub || tryStatement.catchSections.isNotEmpty()) {
JKExpressionStatementImpl(
JKKtTryExpressionImpl(
JKBlockImpl(listOf(body)),
tryStatement::finallyBlock.detached(),
tryStatement.catchSections.flatMap(::convertCatchSection)
)
)
} else body
}
private fun resourceDeclarationsToUseExpression(
resourceDeclarations: List<JKDeclaration>,
innerStatement: JKStatement
): JKStatement =
resourceDeclarations
.reversed()
.fold(innerStatement) { inner, variable ->
JKExpressionStatementImpl(
useExpression(
receiver = (variable as JKLocalVariable)::initializer.detached(),
variableIdentifier = variable::name.detached(),
body = inner,
symbolProvider = context.symbolProvider
)
)
}
private fun convertCatchSection(javaCatchSection: JKJavaTryCatchSection): List<JKKtTryCatchSection> {
javaCatchSection.block.detach(javaCatchSection)
return javaCatchSection.parameter.type.type.let {
(it as? JKJavaDisjunctionType)?.disjunctions ?: listOf(it)
}.map {
val parameter = JKParameterImpl(
JKTypeElementImpl(it.updateNullability(Nullability.NotNull)),
javaCatchSection.parameter.name.copyTreeAndDetach()
)
JKKtTryCatchSectionImpl(
parameter,
javaCatchSection.block.copyTreeAndDetach()
)
}
}
}
@@ -1,192 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiVariable
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.j2k.*
import org.jetbrains.kotlin.j2k.ast.Mutability
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
class TypeMappingConversion(val context: ConversionContext) : RecursiveApplicableConversionBase() {
private val typeFlavorCalculator = TypeFlavorCalculator(object : TypeFlavorConverterFacade {
override val referenceSearcher: ReferenceSearcher
get() = context.converter.converterServices.oldServices.referenceSearcher
override val javaDataFlowAnalyzerFacade: JavaDataFlowAnalyzerFacade
get() = context.converter.converterServices.oldServices.javaDataFlowAnalyzerFacade
override val resolverForConverter: ResolverForConverter
get() = context.converter.converterServices.oldServices.resolverForConverter
override fun inConversionScope(element: PsiElement): Boolean = context.inConversionContext(element)
})
override fun applyToElement(element: JKTreeElement): JKTreeElement {
return when (element) {
is JKTypeElement -> {
val newType = element.type
.fixRawType(element)
.mapType(element)
.refineNullability(element)
JKTypeElementImpl(newType)
}
is JKJavaNewExpression -> {
val newClassSymbol = element.classSymbol.mapClassSymbol(null)
recurse(
JKJavaNewExpressionImpl(
newClassSymbol,
element::arguments.detached(),
element::typeArgumentList.detached().fixTypeArguments(newClassSymbol),
element::classBody.detached()
)
)
}
else -> recurse(element)
}
}
private fun JKTypeArgumentList.fixTypeArguments(classSymbol: JKClassSymbol): JKTypeArgumentList {
if (typeArguments.isNotEmpty()) {
return JKTypeArgumentListImpl(
typeArguments.map { typeArgument ->
JKTypeElementImpl(typeArgument.type.mapType(null))
}
)
}
val typeParametersCount = classSymbol.expectedTypeParametersCount()
return when (typeParametersCount) {
0 -> this
else -> JKTypeArgumentListImpl(List(typeParametersCount) {
JKTypeElementImpl(
kotlinTypeByName(
KotlinBuiltIns.FQ_NAMES.any.toSafe().asString(),
context.symbolProvider,
Nullability.Nullable
)
)
})
}
}
private fun JKType.refineNullability(typeElement: JKTypeElement): JKType {
if (nullability == Nullability.Default && this is JKClassType) {
val newNullability = calculateNullability(typeElement)
if (newNullability != nullability) {
return JKClassTypeImpl(classReference, parameters, newNullability)
}
}
return this
}
private fun JKType.fixRawType(typeElement: JKTypeElement) =
when (typeElement.parent) {
is JKKtIsExpression ->
addTypeParametersToRawProjectionType(JKStarProjectionTypeImpl())
.updateNullability(Nullability.NotNull)
is JKTypeCastExpression ->
addTypeParametersToRawProjectionType(JKStarProjectionTypeImpl())
else ->
addTypeParametersToRawProjectionType(
JKStarProjectionTypeImpl()
)
}
private fun JKType.mapType(typeElement: JKTypeElement?): JKType =
when (this) {
is JKJavaPrimitiveType -> mapPrimitiveType()
is JKClassType -> mapClassType(typeElement)
is JKJavaVoidType ->
kotlinTypeByName(
KotlinBuiltIns.FQ_NAMES.unit.toSafe().asString(),
context.symbolProvider,
Nullability.NotNull
)
is JKJavaArrayType ->
JKClassTypeImpl(
context.symbolProvider.provideByFqName(type.arrayFqName()),
if (type is JKJavaPrimitiveType) emptyList() else listOf(type.mapType(typeElement)),
type.nullability
)
else -> this
}
private fun JKClassSymbol.mapClassSymbol(typeElement: JKTypeElement?): JKClassSymbol {
if (this is JKUniverseClassSymbol) return this
val newFqName = typeElement?.let { kotlinCollectionClassName(it) }
?: kotlinStandardType()
?: fqName
?: return this
return context.symbolProvider.provideByFqName(newFqName)
}
private fun JKClassType.mapClassType(typeElement: JKTypeElement?): JKClassType =
JKClassTypeImpl(
classReference.mapClassSymbol(typeElement),
parameters.map { it.mapType(null) },
nullability
)
private fun JKClassSymbol.kotlinCollectionClassName(typeElement: JKTypeElement?): String? {
val isStructureMutable = calculateStructureMutability(typeElement)
return if (isStructureMutable) toKotlinMutableTypesMap[fqName]
else toKotlinTypesMap[fqName]
}
private fun JKClassSymbol.kotlinStandardType(): String? =
fqName?.let {
JavaToKotlinClassMap.mapJavaToKotlin(FqName(it))?.asString()
}
private fun JKJavaPrimitiveType.mapPrimitiveType(): JKClassType {
val fqName = jvmPrimitiveType.primitiveType.typeFqName
return JKClassTypeImpl(
context.symbolProvider.provideByFqName(ClassId.topLevel(fqName)),
nullability = Nullability.NotNull
)
}
private fun calculateNullability(typeElement: JKTypeElement?): Nullability {
val parent = typeElement?.parent ?: return Nullability.Default
val psi = parent.psi
return when (parent) {
is JKMethod ->
parent.nullabilityBySuperMethod(context.symbolProvider).defaultToNull()
?: psi?.let { typeFlavorCalculator.methodNullability(it as PsiMethod) }
.nullToDefault()
is JKVariable -> psi?.let {
typeFlavorCalculator.variableNullability(psi as PsiVariable)
}.nullToDefault()
else -> Nullability.Default
}
}
private fun Nullability.defaultToNull() =
if (this == Nullability.Default) null else this
private fun Nullability?.nullToDefault() =
this ?: Nullability.Default
private fun calculateStructureMutability(typeElement: JKTypeElement?): Boolean {
val parent = typeElement?.parent ?: return false
val psi = parent.psi ?: return false
return when (parent) {
is JKVariable -> typeFlavorCalculator.variableMutability(psi as PsiVariable) == Mutability.Mutable
is JKMethod -> typeFlavorCalculator.methodMutability(psi as PsiMethod) == Mutability.Mutable
else -> false
}
}
}
@@ -1,63 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class TypeParametersNullabilityConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKTypeParameterList) return recurse(element)
val typeParametersNullabilityMap =
element.typeParameters.map { typeParameter ->
typeParameter.name.value to typeParameter.hasNullableUpperBounds()
}.toMap()
return JKTypeParameterListImpl(
element.typeParameters.map { typeParameter ->
val name = typeParameter.name.value
JKTypeParameterImpl(
JKNameIdentifierImpl(name),
typeParameter.upperBounds.map { upperBoundTypeElement ->
JKTypeElementImpl(
upperBoundTypeElement.type.makeTypeParametersNotNull(typeParametersNullabilityMap)
)
}
)
}
)
}
private fun JKType.makeTypeParametersNotNull(nullabilityMap: Map<String, Boolean>): JKType =
when (this) {
is JKClassType ->
JKClassTypeImpl(
classReference,
parameters.map { it.makeTypeParametersNotNull(nullabilityMap) },
nullability
)
is JKTypeParameterType ->
nullabilityMap[name]
?.takeIf { nullability == Nullability.Default }
?.let { isNullable ->
JKTypeParameterTypeImpl(
name,
if (isNullable) Nullability.NotNull else Nullability.Nullable
)
} ?: this
is JKVarianceTypeParameterType ->
JKVarianceTypeParameterTypeImpl(
variance,
boundType.makeTypeParametersNotNull(nullabilityMap)
)
else -> this
}
private fun JKTypeParameter.hasNullableUpperBounds(): Boolean =
upperBounds.any { it.type.isNullable() }
}
@@ -1,49 +0,0 @@
/*
* Copyright 2010-2018 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.conversions
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiPolyVariantReference
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
import org.jetbrains.kotlin.j2k.tree.impl.psi
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
import org.jetbrains.kotlin.psi.KtImportDirective
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.analysisContext
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
import org.jetbrains.kotlin.resolve.ImportPath
internal fun resolveFqName(classId: ClassId, contextElement: JKTreeElement, context: ConversionContext): PsiElement? {
val element = contextElement.psi ?: return null
return resolveFqName(classId, element)
}
fun resolveFqName(classId: ClassId, element: PsiElement): PsiElement? {
return constructImportDirectiveWithContext(classId, element)
.getChildOfType<KtDotQualifiedExpression>()
?.selectorExpression
?.let {
it.references.mapNotNull { it.resolve() }.firstOrNull()
}
}
private fun constructImportDirectiveWithContext(classId: ClassId, element: PsiElement): KtImportDirective {
val importDirective = KtPsiFactory(element).createImportDirective(ImportPath(classId.asSingleFqName(), false))
importDirective.containingKtFile.analysisContext = element.containingFile
return importDirective
}
internal fun multiResolveFqName(classId: ClassId, elementForContext: PsiElement): List<PsiElement> {
return constructImportDirectiveWithContext(classId, elementForContext)
.getChildOfType<KtDotQualifiedExpression>()
?.selectorExpression
?.let {
it.references.filterIsInstance<PsiPolyVariantReference>().flatMap { it.multiResolve(false).mapNotNull { it.element } }
}.orEmpty()
}
@@ -1,549 +0,0 @@
/*
* Copyright 2010-2018 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.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
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
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import java.math.BigInteger
fun kotlinTypeByName(name: String, symbolProvider: JKSymbolProvider, nullability: Nullability = Nullability.Nullable): JKClassType =
JKClassTypeImpl(
symbolProvider.provideByFqName(name),
emptyList(),
nullability
)
private fun JKType.classSymbol(symbolProvider: JKSymbolProvider) =
when (this) {
is JKClassType -> classReference
is JKJavaPrimitiveType ->
symbolProvider.provideByFqName(jvmPrimitiveType.primitiveType.typeFqName.asString())
else -> null
}
private fun JKKtOperatorToken.arithmeticMethodType(
leftType: JKType,
rightType: JKType,
symbolProvider: JKSymbolProvider
): JKType? {
fun PsiClass.methodReturnType() =
allMethods
.filter { it.name == operatorName }
.firstOrNull {
it.parameterList.parameters.singleOrNull()?.takeIf { parameter ->
val type = parameter.type.toJK(symbolProvider)
if (type !is JKTypeParameterType) rightType.isSubtypeOf(type, symbolProvider)
else true//TODO check for type bounds
} != null
}?.let { it.returnType?.toJK(symbolProvider) }
val classSymbol =
if (leftType.isStringType()) symbolProvider.provideByFqName(KotlinBuiltIns.FQ_NAMES.string.toSafe())
else leftType.classSymbol(symbolProvider)
return when (classSymbol) {
is JKMultiverseKtClassSymbol ->
classSymbol.target.declarations
.asSequence()
.filterIsInstance<KtNamedFunction>()
.filter { it.name == operatorName }
.mapNotNull { symbolProvider.provideDirectSymbol(it) as? JKMethodSymbol }
.firstOrNull { it.parameterTypes?.singleOrNull()?.takeIf { rightType.isSubtypeOf(it, symbolProvider) } != null }
?.returnType
is JKUniverseClassSymbol -> classSymbol.target.psi<PsiClass>()?.methodReturnType()
is JKMultiverseClassSymbol -> classSymbol.target.methodReturnType()
else -> null
}
}
private fun JKKtOperatorToken.unaryExpressionMethodType(
operandType: JKType?,
symbolProvider: JKSymbolProvider
): JKType {
if (operandType is JKNoType) {
return operandType
}
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 { it.typeReference?.toJK(symbolProvider) }
.firstOrNull() ?: TODO(classSymbol::class.toString() + this.operatorName)
null -> TODO(" No class symbol")
else -> TODO(classSymbol::class.toString())
}
}
fun JKOperator.isComparationOperator() =
(token as? JKKtSingleValueOperatorToken)?.psiToken in comparationOperators
fun JKOperator.isEquals() =
(token as? JKKtSingleValueOperatorToken)?.psiToken in equalsOperators
fun JKOperator.isArithmetic() =
(token as? JKKtSingleValueOperatorToken)?.psiToken in arithmeticOperators
fun JKOperator.isLessOrGreater() =
(token as? JKKtSingleValueOperatorToken)?.psiToken in lessGreaterOperators
private val equalsOperators =
TokenSet.create(
KtTokens.EQEQEQ,
KtTokens.EXCLEQEQEQ,
KtTokens.EQEQ,
KtTokens.EXCLEQ
)
private val lessGreaterOperators =
TokenSet.create(
KtTokens.LT,
KtTokens.GT,
KtTokens.LTEQ,
KtTokens.GTEQ
)
private val comparationOperators =
TokenSet.orSet(
lessGreaterOperators,
equalsOperators
)
private val booleanOperators =
TokenSet.orSet(
comparationOperators,
TokenSet.create(
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 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)
val methodSymbol = token.unaryExpressionMethodType(operandType, symbolProvider)
return JKPrefixExpressionImpl(operand, JKKtOperatorImpl(token, methodSymbol))
}
fun kotlinPostfixExpression(
operand: JKExpression,
token: JKKtOperatorToken,
symbolProvider: JKSymbolProvider
): JKPostfixExpression {
val operandType = operand.type(symbolProvider)
val methodSymbol = token.unaryExpressionMethodType(operandType, symbolProvider)
return JKPostfixExpressionImpl(operand, JKKtOperatorImpl(token, methodSymbol))
}
fun untilToExpression(
from: JKExpression,
to: JKExpression,
conversionContext: ConversionContext,
psiContext: PsiElement
): JKExpression =
rangeExpression(
from,
to,
"until",
conversionContext,
psiContext
)
fun downToExpression(
from: JKExpression,
to: JKExpression,
conversionContext: ConversionContext,
psiContext: PsiElement
): JKExpression =
rangeExpression(
from,
to,
"downTo",
conversionContext,
psiContext
)
fun List<JKExpression>.toExpressionList() =
JKExpressionListImpl(this)
fun JKExpression.parenthesizeIfBinaryExpression() =
when (this) {
is JKBinaryExpression -> JKParenthesizedExpressionImpl(this)
else -> this
}
fun rangeExpression(
from: JKExpression,
to: JKExpression,
operatorName: String,
conversionContext: ConversionContext,
psiContext: PsiElement
): JKExpression {
val returnType = (conversionContext.symbolProvider.provideDirectSymbol(
multiResolveFqName(ClassId.fromString("kotlin/ranges/$operatorName"), psiContext).first()
) as JKMethodSymbol).returnType
return JKBinaryExpressionImpl(from, to, JKKtOperatorImpl(JKKtWordOperatorToken(operatorName), returnType!!))
}
fun blockStatement(vararg statements: JKStatement) =
JKBlockStatementImpl(JKBlockImpl(statements.toList()))
fun blockStatement(statements: List<JKStatement>) =
JKBlockStatementImpl(JKBlockImpl(statements))
fun useExpression(
receiver: JKExpression,
variableIdentifier: JKNameIdentifier,
body: JKStatement,
symbolProvider: JKSymbolProvider
): JKExpression {
val useSymbol = symbolProvider.provideByFqName<JKMethodSymbol>("kotlin.io.use")
val lambdaParameter =
JKParameterImpl(JKTypeElementImpl(JKNoTypeImpl), variableIdentifier)
val lambda = JKLambdaExpressionImpl(
body,
listOf(lambdaParameter)
)
val methodCall =
JKJavaMethodCallExpressionImpl(
useSymbol,
JKExpressionListImpl(listOf(lambda))
)
return JKQualifiedExpressionImpl(receiver, JKKtQualifierImpl.DOT, methodCall)
}
fun kotlinAssert(assertion: JKExpression, message: JKExpression?, symbolProvider: JKSymbolProvider) =
JKKtCallExpressionImpl(
JKUnresolvedMethod(//TODO resolve assert
"assert",
kotlinTypeByName(KotlinBuiltIns.FQ_NAMES.unit.asString(), symbolProvider)
),
JKExpressionListImpl(listOfNotNull(assertion, message))
)
fun jvmAnnotation(name: String, symbolProvider: JKSymbolProvider) =
JKAnnotationImpl(
symbolProvider.provideByFqName("kotlin.annotation.AnnotationTarget.$name")
)
fun throwAnnotation(throws: List<JKType>, symbolProvider: JKSymbolProvider) =
JKAnnotationImpl(
symbolProvider.provideByFqName("kotlin.jvm.Throws"),
throws.map {
JKAnnotationParameterImpl(
JKClassLiteralExpressionImpl(JKTypeElementImpl(it), JKClassLiteralExpression.LiteralType.KOTLIN_CLASS)
)
}
)
fun JKAnnotationList.annotationByFqName(fqName: String): JKAnnotation? =
annotations.firstOrNull { it.classSymbol.fqName == fqName }
fun stringLiteral(content: String, symbolProvider: JKSymbolProvider): JKExpression {
val lines = content.split('\n')
return lines.mapIndexed { i, line ->
val newlineSeparator = if (i == lines.size - 1) "" else "\\n"
JKKtLiteralExpressionImpl("\"$line$newlineSeparator\"", JKLiteralExpression.LiteralType.STRING)
}.reduce { acc: JKExpression, literalExpression: JKKtLiteralExpression ->
kotlinBinaryExpression(acc, literalExpression, JKKtSingleValueOperatorToken(KtTokens.PLUS), symbolProvider)!!
}
}
fun JKVariable.findUsages(scope: JKTreeElement, context: ConversionContext): List<JKFieldAccessExpression> {
val symbol = context.symbolProvider.provideUniverseSymbol(this)
val usages = mutableListOf<JKFieldAccessExpression>()
val searcher = object : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element is JKExpression) {
element.unboxFieldReference()?.also {
if (it.identifier == symbol) {
usages += it
}
}
}
return recurse(element)
}
}
searcher.runConversion(scope, context)
return usages
}
fun JKExpression.unboxFieldReference(): JKFieldAccessExpression? = when {
this is JKFieldAccessExpression -> this
this is JKQualifiedExpression && receiver is JKThisExpression -> selector as? JKFieldAccessExpression
else -> null
}
fun JKFieldAccessExpression.asAssignmentFromTarget(): JKKtAssignmentStatement? =
(parent as? JKKtAssignmentStatement)
?.takeIf { it.field == this }
fun JKFieldAccessExpression.isInDecrementOrIncrement(): Boolean =
(parent as? JKUnaryExpression)?.operator?.token?.text in listOf("++", "--")
fun JKExpression.bangedBangedExpr(symbolProvider: JKSymbolProvider): JKExpression =
JKPostfixExpressionImpl(
this,
JKKtOperatorImpl(KtTokens.EXCLEXCL, type(symbolProvider)!!)
)
fun JKVariable.hasWritableUsages(scope: JKTreeElement, context: ConversionContext): Boolean =
findUsages(scope, context).any {
it.asAssignmentFromTarget() != null
|| it.isInDecrementOrIncrement()
}
fun JKLiteralExpression.fixLiteral(expectedType: JKLiteralExpression.LiteralType): JKLiteralExpression =
when (expectedType) {
JKLiteralExpression.LiteralType.DOUBLE -> convertDoubleLiteral(literal)
JKLiteralExpression.LiteralType.FLOAT -> convertFloatLiteral(literal)
JKLiteralExpression.LiteralType.LONG, JKLiteralExpression.LiteralType.INT -> convertIntegerLiteral(this)
JKLiteralExpression.LiteralType.CHAR -> convertCharLiteral(literal)
JKLiteralExpression.LiteralType.STRING -> convertStringLiteral(literal)
else -> this
}
private fun convertDoubleLiteral(text: String): JKKtLiteralExpression {
var newText =
text.replace("L", "", true)
.replace("d", "", true)
.replace(".e", "e", true)
.replace(".f", "", true)
.replace("f", "", true)
if (!newText.contains(".") && !newText.contains("e", true))
newText += "."
if (newText.endsWith("."))
newText += "0"
return JKKtLiteralExpressionImpl(
newText,
JKLiteralExpression.LiteralType.DOUBLE
)
}
private fun convertFloatLiteral(text: String): JKKtLiteralExpressionImpl {
return JKKtLiteralExpressionImpl(
text.replace("L", "", true)
.replace(".f", "f", true)
.replace("F", "f")
.replace(".e", "e", true)
.let {
if (!it.endsWith("f")) "${it}f"
else it
},
JKLiteralExpression.LiteralType.FLOAT
)
}
private fun convertStringLiteral(text: String): JKKtLiteralExpressionImpl {
var newText = text.replace("((?:\\\\)*)\\\\([0-3]?[0-7]{1,2})".toRegex()) {
val leadingBackslashes = it.groupValues[1]
if (leadingBackslashes.length % 2 == 0) {
String.format("%s\\u%04x", leadingBackslashes, Integer.parseInt(it.groupValues[2], 8))
} else {
it.value
}
}
newText = newText.replace("\\$([A-Za-z]+|\\{)".toRegex(), "\\\\$0")
return JKKtLiteralExpressionImpl(newText, JKLiteralExpression.LiteralType.STRING)
}
private fun convertCharLiteral(text: String): JKKtLiteralExpression {
return JKKtLiteralExpressionImpl(
text.replace("\\\\([0-3]?[0-7]{1,2})".toRegex()) {
String.format("\\u%04x", Integer.parseInt(it.groupValues[1], 8))
},
JKLiteralExpression.LiteralType.CHAR
)
}
private fun convertIntegerLiteral(element: JKLiteralExpression): JKKtLiteralExpression {
var text = element.literal
if (element.type == JKLiteralExpression.LiteralType.LONG) {
text = text.replace("l", "L").let {
if (!it.endsWith("L")) it + "L" else it
}
}
fun isHexLiteral(text: String) = text.startsWith("0x") || text.startsWith("0X")
if ((element.type == JKLiteralExpression.LiteralType.LONG || element.type == JKLiteralExpression.LiteralType.INT) && isHexLiteral(text)) {
val v = BigInteger(text.substring(2).replace("L", ""), 16)
if (text.contains("L")) {
if (v.bitLength() > 63) {
text = "-0x${v.toLong().toString(16).substring(1)}L"
}
} else {
if (v.bitLength() > 31) {
text = "-0x${v.toInt().toString(16).substring(1)}"
}
}
} else if (element.type == JKLiteralExpression.LiteralType.INT) {
text = element.literal
}
return JKKtLiteralExpressionImpl(
text,
element.type
)
}
fun equalsExpression(left: JKExpression, right: JKExpression, symbolProvider: JKSymbolProvider) =
kotlinBinaryExpression(
left,
right,
KtTokens.EQEQ,
symbolProvider
)
fun JKClass.getOrCreateCompainonObject(): JKClass =
(declarationList.firstOrNull { it is JKClass && it.classKind == JKClass.ClassKind.COMPANION } as? JKClass)
?: JKClassImpl(
JKNameIdentifierImpl(""),
JKInheritanceInfoImpl(emptyList(), emptyList()),
JKClass.ClassKind.COMPANION,
JKTypeParameterListImpl(),
JKClassBodyImpl(),
JKAnnotationListImpl(),
emptyList(),
Visibility.PUBLIC,
Modality.FINAL
).also { classBody.declarations += it }
fun runExpression(body: JKStatement, symbolProvider: JKSymbolProvider): JKExpression {
val lambda = JKLambdaExpressionImpl(
body,
emptyList()
)
return JKKtCallExpressionImpl(
symbolProvider.provideByFqNameMulti("kotlin.run"),
JKExpressionListImpl(listOf(lambda))
)
}
fun JKAnnotationMemberValue.toExpression(symbolProvider: JKSymbolProvider): JKExpression {
fun handleAnnotationParameter(element: JKTreeElement): JKTreeElement =
when (element) {
is JKClassLiteralExpression ->
element.also {
element.literalType = JKClassLiteralExpression.LiteralType.KOTLIN_CLASS
}
is JKTypeElement ->
JKTypeElementImpl(element.type.replaceJavaClassWithKotlinClassType(symbolProvider))
else -> applyRecursive(element, ::handleAnnotationParameter)
}
return handleAnnotationParameter(
when {
this is JKStubExpression -> this
this is JKAnnotation ->
JKJavaNewExpressionImpl(
classSymbol,
JKExpressionListImpl(arguments.map { it.value.detached(this).toExpression(symbolProvider) }),
JKTypeArgumentListImpl()
)
this is JKKtAnnotationArrayInitializerExpression ->
JKKtAnnotationArrayInitializerExpressionImpl(initializers.map { it.detached(this).toExpression(symbolProvider) })
this is JKExpression -> this
else -> error("Bad initializer")
}
) as JKExpression
}
inline fun JKClass.primaryConstructor(): JKKtPrimaryConstructor? =
classBody.declarations.firstIsInstanceOrNull()
fun JKAnnotation.isVarargsArgument(index: Int): Boolean {
val target = classSymbol.target
return when (target) {
is JKClass -> target.primaryConstructor()?.parameters?.getOrNull(index)?.isVarArgs
is PsiClass -> target.methods.getOrNull(index)?.isVarArgs
else -> false
} ?: false
}
@@ -1,37 +0,0 @@
/*
* 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
}
}
@@ -1,113 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k.tree
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitorVoid
import org.jetbrains.kotlin.utils.Printer
private class DebugTreePrinter : JKVisitorVoid {
internal val stringBuilder = StringBuilder()
private val printer = Printer(stringBuilder)
override fun visitTreeElement(treeElement: JKTreeElement) {
printer.println(treeElement.describe(), " [")
printer.indented {
treeElement.acceptChildren(this, null)
}
printer.println("]")
}
override fun visitNameIdentifier(nameIdentifier: JKNameIdentifier) {
printer.println(nameIdentifier.describe(), "(\"", nameIdentifier.value, "\")")
}
override fun visitJavaMethod(javaMethod: JKJavaMethod) {
printer.print(javaMethod.modifiers().joinToString(" ") { it.text })
printer.println(javaMethod.describe(), " [")
printer.indented {
javaMethod.block.accept(this, null)
javaMethod.parameters.forEach { it.accept(this, null) }
}
printer.println("]")
}
override fun visitExpressionStatement(expressionStatement: JKExpressionStatement) {
printer.println(expressionStatement.describe(), " [")
printer.indented {
expressionStatement.acceptChildren(this, null)
}
printer.println("]")
}
override fun visitQualifiedExpression(qualifiedExpression: JKQualifiedExpression) {
printer.println(qualifiedExpression.describe(), " [")
printer.indented {
qualifiedExpression.acceptChildren(this, null)
}
printer.println("]")
}
override fun visitBlock(block: JKBlock) {
printer.println(block.describe(), " [")
printer.indented {
block.acceptChildren(this, null)
}
printer.println("]")
}
override fun visitTypeElement(typeElement: JKTypeElement) {
val type = typeElement.type
printer.println(type.classNameWithoutJK(), " \"")
printer.indented {
if (type is JKClassType) {
printer.println((type.classReference as? JKClassSymbol)?.fqName ?: type.classReference.let { it::class })
}
if (type is JKJavaPrimitiveType) {
printer.println(type.jvmPrimitiveType.javaKeywordName)
}
}
printer.println("\"")
}
override fun visitFieldAccessExpression(fieldAccessExpression: JKFieldAccessExpression) {
printer.print(fieldAccessExpression.describe(), "(")
printSymbol(fieldAccessExpression.identifier)
printer.printlnWithNoIndent(")")
}
fun printSymbol(symbol: JKSymbol) {
if (symbol is JKUniverseSymbol<*>) {
printer.printWithNoIndent(symbol.target.describe())
} else {
printer.printWithNoIndent("Psi")
}
}
}
private fun JKTreeElement.describe(): String = this.classNameWithoutJK() + "@${this.hashCode().toString(16)}"
private fun JKTreeElement.classNameWithoutJK(): String = this.javaClass.simpleName.removePrefix("JK")
private fun JKType.classNameWithoutJK(): String = this.javaClass.simpleName.removePrefix("JK")
private inline fun Printer.indented(block: () -> Unit) {
this.pushIndent()
block()
this.popIndent()
}
fun JKTreeElement.prettyDebugPrintTree(): String = DebugTreePrinter().apply { accept(this, null) }.stringBuilder.toString()
@@ -1,147 +0,0 @@
/*
* Copyright 2010-2018 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.tree.impl
import org.jetbrains.kotlin.j2k.tree.JKBranchElement
import org.jetbrains.kotlin.j2k.tree.JKElement
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitor
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
private class JKChild<T : JKElement>(val value: Int) : ReadWriteProperty<JKBranchElementBase, T> {
override operator fun getValue(thisRef: JKBranchElementBase, property: KProperty<*>): T {
return thisRef.children[value] as T
}
override operator fun setValue(thisRef: JKBranchElementBase, property: KProperty<*>, value: T) {
(thisRef.children[this.value] as T).detach(thisRef)
thisRef.children[this.value] = value
value.attach(thisRef)
}
}
private class JKListChild<T : JKElement>(val value: Int) : ReadWriteProperty<JKBranchElementBase, List<T>> {
override operator fun getValue(thisRef: JKBranchElementBase, property: KProperty<*>): List<T> {
return thisRef.children[value] as List<T>
}
override operator fun setValue(thisRef: JKBranchElementBase, property: KProperty<*>, value: List<T>) {
(thisRef.children[this.value] as List<T>).forEach { it.detach(thisRef) }
thisRef.children[this.value] = value
value.forEach { it.attach(thisRef) }
}
}
abstract class JKElementBase : JKTreeElement, Cloneable {
override var parent: JKElement? = null
final override fun detach(from: JKElement) {
val prevParent = parent
require(from == prevParent)
parent = null
onDetach(prevParent)
}
open fun onDetach(from: JKElement) {
}
final override fun attach(to: JKElement) {
check(parent == null)
parent = to
onAttach()
}
open fun onAttach() {
}
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitTreeElement(this, data)
override fun <D> acceptChildren(visitor: JKVisitor<Unit, D>, data: D) {}
override fun copy(): JKTreeElement =
clone() as JKTreeElement
}
abstract class JKBranchElementBase : JKElementBase(), JKBranchElement {
private var childNum = 0
protected fun <T : JKTreeElement, U : T> child(v: U): ReadWriteProperty<JKBranchElementBase, T> {
children.add(childNum, v)
v.attach(this)
return JKChild(childNum++)
}
protected inline fun <reified T : JKTreeElement> children(): ReadWriteProperty<JKBranchElementBase, List<T>> {
return children(emptyList())
}
protected fun <T : JKTreeElement> children(v: List<T>): ReadWriteProperty<JKBranchElementBase, List<T>> {
children.add(childNum, v)
v.forEach { it.attach(this) }
return JKListChild(childNum++)
}
final override fun <D> acceptChildren(visitor: JKVisitor<Unit, D>, data: D) {
forEachChild { it.accept(visitor, data) }
}
protected inline fun forEachChild(block: (JKTreeElement) -> Unit) {
children.forEach {
if (it is JKTreeElement)
block(it)
else
(it as? List<JKTreeElement>)?.forEach { block(it) }
}
}
final override var valid: Boolean = true
final override fun invalidate() {
forEachChild { it.detach(this) }
valid = false
}
override fun onAttach() {
check(valid)
}
final override var children: MutableList<Any> = mutableListOf()
private set
override fun copy(): JKTreeElement {
val cloned = super.copy() as JKBranchElementBase
val deepClonedChildren =
cloned.children.map {
when (it) {
is JKElementBase -> it.copy()
is List<*> -> (it as List<JKTreeElement>).map { it.copy() }
else -> error("Tree is corrupted")
}
}
deepClonedChildren.forEach { child ->
when (child) {
is JKElementBase -> {
child.detach(this)
child.attach(cloned)
}
is List<*> -> (child as List<JKTreeElement>).forEach {
it.detach(this)
it.attach(cloned)
}
}
}
cloned.children = deepClonedChildren.toMutableList()
return cloned
}
}
@@ -1,413 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k.tree.impl
import com.intellij.psi.JavaTokenType
import com.intellij.psi.impl.source.tree.ElementType.OPERATION_BIT_SET
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.ast.Parameter
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.JKLiteralExpression.LiteralType.*
import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitor
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
class JKJavaFieldImpl(
type: JKTypeElement,
name: JKNameIdentifier,
initializer: JKExpression,
annotationList: JKAnnotationList,
override var extraModifiers: List<ExtraModifier>,
override var visibility: Visibility,
override var modality: Modality,
override var mutability: Mutability
) : JKJavaField,
JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaField(this, data)
override var annotationList: JKAnnotationList by child(annotationList)
override var initializer: JKExpression by child(initializer)
override var type by child(type)
override var name: JKNameIdentifier by child(name)
}
class JKJavaMethodImpl(
returnType: JKTypeElement,
name: JKNameIdentifier,
parameters: List<JKParameter>,
block: JKBlock,
typeParameterList: JKTypeParameterList,
annotationList: JKAnnotationList,
throwsList: List<JKTypeElement>,
override var extraModifiers: List<ExtraModifier>,
override var visibility: Visibility,
override var modality: Modality
) : JKJavaMethod, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaMethod(this, data)
override var returnType: JKTypeElement by child(returnType)
override var name: JKNameIdentifier by child(name)
override var parameters: List<JKParameter> by children(parameters)
override var block: JKBlock by child(block)
override var typeParameterList: JKTypeParameterList by child(typeParameterList)
override var annotationList: JKAnnotationList by child(annotationList)
override var throwsList: List<JKTypeElement> by children(throwsList)
}
class JKJavaLiteralExpressionImpl(
override val literal: String,
override val type: JKLiteralExpression.LiteralType
) : JKJavaLiteralExpression, JKElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaLiteralExpression(this, data)
init {
require(type in setOf(STRING, CHAR, INT, LONG, FLOAT, DOUBLE))
}
}
class JKJavaOperatorToken(val psiToken: IElementType) : JKOperatorToken {
override val text: String
get() = when (psiToken) {
JavaTokenType.EQ -> "="
JavaTokenType.EQEQ -> "=="
JavaTokenType.NE -> "!="
JavaTokenType.ANDAND -> "&&"
JavaTokenType.OROR -> "||"
JavaTokenType.GT -> ">"
JavaTokenType.LT -> "<"
JavaTokenType.GE -> ">="
JavaTokenType.LE -> "<="
JavaTokenType.EXCL -> "!"
JavaTokenType.PLUS -> "+"
JavaTokenType.MINUS -> "-"
JavaTokenType.ASTERISK -> "*"
JavaTokenType.DIV -> "/"
JavaTokenType.PERC -> "%"
JavaTokenType.PLUSEQ -> "+="
JavaTokenType.MINUSEQ -> "-="
JavaTokenType.ASTERISKEQ -> "*="
JavaTokenType.DIVEQ -> "/="
JavaTokenType.PERCEQ -> "%="
JavaTokenType.GTGT -> "shr"
JavaTokenType.LTLT -> "shl"
JavaTokenType.XOR -> "xor"
JavaTokenType.AND -> "and"
JavaTokenType.OR -> "or"
JavaTokenType.GTGTGT -> "ushr"
JavaTokenType.GTGTEQ -> "shr"
JavaTokenType.LTLTEQ -> "shl"
JavaTokenType.XOREQ -> "xor"
JavaTokenType.ANDEQ -> "and"
JavaTokenType.OREQ -> "or"
JavaTokenType.GTGTGTEQ -> "ushr"
JavaTokenType.PLUSPLUS -> "++"
JavaTokenType.MINUSMINUS -> "--"
JavaTokenType.TILDE -> "~"
else -> TODO(psiToken.toString())
}
}
fun JKJavaOperatorToken.toKtToken(): JKKtOperatorToken =
when (this.psiToken) {
JavaTokenType.DIV -> JKKtSingleValueOperatorToken(KtTokens.DIV)
JavaTokenType.MINUS -> JKKtSingleValueOperatorToken(KtTokens.MINUS)
JavaTokenType.ANDAND -> JKKtSingleValueOperatorToken(KtTokens.ANDAND)
JavaTokenType.OROR -> JKKtSingleValueOperatorToken(KtTokens.OROR)
JavaTokenType.PLUS -> JKKtSingleValueOperatorToken(KtTokens.PLUS)
JavaTokenType.ASTERISK -> JKKtSingleValueOperatorToken(KtTokens.MUL)
JavaTokenType.GT -> JKKtSingleValueOperatorToken(KtTokens.GT)
JavaTokenType.GE -> JKKtSingleValueOperatorToken(KtTokens.GTEQ)
JavaTokenType.LT -> JKKtSingleValueOperatorToken(KtTokens.LT)
JavaTokenType.LE -> JKKtSingleValueOperatorToken(KtTokens.LTEQ)
JavaTokenType.PERC -> JKKtSingleValueOperatorToken(KtTokens.PERC)
JavaTokenType.EQ -> JKKtSingleValueOperatorToken(KtTokens.EQ)
JavaTokenType.EQEQ -> JKKtSingleValueOperatorToken(KtTokens.EQEQ)
JavaTokenType.NE -> JKKtSingleValueOperatorToken(KtTokens.EXCLEQ)
JavaTokenType.PLUSEQ -> JKKtSingleValueOperatorToken(KtTokens.PLUSEQ)
JavaTokenType.MINUSEQ -> JKKtSingleValueOperatorToken(KtTokens.MINUSEQ)
JavaTokenType.PLUSPLUS -> JKKtSingleValueOperatorToken(KtTokens.PLUSPLUS)
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")
JavaTokenType.GTGTGT -> JKKtWordOperatorToken("ushr")
JavaTokenType.GTGT -> JKKtWordOperatorToken("shr")
JavaTokenType.LTLT -> JKKtWordOperatorToken("shl")
JavaTokenType.OREQ -> JKKtWordOperatorToken("or")
JavaTokenType.ANDEQ -> JKKtWordOperatorToken("and")
JavaTokenType.LTLTEQ -> JKKtWordOperatorToken("shl")
JavaTokenType.GTGTEQ -> JKKtWordOperatorToken("shr")
JavaTokenType.GTGTGTEQ -> JKKtWordOperatorToken("ushr")
JavaTokenType.XOREQ -> JKKtWordOperatorToken("xor")
else -> TODO(this.psiToken.toString())
}
class JKJavaOperatorImpl private constructor(psiToken: IElementType) : JKOperator {
override val token: JKJavaOperatorToken = JKJavaOperatorToken(psiToken)
override val precedence: Int
get() = when (token.psiToken) {
JavaTokenType.ASTERISK, JavaTokenType.DIV, JavaTokenType.PERC -> 3
JavaTokenType.PLUS, JavaTokenType.MINUS -> 4
KtTokens.ELVIS -> 7
JavaTokenType.GT, JavaTokenType.LT, JavaTokenType.GE, JavaTokenType.LE -> 9
JavaTokenType.EQEQ, JavaTokenType.NE, KtTokens.EQEQEQ, KtTokens.EXCLEQEQEQ -> 10
JavaTokenType.ANDAND -> 11
JavaTokenType.OROR -> 12
JavaTokenType.GTGTGT, JavaTokenType.GTGT, JavaTokenType.LTLT -> 7
else -> 6 /* simple name */
}
companion object {
val tokenToOperator =
(OPERATION_BIT_SET.types + arrayOf(KtTokens.EQEQEQ, KtTokens.EXCLEQEQEQ))
.associate {
it to JKJavaOperatorImpl(it)
}
}
}
sealed class JKJavaQualifierImpl : JKQualifier {
object DOT : JKJavaQualifierImpl()
}
class JKJavaMethodCallExpressionImpl(
override var identifier: JKMethodSymbol,
arguments: JKExpressionList,
typeArgumentList: JKTypeArgumentList = JKTypeArgumentListImpl()
) : JKJavaMethodCallExpression, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaMethodCallExpression(this, data)
override var arguments: JKExpressionList by child(arguments)
override var typeArgumentList: JKTypeArgumentList by child(typeArgumentList)
}
class JKClassBodyImpl(declarations: List<JKDeclaration> = emptyList()) : JKClassBody, JKBranchElementBase() {
override var declarations: List<JKDeclaration> by children(declarations)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitClassBody(this, data)
}
class JKEmptyClassBodyImpl : JKEmptyClassBody, JKBranchElementBase() {
override var declarations: List<JKDeclaration> by children(emptyList())
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitEmptyClassBody(this, data)
}
class JKJavaNewExpressionImpl(
override var classSymbol: JKClassSymbol,
arguments: JKExpressionList,
typeArgumentList: JKTypeArgumentList,
classBody: JKClassBody = JKEmptyClassBodyImpl()
) : JKJavaNewExpression, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var arguments: JKExpressionList by child(arguments)
override var typeArgumentList: JKTypeArgumentList by child(typeArgumentList)
override var classBody: JKClassBody by child(classBody)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaNewExpression(this, data)
}
class JKJavaDefaultNewExpressionImpl(
override val classSymbol: JKClassSymbol
) : JKJavaDefaultNewExpression, JKElementBase(), PsiOwner by PsiOwnerImpl()
class JKJavaNewEmptyArrayImpl(initializer: List<JKExpression>, type: JKTypeElement) : JKJavaNewEmptyArray, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override val type by child(type)
override var initializer by children(initializer)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaNewEmptyArray(this, data)
}
class JKJavaNewArrayImpl(initializer: List<JKExpression>, type: JKTypeElement) : JKJavaNewArray, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override val type by child(type)
override var initializer by children(initializer)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaNewArray(this, data)
}
sealed class JKJavaPrimitiveTypeImpl(override val jvmPrimitiveType: JvmPrimitiveType) : JKJavaPrimitiveType {
object BOOLEAN : JKJavaPrimitiveTypeImpl(JvmPrimitiveType.BOOLEAN)
object CHAR : JKJavaPrimitiveTypeImpl(JvmPrimitiveType.CHAR)
object BYTE : JKJavaPrimitiveTypeImpl(JvmPrimitiveType.BYTE)
object SHORT : JKJavaPrimitiveTypeImpl(JvmPrimitiveType.SHORT)
object INT : JKJavaPrimitiveTypeImpl(JvmPrimitiveType.INT)
object FLOAT : JKJavaPrimitiveTypeImpl(JvmPrimitiveType.FLOAT)
object LONG : JKJavaPrimitiveTypeImpl(JvmPrimitiveType.LONG)
object DOUBLE : JKJavaPrimitiveTypeImpl(JvmPrimitiveType.DOUBLE)
companion object {
val KEYWORD_TO_INSTANCE = listOf(
BOOLEAN, CHAR, BYTE, SHORT, INT, FLOAT, LONG, DOUBLE
).associate { it.jvmPrimitiveType.javaKeywordName to it } + ("void" to JKJavaVoidType)
}
}
object JKJavaVoidType : JKType {
override var nullability: Nullability
get() = Nullability.NotNull
set(it) {}
}
class JKJavaArrayTypeImpl(override val type: JKType, override var nullability: Nullability = Nullability.Default) : JKJavaArrayType {
}
class JKJavaDisjunctionTypeImpl(
override val disjunctions: List<JKType>,
override val nullability: Nullability = Nullability.Default
) : JKJavaDisjunctionType
class JKReturnStatementImpl(expression: JKExpression) : JKBranchElementBase(), JKReturnStatement, PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitReturnStatement(this, data)
override val expression by child(expression)
}
class JKJavaAssertStatementImpl(condition: JKExpression, description: JKExpression) : JKJavaAssertStatement, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override val description by child(description)
override val condition by child(condition)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaAssertStatement(this, data)
}
class JKJavaForLoopStatementImpl(initializer: JKStatement, condition: JKExpression, updaters: List<JKStatement>, body: JKStatement) :
JKJavaForLoopStatement, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var body by child(body)
override var updaters by children(updaters)
override var condition by child(condition)
override var initializer by child(initializer)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaForLoopStatement(this, data)
}
class JKJavaPolyadicExpressionImpl(operands: List<JKExpression>, override var tokens: List<JKOperator>) : JKJavaPolyadicExpression,
JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var operands by children(operands)
override fun getTokenBeforeOperand(operand: JKExpression): JKOperator? {
val index = operands.indexOf(operand)
return if (index < 1 || index > tokens.size) null else tokens[index - 1]
}
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaPolyadicExpression(this, data)
}
class JKJavaAssignmentExpressionImpl(
field: JKAssignableExpression,
expression: JKExpression,
override var operator: JKOperator
) : JKBranchElementBase(), JKJavaAssignmentExpression, PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaAssignmentExpression(this, data)
override var field: JKAssignableExpression by child(field)
override var expression: JKExpression by child(expression)
}
class JKJavaSwitchStatementImpl(
expression: JKExpression,
cases: List<JKJavaSwitchCase>
) : JKJavaSwitchStatement, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var expression: JKExpression by child(expression)
override var cases: List<JKJavaSwitchCase> by children(cases)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaSwitchStatement(this, data)
}
class JKJavaDefaultSwitchCaseImpl(statements: List<JKStatement>) : JKJavaDefaultSwitchCase, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var statements: List<JKStatement> by children(statements)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaDefaultSwitchCase(this, data)
}
class JKJavaLabelSwitchCaseImpl(
label: JKExpression,
statements: List<JKStatement>
) : JKJavaLabelSwitchCase, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var statements: List<JKStatement> by children(statements)
override var label: JKExpression by child(label)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaLabelSwitchCase(this, data)
}
class JKJavaThrowStatementImpl(exception: JKExpression) : JKJavaThrowStatement, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var exception: JKExpression by child(exception)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaThrowStatement(this, data)
}
class JKJavaTryStatementImpl(
resourceDeclarations: List<JKDeclaration>,
tryBlock: JKBlock,
finallyBlock: JKBlock,
catchSections: List<JKJavaTryCatchSection>
) : JKJavaTryStatement,
JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var resourceDeclarations: List<JKDeclaration> by children(resourceDeclarations)
override var tryBlock: JKBlock by child(tryBlock)
override var finallyBlock: JKBlock by child(finallyBlock)
override var catchSections: List<JKJavaTryCatchSection> by children(catchSections)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaTryStatement(this, data)
}
class JKJavaTryCatchSectionImpl(
parameter: JKParameter,
block: JKBlock
) : JKJavaTryCatchSection, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var parameter: JKParameter by child(parameter)
override var block: JKBlock by child(block)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaTryCatchSection(this, data)
}
class JKJavaSynchronizedStatementImpl(
lockExpression: JKExpression,
body: JKBlock
) : JKJavaSynchronizedStatement, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override val lockExpression: JKExpression by child(lockExpression)
override val body: JKBlock by child(body)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaSynchronizedStatement(this, data)
}
class JKJavaAnnotationMethodImpl(
returnType: JKTypeElement,
name: JKNameIdentifier,
defaultValue: JKAnnotationMemberValue
) : JKJavaAnnotationMethod, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var returnType: JKTypeElement by child(returnType)
override var name: JKNameIdentifier by child(name)
override var parameters: List<JKParameter> by children()
override var defaultValue: JKAnnotationMemberValue by child(defaultValue)
override var block: JKBlock by child(JKBodyStub)
override var typeParameterList: JKTypeParameterList by child(JKTypeParameterListImpl())
override var annotationList: JKAnnotationList by child(JKAnnotationListImpl())
override var extraModifiers: List<ExtraModifier> = emptyList()
override var visibility: Visibility = Visibility.PUBLIC
override var modality: Modality = Modality.FINAL
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaAnnotationMethod(this, data)
}
class JKKtAnnotationArrayInitializerExpressionImpl(initializers: List<JKAnnotationMemberValue>) : JKKtAnnotationArrayInitializerExpression,
JKBranchElementBase() {
constructor(vararg initializers: JKAnnotationMemberValue) : this(initializers.toList())
override val initializers: List<JKAnnotationMemberValue> by children(initializers)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtAnnotationArrayInitializerExpression(this, data)
}
@@ -1,542 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k.tree.impl
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.j2k.JKSymbolProvider
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.conversions.resolveFqName
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.JKLiteralExpression.LiteralType
import org.jetbrains.kotlin.j2k.tree.JKLiteralExpression.LiteralType.BOOLEAN
import org.jetbrains.kotlin.j2k.tree.JKLiteralExpression.LiteralType.NULL
import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitor
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtNamedFunction
class JKFileImpl(
packageDeclaration: JKPackageDeclaration,
importList: List<JKImportStatement>,
declarationList: List<JKDeclaration>
) : JKFile, JKBranchElementBase(),
PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitFile(this, data)
override var packageDeclaration: JKPackageDeclaration by child(packageDeclaration)
override var importList: List<JKImportStatement> by children(importList)
override var declarationList by children(declarationList)
}
class JKClassImpl(
name: JKNameIdentifier,
inheritance: JKInheritanceInfo,
override var classKind: JKClass.ClassKind,
typeParameterList: JKTypeParameterList,
classBody: JKClassBody,
annotationList: JKAnnotationList,
override var extraModifiers: List<ExtraModifier>,
override var visibility: Visibility,
override var modality: Modality
) : JKClass, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitClass(this, data)
override var name by child(name)
override val inheritance by child(inheritance)
override var typeParameterList: JKTypeParameterList by child(typeParameterList)
override var classBody: JKClassBody by child(classBody)
override var annotationList: JKAnnotationList by child(annotationList)
}
class JKNameIdentifierImpl(override val value: String) : JKNameIdentifier, JKElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitNameIdentifier(this, data)
}
class JKForLoopVariableImpl(
type: JKTypeElement,
name: JKNameIdentifier,
initializer: JKExpression
) : JKForLoopVariable, JKBranchElementBase() {
override var initializer by child(initializer)
override var name by child(name)
override var type by child(type)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitForLoopVariable(this, data)
}
class JKParameterImpl(
type: JKTypeElement,
name: JKNameIdentifier,
override var isVarArgs: Boolean = false,
initializer: JKExpression = JKStubExpressionImpl()
) : JKParameter, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitParameter(this, data)
override var initializer by child(initializer)
override var name by child(name)
override var type by child(type)
}
class JKBlockImpl(statements: List<JKStatement> = emptyList()) : JKBlock, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
constructor(vararg statements: JKStatement) : this(statements.toList())
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitBlock(this, data)
override var statements by children(statements)
}
class JKBinaryExpressionImpl(
left: JKExpression,
right: JKExpression,
override var operator: JKOperator
) : 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)
}
class JKPrefixExpressionImpl(expression: JKExpression, override var operator: JKOperator) : JKPrefixExpression, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitPrefixExpression(this, data)
override var expression by child(expression)
}
class JKPostfixExpressionImpl(expression: JKExpression, override var operator: JKOperator) : JKPostfixExpression, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitPostfixExpression(this, data)
override var expression by child(expression)
}
class JKExpressionListImpl(expressions: List<JKExpression> = emptyList()) : JKExpressionList, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
constructor(vararg expresions: JKExpression) : this(expresions.asList())
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitExpressionList(this, data)
override var expressions by children(expressions)
}
class JKQualifiedExpressionImpl(
receiver: JKExpression,
override var operator: JKQualifier,
selector: JKExpression
) : JKQualifiedExpression, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitQualifiedExpression(this, data)
override var receiver: JKExpression by child(receiver)
override var selector: JKExpression by child(selector)
}
class JKExpressionStatementImpl(expression: JKExpression) : JKExpressionStatement, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitExpressionStatement(this, data)
override val expression: JKExpression by child(expression)
}
class JKDeclarationStatementImpl(declaredStatements: List<JKDeclaration>) : JKDeclarationStatement, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override val declaredStatements by children(declaredStatements)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitDeclarationStatement(this, data)
}
class JKArrayAccessExpressionImpl(
expression: JKExpression,
indexExpression: JKExpression
) : JKArrayAccessExpression, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitArrayAccessExpression(this, data)
override var expression: JKExpression by child(expression)
override var indexExpression: JKExpression by child(indexExpression)
}
class JKParenthesizedExpressionImpl(expression: JKExpression) : JKParenthesizedExpression, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitParenthesizedExpression(this, data)
override var expression: JKExpression by child(expression)
}
class JKTypeCastExpressionImpl(override var expression: JKExpression, type: JKTypeElement) : JKTypeCastExpression, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitTypeCastExpression(this, data)
override var type by child(type)
}
class JKTypeElementImpl(override var type: JKType) : JKTypeElement, JKElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitTypeElement(this, data)
}
class JKClassTypeImpl(
override val classReference: JKClassSymbol,
override val parameters: List<JKType> = emptyList(),
override val nullability: Nullability = Nullability.Default
) : JKClassType
object JKNoTypeImpl: JKNoType {
override val nullability: Nullability = Nullability.NotNull
}
class JKStarProjectionTypeImpl : JKStarProjectionType
fun JKType.fqName(): String =
when (this) {
is JKClassType -> {
val target = classReference?.target
when (target) {
is KtClass -> target.fqName?.asString() ?: throw RuntimeException("FqName can not be calculated")
is PsiClass -> target.qualifiedName ?: throw RuntimeException("FqName can not be calculated")
else -> TODO(target.toString())
}
}
is JKJavaPrimitiveType -> jvmPrimitiveType.name
else -> TODO(toString())
}
class JKNullLiteral : JKLiteralExpression, JKElementBase(), PsiOwner by PsiOwnerImpl() {
override val literal: String
get() = "null"
override val type: LiteralType
get() = NULL
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitLiteralExpression(this, data)
}
class JKBooleanLiteral(val value: Boolean) : JKLiteralExpression, JKElementBase(), PsiOwner by PsiOwnerImpl() {
override val literal: String
get() = value.toString()
override val type: LiteralType
get() = BOOLEAN
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitLiteralExpression(this, data)
}
fun JKLiteralExpression.LiteralType.toJkType(symbolProvider: JKSymbolProvider): JKType {
fun defaultTypeByName(name: String) =
JKClassTypeImpl(
symbolProvider.provideByFqName("kotlin.$name"), emptyList(), Nullability.NotNull
)
return when (this) {
JKLiteralExpression.LiteralType.CHAR -> defaultTypeByName("Char")
JKLiteralExpression.LiteralType.BOOLEAN -> defaultTypeByName("Boolean")
JKLiteralExpression.LiteralType.INT -> defaultTypeByName("Int")
JKLiteralExpression.LiteralType.LONG -> defaultTypeByName("Long")
JKLiteralExpression.LiteralType.FLOAT -> defaultTypeByName("Float")
JKLiteralExpression.LiteralType.DOUBLE -> defaultTypeByName("Double")
JKLiteralExpression.LiteralType.NULL ->
ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.unit.toSafe()).toKtClassType(symbolProvider)
JKLiteralExpression.LiteralType.STRING ->
ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.string.toSafe()).toKtClassType(symbolProvider)
}
}
class JKLocalVariableImpl(
type: JKTypeElement,
name: JKNameIdentifier,
initializer: JKExpression,
override var mutability: Mutability
) : JKLocalVariable, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var initializer by child(initializer)
override var name by child(name)
override var type by child(type)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitLocalVariable(this, data)
}
class JKStubExpressionImpl : JKStubExpression, JKElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitStubExpression(this, data)
}
object JKBodyStub : JKBlock, JKTreeElement {
override fun copy(): JKTreeElement = this
override var statements: List<JKStatement>
get() = emptyList()
set(value) {}
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitBlock(this, data)
override fun <D> acceptChildren(visitor: JKVisitor<Unit, D>, data: D) {}
override val parent: JKElement?
get() = null
override fun detach(from: JKElement) {
}
override fun attach(to: JKElement) {
}
}
class JKBlockStatementImpl(block: JKBlock) : JKBlockStatement, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var block by child(block)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitBlockStatement(this, data)
}
class JKBlockStatementWithoutBracketsImpl(block: JKBlock) : JKBlockStatementWithoutBrackets, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var block by child(block)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitBlockStatementWithoutBrackets(this, data)
}
class JKThisExpressionImpl(qualifierLabel: JKLabel) : JKThisExpression, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var qualifierLabel: JKLabel by child(qualifierLabel)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitThisExpression(this, data)
}
class JKSuperExpressionImpl(qualifierLabel: JKLabel = JKLabelEmptyImpl()) : JKSuperExpression, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var qualifierLabel: JKLabel by child(qualifierLabel)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitSuperExpression(this, data)
}
class JKWhileStatementImpl(condition: JKExpression, body: JKStatement) : JKWhileStatement, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var condition by child(condition)
override var body by child(body)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitWhileStatement(this, data)
}
class JKDoWhileStatementImpl(body: JKStatement, condition: JKExpression) : JKDoWhileStatement, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var condition by child(condition)
override var body by child(body)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitDoWhileStatement(this, data)
}
class JKBreakStatementImpl : JKBreakStatement, JKElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitBreakStatement(this, data)
}
class JKBreakWithLabelStatementImpl(override var label: JKNameIdentifier) : JKBreakWithLabelStatement, JKElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitBreakWithLabelStatement(this, data)
}
class JKIfStatementImpl(condition: JKExpression, thenBranch: JKStatement) : JKIfStatement, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var thenBranch by child(thenBranch)
override var condition by child(condition)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitIfStatement(this, data)
}
class JKIfElseStatementImpl(condition: JKExpression, thenBranch: JKStatement, elseBranch: JKStatement) : JKIfElseStatement,
JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var elseBranch by child(elseBranch)
override var thenBranch by child(thenBranch)
override var condition by child(condition)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitIfElseStatement(this, data)
}
class JKIfElseExpressionImpl(condition: JKExpression, thenBranch: JKExpression, elseBranch: JKExpression) : JKIfElseExpression,
JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var elseBranch by child(elseBranch)
override var thenBranch by child(thenBranch)
override var condition by child(condition)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitIfElseExpression(this, data)
}
class JKClassAccessExpressionImpl(override var identifier: JKClassSymbol) : JKClassAccessExpression, JKElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitClassAccessExpression(this, data)
}
class JKLambdaExpressionImpl(
statement: JKStatement,
parameters: List<JKParameter>,
returnType: JKTypeElement = JKTypeElementImpl(JKContextType)//TODO use function type
) : JKLambdaExpression, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var statement by child(statement)
override val returnType by child(returnType)
override var parameters by children(parameters)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitLambdaExpression(this, data)
}
class JKInheritanceInfoImpl(
extends: List<JKTypeElement>,
implements: List<JKTypeElement>
) : JKInheritanceInfo, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var extends: List<JKTypeElement> by children(extends)
override var implements: List<JKTypeElement> by children(implements)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitInheritanceInfo(this, data)
}
class JKDelegationConstructorCallImpl(
override val identifier: JKMethodSymbol,
expression: JKExpression,
arguments: JKExpressionList
) : JKBranchElementBase(), JKDelegationConstructorCall, PsiOwner by PsiOwnerImpl() {
override var typeArgumentList: JKTypeArgumentList by child(JKTypeArgumentListImpl())
override val expression: JKExpression by child(expression)
override var arguments: JKExpressionList by child(arguments)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitDelegationConstructorCall(this, data)
}
class JKFieldAccessExpressionImpl(override var identifier: JKFieldSymbol) : JKFieldAccessExpression, JKElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitFieldAccessExpression(this, data)
}
val JKStatement.statements: List<JKStatement>
get() =
when (this) {
is JKBlockStatement -> block.statements
else -> listOf(this)
}
class JKLabelEmptyImpl : JKLabelEmpty, JKElementBase(), PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitLabelEmpty(this, data)
}
class JKLabelTextImpl(label: JKNameIdentifier) : JKLabelText, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override val label: JKNameIdentifier by child(label)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitLabelText(this, data)
}
class JKContinueStatementImpl(label: JKLabel) : JKContinueStatement, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var label: JKLabel by child(label)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitContinueStatement(this, data)
}
class JKLabeledStatementImpl(statement: JKStatement, labels: List<JKNameIdentifier>) : JKLabeledStatement, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var statement: JKStatement by child(statement)
override val labels: List<JKNameIdentifier> by children(labels)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitLabeledStatement(this, data)
}
class JKEmptyStatementImpl: JKEmptyStatement, JKElementBase() , PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitEmptyStatement(this, data)
}
class PsiOwnerImpl(override var psi: PsiElement? = null) : PsiOwner
val JKElement.psi: PsiElement?
get() = (this as? PsiOwner)?.psi
fun <Elem : PsiElement>JKElement.psi(): Elem? =
(this as? PsiOwner)?.psi as? Elem
class JKTypeParameterListImpl(typeParameters: List<JKTypeParameter> = emptyList()) : JKTypeParameterList, JKBranchElementBase() {
override var typeParameters by children(typeParameters)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitTypeParameterList(this, data)
}
class JKTypeParameterImpl(name: JKNameIdentifier, upperBounds: List<JKTypeElement>) : JKTypeParameter, JKBranchElementBase() {
override var name: JKNameIdentifier by child(name)
override var upperBounds: List<JKTypeElement> by children(upperBounds)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitTypeParameter(this, data)
}
class JKVarianceTypeParameterTypeImpl(
override val variance: JKVarianceTypeParameterType.Variance,
override val boundType: JKType
) : JKVarianceTypeParameterType
class JKTypeParameterTypeImpl(
override val name: String,
override val nullability: Nullability = Nullability.Default
) : JKTypeParameterType
class JKEnumConstantImpl(
name: JKNameIdentifier,
arguments: JKExpressionList,
body: JKClassBody,
type: JKTypeElement
) : JKEnumConstant, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var name: JKNameIdentifier by child(name)
override val arguments: JKExpressionList by child(arguments)
override val body: JKClassBody by child(body)
override var type: JKTypeElement by child(type)
override var initializer: JKExpression by child(JKStubExpressionImpl())
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitEnumConstant(this, data)
}
fun JKTypeElement.present(): Boolean =
type != JKNoTypeImpl
class JKForInStatementImpl(declaration: JKDeclaration, iterationExpression: JKExpression, body: JKStatement) :
JKForInStatement, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var declaration: JKDeclaration by child(declaration)
override var iterationExpression: JKExpression by child(iterationExpression)
override var body: JKStatement by child(body)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitForInStatement(this, data)
}
fun JKStatement.isEmpty(): Boolean =
when (this) {
is JKEmptyStatement -> true
is JKBlockStatement -> block is JKBodyStub
is JKExpressionStatement -> expression is JKStubExpression
else -> false
}
class JKPackageDeclarationImpl(packageName: JKNameIdentifier) : JKPackageDeclaration, JKBranchElementBase() {
override var packageName: JKNameIdentifier by child(packageName)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitPackageDeclaration(this, data)
}
class JKAnnotationListImpl(annotations: List<JKAnnotation> = emptyList()) : JKAnnotationList, JKBranchElementBase() {
override var annotations: List<JKAnnotation> by children(annotations)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitAnnotationList(this, data)
}
class JKAnnotationImpl(
override var classSymbol: JKClassSymbol,
arguments: List<JKAnnotationParameter> = emptyList()
) : JKAnnotation, JKBranchElementBase() {
override var arguments: List<JKAnnotationParameter> by children(arguments)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitAnnotation(this, data)
}
class JKTypeArgumentListImpl(typeArguments: List<JKTypeElement> = emptyList()) : JKTypeArgumentList, JKBranchElementBase(),
PsiOwner by PsiOwnerImpl() {
override val typeArguments: List<JKTypeElement> by children(typeArguments)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitTypeArgumentList(this, data)
}
class JKClassLiteralExpressionImpl(
classType: JKTypeElement,
override var literalType: JKClassLiteralExpression.LiteralType
) : JKClassLiteralExpression, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override val classType: JKTypeElement by child(classType)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitClassLiteralExpression(this, data)
}
class JKImportStatementImpl(name: JKNameIdentifier) : JKImportStatement, JKBranchElementBase() {
override val name: JKNameIdentifier by child(name)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitImportStatement(this, data)
}
class JKAnnotationParameterImpl(value: JKAnnotationMemberValue) : JKAnnotationParameter, JKBranchElementBase() {
override var value: JKAnnotationMemberValue by child(value)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitAnnotationParameter(this, data)
}
class JKAnnotationNameParameterImpl(
value: JKAnnotationMemberValue,
name: JKNameIdentifier
) : JKAnnotationNameParameter, JKBranchElementBase() {
override var value: JKAnnotationMemberValue by child(value)
override val name: JKNameIdentifier by child(name)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitAnnotationNameParameter(this, data)
}
@@ -1,288 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k.tree.impl
import com.intellij.psi.JavaTokenType
import org.jetbrains.kotlin.j2k.ast.Nullability
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitor
import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.utils.addToStdlib.cast
class JKKtPropertyImpl(
type: JKTypeElement,
name: JKNameIdentifier,
initializer: JKExpression,
getter: JKKtGetterOrSetter,
setter: JKKtGetterOrSetter,
annotationList: JKAnnotationList,
override var extraModifiers: List<ExtraModifier>,
override var visibility: Visibility,
override var modality: Modality,
override var mutability: Mutability
) : JKBranchElementBase(), JKKtProperty, PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtProperty(this, data)
override var annotationList: JKAnnotationList by child(annotationList)
override var type by child(type)
override var name: JKNameIdentifier by child(name)
override var initializer: JKExpression by child(initializer)
override var getter: JKKtGetterOrSetter by child(getter)
override var setter: JKKtGetterOrSetter by child(setter)
}
class JKKtFunctionImpl(
returnType: JKTypeElement,
name: JKNameIdentifier,
parameters: List<JKParameter>,
block: JKBlock,
typeParameterList: JKTypeParameterList,
annotationList: JKAnnotationList,
override var extraModifiers: List<ExtraModifier>,
override var visibility: Visibility,
override var modality: Modality
) : JKBranchElementBase(), JKKtFunction, PsiOwner by PsiOwnerImpl() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtFunction(this, data)
override var returnType: JKTypeElement by child(returnType)
override var name: JKNameIdentifier by child(name)
override var parameters: List<JKParameter> by children(parameters)
override var block: JKBlock by child(block)
override var typeParameterList: JKTypeParameterList by child(typeParameterList)
override var annotationList: JKAnnotationList by child(annotationList)
}
sealed class JKKtQualifierImpl : JKQualifier, JKElementBase() {
object DOT : JKKtQualifierImpl()
object SAFE : JKKtQualifierImpl()
}
class JKKtCallExpressionImpl(
override val identifier: JKMethodSymbol,
arguments: JKExpressionList,
typeArgumentList: JKTypeArgumentList = JKTypeArgumentListImpl()
) : JKKtMethodCallExpression, JKBranchElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtMethodCallExpression(this, data)
override var arguments: JKExpressionList by child(arguments)
override var typeArgumentList: JKTypeArgumentList by child(typeArgumentList)
}
class JKKtLiteralExpressionImpl(
override val literal: String,
override val type: JKLiteralExpression.LiteralType
) : JKKtLiteralExpression,
JKElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtLiteralExpression(this, data)
}
class JKKtSingleValueOperatorToken(val psiToken: KtSingleValueToken) : JKKtOperatorToken {
override val operatorName: String
get() = OperatorConventions.getNameForOperationSymbol(psiToken, true, true)?.identifier
?: OperatorConventions.BOOLEAN_OPERATIONS[psiToken]?.identifier
?: TODO(psiToken.value)
override val text: String = psiToken.value
}
class JKKtWordOperatorToken(override val text: String) : JKKtOperatorToken {
override val operatorName: String = text
}
class JKKtOperatorImpl(override val token: JKKtOperatorToken, val returnType: JKType) : JKOperator, JKElementBase() {
constructor(singleValueToken: KtSingleValueToken, returnType: JKType) : this(
JKKtSingleValueOperatorToken(singleValueToken),
returnType
)
override val precedence: Int
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
}
class JKKtAlsoCallExpressionImpl(
statement: JKStatement,
override val identifier: JKMethodSymbol,
typeArgumentList: JKTypeArgumentList = JKTypeArgumentListImpl()
) : JKKtAlsoCallExpression, JKBranchElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtAlsoCallExpression(this, data)
override var statement
get() = arguments.expressions.first().cast<JKLambdaExpressionImpl>().statement
set(it) {
arguments.expressions.first().cast<JKLambdaExpressionImpl>().statement = it
}
override var arguments: JKExpressionList by child(
JKExpressionListImpl(
listOf(
JKLambdaExpressionImpl(statement, emptyList())
)
)
)
override var typeArgumentList: JKTypeArgumentList by child(typeArgumentList)
}
class JKKtAssignmentStatementImpl(
field: JKAssignableExpression,
expression: JKExpression,
override var operator: JKOperator
) : JKKtAssignmentStatement, JKBranchElementBase() {
override var field: JKAssignableExpression by child(field)
override var expression by child(expression)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtAssignmentStatement(this, data)
}
object JKContextType : JKType {
override val nullability: Nullability
get() = Nullability.Default
}
class JKKtConstructorImpl(
name: JKNameIdentifier,
parameters: List<JKParameter>,
block: JKBlock,
delegationCall: JKExpression,
annotationList: JKAnnotationList,
override var extraModifiers: List<ExtraModifier>,
override var visibility: Visibility,
override var modality: Modality
) : JKBranchElementBase(), JKKtConstructor {
override var returnType: JKTypeElement by child(JKTypeElementImpl(JKNoTypeImpl))
override var name: JKNameIdentifier by child(name)
override var parameters: List<JKParameter> by children(parameters)
override var block: JKBlock by child(block)
override var delegationCall: JKExpression by child(delegationCall)
override var typeParameterList: JKTypeParameterList by child(JKTypeParameterListImpl())
override var annotationList: JKAnnotationList by child(annotationList)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtConstructor(this, data)
}
class JKKtPrimaryConstructorImpl(
name: JKNameIdentifier,//TODO not needed
parameters: List<JKParameter>,
delegationCall: JKExpression,
annotationList: JKAnnotationList,
override var extraModifiers: List<ExtraModifier>,
override var visibility: Visibility,
override var modality: Modality
) : JKBranchElementBase(), JKKtPrimaryConstructor {
override var returnType: JKTypeElement by child(JKTypeElementImpl(JKNoTypeImpl))
override var name: JKNameIdentifier by child(name)
override var parameters: List<JKParameter> by children(parameters)
override var block: JKBlock by child(JKBodyStub)
override var delegationCall: JKExpression by child(delegationCall)
override var typeParameterList: JKTypeParameterList by child(JKTypeParameterListImpl())
override var annotationList: JKAnnotationList by child(annotationList)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtPrimaryConstructor(this, data)
}
class JKKtWhenStatementImpl(
expression: JKExpression,
cases: List<JKKtWhenCase>
) : JKKtWhenStatement, JKBranchElementBase() {
override var expression: JKExpression by child(expression)
override var cases: List<JKKtWhenCase> by children(cases)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtWhenStatement(this, data)
}
class JKKtWhenCaseImpl(labels: List<JKKtWhenLabel>, statement: JKStatement) : JKKtWhenCase, JKBranchElementBase() {
override var labels: List<JKKtWhenLabel> by children(labels)
override var statement: JKStatement by child(statement)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtWhenCase(this, data)
}
class JKKtElseWhenLabelImpl : JKKtElseWhenLabel, JKElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtElseWhenLabel(this, data)
}
class JKKtValueWhenLabelImpl(expression: JKExpression) : JKKtValueWhenLabel, JKBranchElementBase() {
override var expression: JKExpression by child(expression)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtValueWhenLabel(this, data)
}
class JKKtIsExpressionImpl(expression: JKExpression, type: JKTypeElement) : JKKtIsExpression, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var type by child(type)
override var expression by child(expression)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtIsExpression(this, data)
}
class JKKtInitDeclarationImpl(block: JKBlock) : JKKtInitDeclaration, JKBranchElementBase() {
override var block: JKBlock by child(block)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtInitDeclaration(this, data)
}
class JKKtConvertedFromForLoopSyntheticWhileStatementImpl(
variableDeclaration: JKStatement,
whileStatement: JKWhileStatement
) : JKKtConvertedFromForLoopSyntheticWhileStatement, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var variableDeclaration: JKStatement by child(variableDeclaration)
override var whileStatement: JKWhileStatement by child(whileStatement)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R =
visitor.visitKtConvertedFromForLoopSyntheticWhileStatement(this, data)
}
class JKKtThrowExpressionImpl(exception: JKExpression) : JKKtThrowExpression, JKBranchElementBase() {
override var exception: JKExpression by child(exception)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtThrowExpression(this, data)
}
class JKKtTryExpressionImpl(
tryBlock: JKBlock,
finallyBlock: JKBlock,
catchSections: List<JKKtTryCatchSection>
) : JKKtTryExpression, JKBranchElementBase(){
override var tryBlock: JKBlock by child(tryBlock)
override var finallyBlock: JKBlock by child(finallyBlock)
override var catchSections: List<JKKtTryCatchSection> by children(catchSections)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtTryExpression(this, data)
}
class JKKtTryCatchSectionImpl(
parameter: JKParameter,
block: JKBlock
) : JKKtTryCatchSection, JKBranchElementBase() {
override var parameter: JKParameter by child(parameter)
override var block: JKBlock by child(block)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtTryCatchSection(this, data)
}
class JKKtGetterOrSetterImpl(
body: JKStatement,
override val kind: JKKtGetterOrSetter.Kind,
override var visibility: Visibility
) : JKKtGetterOrSetter, JKBranchElementBase() {
override var body: JKStatement by child(body)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtGetterOrSetter(this, data)
}
class JKKtEmptyGetterOrSetterImpl : JKKtEmptyGetterOrSetter, JKBranchElementBase() {
override var visibility: Visibility = Visibility.PUBLIC
override var body: JKStatement by child(JKEmptyStatementImpl())
override val kind: JKKtGetterOrSetter.Kind
get() = error("Cannot get kind of JKKtEmptyGetterOrSetter")
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtEmptyGetterOrSetter(this, data)
}
@@ -1,276 +0,0 @@
/*
* Copyright 2010-2018 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.tree.impl
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiReference
import com.intellij.psi.PsiVariable
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
import org.jetbrains.kotlin.idea.search.declarationsSearch.findDeepestSuperMethodsKotlinAware
import org.jetbrains.kotlin.idea.search.declarationsSearch.findDeepestSuperMethodsNoWrapping
import org.jetbrains.kotlin.j2k.JKSymbolProvider
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.conversions.parentOfType
import org.jetbrains.kotlin.j2k.conversions.resolveFqName
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtNamedFunction
interface JKSymbol {
val target: Any
val declaredIn: JKSymbol?
val fqName: String?
}
interface JKUnresolvedSymbol : JKSymbol
fun JKSymbol.isUnresolved() =
this is JKUnresolvedSymbol
interface JKNamedSymbol : JKSymbol {
val name: String
}
interface JKUniverseSymbol<T : JKTreeElement> : JKSymbol {
override var target: T
}
interface JKClassSymbol : JKNamedSymbol
interface JKMethodSymbol : JKNamedSymbol {
override val fqName: String
val receiverType: JKType?
val parameterTypes: List<JKType>?
val returnType: JKType?
}
fun JKMethodSymbol.parameterTypesWithUnfoldedVarargs(): Sequence<JKType>? {
val realParameterTypes = parameterTypes ?: return null
if (realParameterTypes.isEmpty()) return emptySequence()
val lastArrayType = realParameterTypes.last().arrayInnerType() ?: return realParameterTypes.asSequence()
return realParameterTypes.dropLast(1).asSequence() + generateSequence { lastArrayType }
}
interface JKFieldSymbol : JKNamedSymbol {
override val fqName: String
val fieldType: JKType?
}
class JKUniverseClassSymbol : JKClassSymbol, JKUniverseSymbol<JKClass> {
override lateinit var target: JKClass
override val declaredIn: JKSymbol
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val fqName: String
get() = target.name.value // TODO("Fix this")
override val name: String
get() = target.name.value
}
class JKMultiverseClassSymbol(override val target: PsiClass) : JKClassSymbol {
override val declaredIn: JKSymbol
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val fqName: String?
get() = target.getKotlinFqName()?.asString() ?: target.qualifiedName
override val name: String
get() = target.name!!
}
class JKMultiverseKtClassSymbol(override val target: KtClassOrObject) : JKClassSymbol {
override val name: String
get() = target.name!!
override val declaredIn: JKSymbol
get() = TODO("not implemented")
override val fqName: String?
get() = target.fqName?.asString()
}
fun JKClassSymbol.displayName() =
when (this) {
is JKUniverseClassSymbol ->
target.psi<PsiClass>()
?.nameWithOuterClasses()
?: name
is JKMultiverseClassSymbol -> target.nameWithOuterClasses()
else -> name
}
fun PsiClass.nameWithOuterClasses() =
generateSequence(this) { it.containingClass }
.toList()
.reversed()
.joinToString(separator = ".") { it.name!! }
class JKUniverseMethodSymbol(private val symbolProvider: JKSymbolProvider) : JKMethodSymbol, JKUniverseSymbol<JKMethod> {
override val receiverType: JKType?
get() = (target.parent as? JKClass)?.let {
JKClassTypeImpl(symbolProvider.provideUniverseSymbol(it), emptyList()/*TODO*/)
}
override val parameterTypes: List<JKType>
get() = target.parameters.map { it.type.type }
override val returnType: JKType
get() = target.returnType.type
override val name: String
get() = target.name.value
override lateinit var target: JKMethod
override val declaredIn: JKSymbol?
get() = target.parentOfType<JKClass>()?.let { symbolProvider.provideUniverseSymbol(it) }
override val fqName: String
get() = target.name.value // TODO("Fix this")
}
class JKMultiverseMethodSymbol(override val target: PsiMethod, private val symbolProvider: JKSymbolProvider) : JKMethodSymbol {
override val receiverType: JKType?
get() = target.containingClass?.let {
JKClassTypeImpl(symbolProvider.provideDirectSymbol(it) as JKClassSymbol, emptyList()/*TODO*/)
}
override val parameterTypes: List<JKType>
get() = target.parameterList.parameters.map { it.type.toJK(symbolProvider) }
override val returnType: JKType
get() = target.returnType!!.toJK(symbolProvider)
override val name: String
get() = target.name
override val declaredIn: JKSymbol?
get() = target.containingClass?.let { symbolProvider.provideDirectSymbol(it) }
override val fqName: String
get() = target.getKotlinFqName()?.asString() ?: target.name
}
class JKMultiverseFunctionSymbol(override val target: KtNamedFunction, private val symbolProvider: JKSymbolProvider) : JKMethodSymbol {
override val receiverType: JKType?
get() = target.receiverTypeReference?.toJK(symbolProvider)
override val parameterTypes: List<JKType>?
get() = target.valueParameters.map { parameter ->
val type = parameter.typeReference?.toJK(symbolProvider)
type?.let {
if (parameter.isVarArg) {
JKClassTypeImpl(
symbolProvider.provideByFqName(KotlinBuiltIns.FQ_NAMES.array),
listOf(it)
)
} else it
}
}.takeIf { parameters -> parameters.all { it != null } } as? List<JKType>
override val returnType: JKType?
get() = target.typeReference?.toJK(symbolProvider)
override val name: String
get() = target.name!!
override val declaredIn: JKSymbol
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val fqName: String
get() = target.fqName!!.asString()
}
class JKUniverseFieldSymbol : JKFieldSymbol, JKUniverseSymbol<JKVariable> {
override val fieldType: JKType
get() = target.type.type
override val name: String
get() = target.name.value
override lateinit var target: JKVariable
override val declaredIn: JKSymbol
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val fqName: String
get() = target.name.value // TODO("Fix this")
}
class JKMultiverseFieldSymbol(override val target: PsiVariable, private val symbolProvider: JKSymbolProvider) : JKFieldSymbol {
override val fieldType: JKType
get() = target.type.toJK(symbolProvider)
override val name: String
get() = target.name!!
override val declaredIn: JKSymbol
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val fqName: String
get() = target.getKotlinFqName()?.asString() ?: target.name!!
}
class JKMultiversePropertySymbol(override val target: KtCallableDeclaration, private val symbolProvider: JKSymbolProvider) : JKFieldSymbol {
override val fieldType: JKType?
get() = target.typeReference?.toJK(symbolProvider)
override val name: String
get() = target.name!!
override val declaredIn: JKSymbol
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val fqName: String
get() = target.fqName!!.asString()
}
class JKUnresolvedField(override val target: String, private val symbolProvider: JKSymbolProvider) : JKFieldSymbol, JKUnresolvedSymbol {
override val fieldType: JKType
get() {
val resolvedType = (target as? PsiReferenceExpressionImpl)?.type
if (resolvedType != null) return resolvedType.toJK(symbolProvider)
return JKClassTypeImpl(symbolProvider.provideByFqName("kotlin.Nothing"), emptyList())
}
override val declaredIn: JKSymbol
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val fqName: String = target
override val name: String = target
}
class JKUnresolvedMethod(
override val target: String,
override val returnType: JKType = JKNoTypeImpl
) : JKMethodSymbol, JKUnresolvedSymbol {
constructor(target: PsiReference) : this(target.canonicalText)
override val declaredIn: JKSymbol
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val fqName: String = target
override val receiverType: JKType?
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val parameterTypes: List<JKType>
get() = TODO(target) //To change initializer of created properties use File | Settings | File Templates.
override val name: String
get() = target
}
class JKExclExclMethod(
operandType: JKType
) : JKMethodSymbol {
override val target: String = "!!"
override val returnType: JKType = operandType.updateNullability(Nullability.NotNull)
override val declaredIn: JKSymbol
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val fqName: String = "!!"
override val receiverType: JKType?
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val parameterTypes: List<JKType>
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val name: String = "!!"
}
class JKUnresolvedClassSymbol(override val target: String) : JKClassSymbol, JKUnresolvedSymbol {
override val declaredIn: JKSymbol
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val fqName: String?
get() = target
override val name: String
get() = target.substringAfterLast('.')
}
fun JKSymbol.deepestFqName(): String? {
fun Any.deepestFqNameForTarget(): String? =
when (this) {
is PsiMethod -> (findDeepestSuperMethods().firstOrNull() ?: this).getKotlinFqName()?.asString()
is KtNamedFunction -> findDeepestSuperMethodsNoWrapping(this).firstOrNull()?.getKotlinFqName()?.asString()
is JKMethod -> psi()?.deepestFqNameForTarget()
else -> null
}
return target.deepestFqNameForTarget() ?: fqName
}
@@ -1,139 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k.tree
import org.jetbrains.kotlin.idea.search.usagesSearch.constructor
import org.jetbrains.kotlin.j2k.tree.impl.*
interface JKField : JKVariable, JKVisibilityOwner, JKMutabilityOwner, JKModalityOwner, JKExtraModifiersOwner, JKAnnotationListOwner
interface JKJavaField : JKField, JKBranchElement
interface JKJavaMethod : JKMethod, JKBranchElement {
var throwsList: List<JKTypeElement>
}
interface JKJavaMethodCallExpression : JKMethodCallExpression
interface JKClassBody : JKTreeElement, JKBranchElement {
var declarations: List<JKDeclaration>
}
interface JKEmptyClassBody : JKClassBody
interface JKJavaNewExpression : JKExpression, JKTypeArgumentListOwner, PsiOwner {
val classSymbol: JKClassSymbol
var arguments: JKExpressionList
var classBody: JKClassBody
}
fun JKJavaNewExpression.isAnonymousClass() =
classBody !is JKEmptyClassBody
interface JKJavaDefaultNewExpression : JKExpression {
val classSymbol: JKClassSymbol
}
interface JKJavaNewEmptyArray : JKExpression {
val type: JKTypeElement
var initializer: List<JKExpression>
}
interface JKJavaNewArray : JKExpression {
val type: JKTypeElement
var initializer: List<JKExpression>
}
interface JKJavaLiteralExpression : JKLiteralExpression
interface JKReturnStatement : JKStatement {
val expression: JKExpression
}
interface JKJavaAssertStatement : JKStatement {
val condition: JKExpression
val description: JKExpression
}
interface JKJavaForLoopStatement : JKLoopStatement {
var initializer: JKStatement
var condition: JKExpression
var updaters: List<JKStatement>
}
interface JKJavaPolyadicExpression : JKExpression {
var operands: List<JKExpression>
var tokens: List<JKOperator>
fun getTokenBeforeOperand(operand: JKExpression): JKOperator?
}
interface JKJavaAssignmentExpression : JKExpression, JKBranchElement {
var field: JKAssignableExpression
var expression: JKExpression
var operator: JKOperator
}
interface JKJavaThrowStatement : JKStatement {
var exception: JKExpression
}
interface JKJavaTryStatement : JKStatement {
var resourceDeclarations: List<JKDeclaration>
var tryBlock: JKBlock
var finallyBlock: JKBlock
var catchSections: List<JKJavaTryCatchSection>
}
interface JKJavaTryCatchSection : JKTreeElement {
var parameter: JKParameter
var block: JKBlock
}
interface JKJavaSwitchStatement : JKStatement {
var expression: JKExpression
var cases: List<JKJavaSwitchCase>
}
interface JKJavaSwitchCase : JKTreeElement {
fun isDefault(): Boolean
var statements: List<JKStatement>
}
interface JKJavaDefaultSwitchCase : JKJavaSwitchCase {
override fun isDefault(): Boolean = true
}
interface JKJavaLabelSwitchCase : JKJavaSwitchCase {
override fun isDefault(): Boolean = false
var label: JKExpression
}
interface JKJavaContinueStatement: JKStatement
interface JKJavaSynchronizedStatement : JKStatement, JKBranchElement {
val lockExpression: JKExpression
val body: JKBlock
}
interface JKJavaAnnotationMethod : JKMethod, JKBranchElement {
val defaultValue: JKAnnotationMemberValue
}
@@ -1,432 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k.tree
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.j2k.tree.impl.JKClassSymbol
import org.jetbrains.kotlin.j2k.tree.impl.JKFieldSymbol
import org.jetbrains.kotlin.j2k.tree.impl.JKMethodSymbol
import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitor
interface JKTreeElement : JKElement {
fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R
fun <R> accept(visitor: JKVisitor<R, Nothing?>): R = accept(visitor, null)
fun <D> acceptChildren(visitor: JKVisitor<Unit, D>, data: D)
fun acceptChildren(visitor: JKVisitor<Unit, Nothing?>) = acceptChildren(visitor, null)
fun copy(): JKTreeElement
}
interface PsiOwner {
var psi: PsiElement?
}
interface JKDeclaration : JKTreeElement
interface JKImportStatement : JKTreeElement {
val name: JKNameIdentifier
}
interface JKFile : JKTreeElement, JKBranchElement {
var packageDeclaration: JKPackageDeclaration
var importList: List<JKImportStatement>
var declarationList: List<JKDeclaration>
}
interface JKClass : JKDeclaration, JKVisibilityOwner, JKExtraModifiersOwner, JKModalityOwner, JKTypeParameterListOwner, JKAnnotationListOwner,
JKBranchElement {
val name: JKNameIdentifier
val inheritance: JKInheritanceInfo
var classBody: JKClassBody
var classKind: ClassKind
enum class ClassKind {
ANNOTATION, CLASS, ENUM, INTERFACE, OBJECT, COMPANION
}
}
fun JKClass.isLocalClass(): Boolean =
parent !is JKClassBody && parent !is JKFile
val JKClass.declarationList: List<JKDeclaration>
get() = classBody.declarations
interface JKInheritanceInfo : JKTreeElement, JKBranchElement {
var extends: List<JKTypeElement>
var implements: List<JKTypeElement>
}
fun JKInheritanceInfo.present(): Boolean =
extends.isNotEmpty() || implements.isNotEmpty()
interface JKAnnotationList : JKTreeElement {
var annotations: List<JKAnnotation>
}
interface JKAnnotation : JKAnnotationMemberValue {
var classSymbol: JKClassSymbol
var arguments: List<JKAnnotationParameter>
}
interface JKAnnotationParameter : JKTreeElement {
var value: JKAnnotationMemberValue
}
interface JKAnnotationNameParameter : JKAnnotationParameter {
val name: JKNameIdentifier
}
interface JKAnnotationListOwner : JKTreeElement {
var annotationList: JKAnnotationList
}
interface JKMethod : JKDeclaration, JKVisibilityOwner, JKModalityOwner, JKExtraModifiersOwner, JKTypeParameterListOwner,
JKAnnotationListOwner {
val name: JKNameIdentifier
var parameters: List<JKParameter>
var returnType: JKTypeElement
var block: JKBlock
}
interface JKVariable : JKDeclaration {
var type: JKTypeElement
var name: JKNameIdentifier
var initializer: JKExpression
}
interface JKForLoopVariable : JKVariable
interface JKLocalVariable : JKVariable, JKMutabilityOwner
interface JKExtraModifiersOwner : JKModifiersListOwner {
var extraModifiers: List<ExtraModifier>
}
interface Modifier {
val text: String
}
enum class ExtraModifier(override val text: String) : Modifier {
ACTUAL("actual"),
ANNOTATION("annotation"),
COMPANION("companion"),
CONST("const"),
CROSSINLINE("crossinline"),
DATA("data"),
EXPECT("expect"),
EXTERNAL("external"),
INFIX("infix"),
INLINE("inline"),
INNER("inner"),
LATEINIT("lateinit"),
NOINLINE("noinline"),
OPERATOR("operator"),
OUT("out"),
REIFIED("reified"),
SEALED("sealed"),
SUSPEND("suspend"),
TAILREC("tailrec"),
VARARG("vararg"),
NATIVE("native"),
STATIC("static"),
STRICTFP("strictfp"),
SYNCHRONIZED("synchronized"),
TRANSIENT("transient"),
VOLATILE("volatile")
}
interface JKVisibilityOwner : JKModifiersListOwner{
var visibility: Visibility
}
enum class Visibility(override val text: String) : Modifier {
PUBLIC("public"),
INTERNAL("internal"),
PACKAGE_PRIVATE(""),
PROTECTED("protected"),
PRIVATE("private")
}
interface JKModalityOwner : JKModifiersListOwner {
var modality: Modality
}
enum class Modality(override val text: String) : Modifier {
OPEN("open"),
FINAL("final"),
ABSTRACT("abstract"),
OVERRIDE("override")
}
interface JKMutabilityOwner : JKModifiersListOwner {
var mutability: Mutability
}
enum class Mutability(override val text: String) : Modifier {
MUTABLE("var"),
IMMUTABLE("val"),
UNKNOWN("var")//TODO ???
}
interface JKModifiersListOwner : JKTreeElement
fun JKModifiersListOwner.modifiers(): List<Modifier> =
listOfNotNull((this as? JKVisibilityOwner)?.visibility) +
(this as? JKExtraModifiersOwner)?.extraModifiers.orEmpty() +
listOfNotNull((this as? JKModalityOwner)?.modality) +
listOfNotNull((this as? JKMutabilityOwner)?.mutability)
interface JKTypeElement : JKTreeElement {
val type: JKType
}
interface JKStatement : JKTreeElement
interface JKBlock : JKTreeElement {
var statements: List<JKStatement>
}
interface JKIdentifier : JKTreeElement
interface JKNameIdentifier : JKIdentifier {
val value: String
}
interface JKExpression : JKTreeElement, JKAnnotationMemberValue
interface JKExpressionStatement : JKStatement, JKBranchElement {
val expression: JKExpression
}
interface JKDeclarationStatement : JKStatement {
val declaredStatements: List<JKDeclaration>
}
interface JKOperatorExpression : JKExpression {
var operator: JKOperator
}
//TODO make left & right to be immutable
interface JKBinaryExpression : JKOperatorExpression {
var left: JKExpression
var right: JKExpression
}
interface JKUnaryExpression : JKOperatorExpression {
var expression: JKExpression
}
interface JKPrefixExpression : JKUnaryExpression
interface JKPostfixExpression : JKUnaryExpression
interface JKQualifiedExpression : JKExpression, JKAssignableExpression {
var receiver: JKExpression
var operator: JKQualifier
var selector: JKExpression
}
interface JKTypeArgumentList : JKTreeElement {
val typeArguments: List<JKTypeElement>
}
interface JKTypeArgumentListOwner : JKTreeElement {
var typeArgumentList: JKTypeArgumentList
}
interface JKMethodCallExpression : JKExpression, JKTypeArgumentListOwner, JKBranchElement {
val identifier: JKMethodSymbol
var arguments: JKExpressionList
}
interface JKFieldAccessExpression : JKAssignableExpression {
val identifier: JKFieldSymbol
}
interface JKClassAccessExpression : JKExpression {
val identifier: JKClassSymbol
}
interface JKArrayAccessExpression : JKAssignableExpression {
var expression: JKExpression
var indexExpression: JKExpression
}
interface JKParenthesizedExpression : JKExpression {
val expression: JKExpression
}
interface JKTypeCastExpression : JKExpression {
val expression: JKExpression
val type: JKTypeElement
}
interface JKExpressionList : JKTreeElement, JKBranchElement {
var expressions: List<JKExpression>
}
interface JKLiteralExpression : JKExpression {
val literal: String
val type: LiteralType
enum class LiteralType {
STRING, CHAR, BOOLEAN, NULL, INT, LONG, FLOAT, DOUBLE
}
}
interface JKParameter : JKVariable, JKModifiersListOwner {
var isVarArgs: Boolean
}
interface JKStringLiteralExpression : JKLiteralExpression {
val text: String
}
interface JKStubExpression : JKExpression
interface JKLoopStatement : JKStatement {
var body: JKStatement
}
interface JKBlockStatement : JKStatement, JKBranchElement {
var block: JKBlock
}
interface JKBlockStatementWithoutBrackets : JKStatement, JKBranchElement {
var block: JKBlock
}
interface JKThisExpression : JKExpression {
var qualifierLabel: JKLabel
}
interface JKSuperExpression : JKExpression {
var qualifierLabel: JKLabel
}
interface JKWhileStatement : JKLoopStatement {
var condition: JKExpression
}
interface JKDoWhileStatement : JKLoopStatement {
var condition: JKExpression
}
interface JKBreakStatement : JKStatement
interface JKBreakWithLabelStatement : JKBreakStatement {
var label: JKNameIdentifier
}
interface JKIfStatement : JKStatement {
var condition: JKExpression
var thenBranch: JKStatement
}
interface JKIfElseStatement : JKIfStatement {
var elseBranch: JKStatement
}
interface JKIfElseExpression : JKExpression {
var condition: JKExpression
var thenBranch: JKExpression
var elseBranch: JKExpression
}
interface JKAssignableExpression : JKExpression
interface JKLambdaExpression : JKExpression {
var parameters: List<JKParameter>
val returnType: JKTypeElement
var statement: JKStatement
}
interface JKDelegationConstructorCall : JKMethodCallExpression {
override val identifier: JKMethodSymbol
val expression: JKExpression
override var arguments: JKExpressionList
}
interface JKLabel : JKTreeElement
interface JKLabelEmpty : JKLabel
interface JKLabelText : JKLabel {
val label: JKNameIdentifier
}
interface JKContinueStatement : JKStatement {
var label: JKLabel
}
interface JKLabeledStatement : JKStatement {
var statement: JKStatement
val labels: List<JKNameIdentifier>
}
interface JKEmptyStatement : JKStatement
interface JKTypeParameterList : JKTreeElement {
var typeParameters: List<JKTypeParameter>
}
interface JKTypeParameter : JKTreeElement {
var name: JKNameIdentifier
var upperBounds: List<JKTypeElement>
}
interface JKTypeParameterListOwner : JKTreeElement {
var typeParameterList: JKTypeParameterList
}
interface JKEnumConstant : JKVariable {
val arguments: JKExpressionList
val body: JKClassBody
}
interface JKForInStatement : JKStatement {
var declaration: JKDeclaration
var iterationExpression: JKExpression
var body: JKStatement
}
interface JKPackageDeclaration : JKDeclaration {
var packageName: JKNameIdentifier
}
interface JKClassLiteralExpression : JKExpression {
val classType: JKTypeElement
var literalType: LiteralType
enum class LiteralType {
KOTLIN_CLASS,
JAVA_CLASS,
JAVA_PRIMITIVE_CLASS,
JAVA_VOID_TYPE
}
}
interface JKAnnotationMemberValue : JKTreeElement
@@ -1,116 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k.tree
import org.jetbrains.kotlin.j2k.tree.impl.JKMethodSymbol
interface JKKtGetterOrSetter : JKTreeElement, JKVisibilityOwner, JKBranchElement {
var body: JKStatement
val kind: Kind
enum class Kind {
GETTER, SETTER
}
}
interface JKKtEmptyGetterOrSetter : JKKtGetterOrSetter
interface JKKtProperty : JKField, PsiOwner {
var getter: JKKtGetterOrSetter
var setter: JKKtGetterOrSetter
}
interface JKKtFunction : JKMethod, PsiOwner {
}
interface JKKtConstructor : JKDeclaration, JKExtraModifiersOwner, JKMethod, JKBranchElement {
override var name: JKNameIdentifier
override var parameters: List<JKParameter>
var delegationCall: JKExpression
}
interface JKKtPrimaryConstructor : JKKtConstructor
interface JKKtAssignmentStatement : JKStatement {
var field: JKAssignableExpression
var expression: JKExpression
var operator: JKOperator
}
interface JKKtCall : JKMethodCallExpression
interface JKKtMethodCallExpression : JKMethodCallExpression
interface JKKtAlsoCallExpression : JKKtMethodCallExpression {
var statement: JKStatement
}
interface JKKtLiteralExpression : JKLiteralExpression
interface JKKtWhenStatement : JKStatement {
var expression: JKExpression
var cases: List<JKKtWhenCase>
}
interface JKKtWhenCase : JKTreeElement {
var labels: List<JKKtWhenLabel>
var statement: JKStatement
}
interface JKKtWhenLabel : JKTreeElement
interface JKKtElseWhenLabel : JKKtWhenLabel
interface JKKtValueWhenLabel : JKKtWhenLabel {
var expression: JKExpression
}
interface JKKtIsExpression : JKExpression, PsiOwner {
var expression: JKExpression
var type: JKTypeElement
}
interface JKKtInitDeclaration : JKDeclaration {
var block: JKBlock
}
interface JKKtConvertedFromForLoopSyntheticWhileStatement : JKStatement {
var variableDeclaration: JKStatement
var whileStatement: JKWhileStatement
}
interface JKKtThrowExpression : JKExpression {
var exception: JKExpression
}
interface JKKtTryExpression : JKExpression {
var tryBlock: JKBlock
var finallyBlock: JKBlock
var catchSections: List<JKKtTryCatchSection>
}
interface JKKtTryCatchSection : JKTreeElement {
var parameter: JKParameter
var block: JKBlock
}
interface JKKtAnnotationArrayInitializerExpression : JKExpression, JKBranchElement {
val initializers: List<JKAnnotationMemberValue>
}
@@ -1,197 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k.tree
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.tree.impl.JKBranchElementBase
import org.jetbrains.kotlin.j2k.tree.impl.JKClassSymbol
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import kotlin.reflect.KProperty0
import kotlin.jvm.internal.CallableReference
interface JKOperator {
val token: JKOperatorToken
val precedence: Int
}
interface JKOperatorToken {
val text: String
}
interface JKKtOperatorToken : JKOperatorToken {
val operatorName: String
}
interface JKQualifier
interface JKElement {
val parent: JKElement?
fun detach(from: JKElement)
fun attach(to: JKElement)
}
interface JKBranchElement : JKElement {
val children: List<Any>
val valid: Boolean
fun invalidate()
}
interface JKType {
val nullability: Nullability
}
fun JKType.isNullable(): Boolean =
nullability != Nullability.NotNull
interface JKVarianceTypeParameterType : JKType {
val variance: Variance
val boundType: JKType
override val nullability: Nullability
get() = Nullability.NotNull
enum class Variance {
IN, OUT
}
}
interface JKTypeParameterType : JKType {
val name: String
}
interface JKNoType : JKType
interface JKParametrizedType : JKType {
val parameters: List<JKType>
}
interface JKClassType : JKParametrizedType {
val classReference: JKClassSymbol
override val nullability: Nullability
}
interface JKJavaPrimitiveType : JKType {
val jvmPrimitiveType: JvmPrimitiveType
override val nullability: Nullability
get() = Nullability.NotNull
}
interface JKJavaArrayType : JKType {
val type: JKType
}
interface JKStarProjectionType : JKType {
override val nullability: Nullability
get() = Nullability.NotNull
}
interface JKJavaDisjunctionType : JKType {
val disjunctions: List<JKType>
}
inline fun <reified T> JKElement.getParentOfType(): T? {
var p = parent
while (true) {
if (p is T || p == null)
return p as? T
p = p.parent
}
}
private fun <T : JKElement> KProperty0<Any>.detach(element: T) {
if (element.parent == null) return
// TODO: Fix when KT-16818 is implemented
val boundReceiver = (this as CallableReference).boundReceiver
require(boundReceiver != CallableReference.NO_RECEIVER)
require(boundReceiver is JKElement)
element.detach(boundReceiver)
}
fun <T : JKElement> KProperty0<T>.detached(): T =
get().also { detach(it) }
fun <T : JKElement> KProperty0<List<T>>.detached(): List<T> =
get().also { list -> list.forEach { detach(it) } }
fun <T : JKElement> T.detached(from: JKElement): T =
also { it.detach(from) }
fun <T : JKBranchElement> T.invalidated(): T =
also { it.invalidate() }
fun <R : JKTreeElement, T> applyRecursive(
element: R,
data: T,
onElementChanged: (JKTreeElement, JKTreeElement) -> Unit,
func: (JKTreeElement, T) -> JKTreeElement
): R {
fun <T> applyRecursiveToList(
element: JKTreeElement,
child: List<JKTreeElement>,
iter: MutableListIterator<Any>,
data: T,
func: (JKTreeElement, T) -> JKTreeElement
): List<JKTreeElement> {
val newChild = child.map {
func(it, data)
}
child.forEach { it.detach(element) }
iter.set(child)
newChild.forEach { it.attach(element) }
newChild.zip(child).forEach { (old, new) ->
if (old !== new) {
onElementChanged(new, old)
}
}
return newChild
}
if (element is JKBranchElementBase) {
val iter = element.children.listIterator()
while (iter.hasNext()) {
val child = iter.next()
if (child is List<*>) {
iter.set(applyRecursiveToList(element, child as List<JKTreeElement>, iter, data, func))
} else if (child is JKTreeElement) {
val newChild = func(child, data)
if (child !== newChild) {
child.detach(element)
iter.set(newChild)
newChild.attach(element)
onElementChanged(newChild, child)
}
} else {
error("unsupported child type: ${child::class}")
}
}
}
return element
}
fun <R : JKTreeElement> applyRecursive(
element: R,
func: (JKTreeElement) -> JKTreeElement
): R = applyRecursive(element, null, { _, _ -> }) { it, _ -> func(it) }
@@ -1,396 +0,0 @@
/*
* Copyright 2010-2018 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.tree
import com.intellij.psi.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaClassDescriptor
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.JKSymbolProvider
import org.jetbrains.kotlin.j2k.ast.ArrayType
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.conversions.resolveFqName
import org.jetbrains.kotlin.j2k.kotlinTypeByName
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isNullable
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
fun JKExpression.type(symbolProvider: JKSymbolProvider): JKType? =
when (this) {
is JKLiteralExpression -> type.toJkType(symbolProvider)
is JKOperatorExpression -> {
(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
is JKQualifiedExpressionImpl -> this.selector.type(symbolProvider)
is JKKtThrowExpression -> kotlinTypeByName(KotlinBuiltIns.FQ_NAMES.nothing.asString(), symbolProvider)
is JKClassAccessExpression -> null
is JKJavaNewExpression -> JKClassTypeImpl(classSymbol)
is JKKtIsExpression -> kotlinTypeByName(KotlinBuiltIns.FQ_NAMES._boolean.asString(), symbolProvider)
is JKParenthesizedExpression -> expression.type(symbolProvider)
is JKTypeCastExpression -> type.type
is JKThisExpression -> null// TODO return actual type
is JKSuperExpression -> null// TODO return actual type
is JKStubExpression -> null
is JKIfElseExpression -> thenBranch.type(symbolProvider)// TODO return actual type
is JKArrayAccessExpression ->
(expression.type(symbolProvider) as? JKParametrizedType)?.parameters?.lastOrNull()
is JKClassLiteralExpression -> {
val symbol = when (literalType) {
JKClassLiteralExpression.LiteralType.KOTLIN_CLASS ->
symbolProvider.provideByFqName<JKClassSymbol>("kotlin.reflect.KClass")
JKClassLiteralExpression.LiteralType.JAVA_CLASS,
JKClassLiteralExpression.LiteralType.JAVA_PRIMITIVE_CLASS, JKClassLiteralExpression.LiteralType.JAVA_VOID_TYPE ->
symbolProvider.provideByFqName("java.lang.Class")
}
JKClassTypeImpl(symbol, listOf(classType.type), Nullability.NotNull)
}
is JKKtAnnotationArrayInitializerExpression -> JKNoTypeImpl //TODO
is JKLambdaExpression -> returnType.type
else -> TODO(this::class.java.toString())
}
fun ClassId.toKtClassType(
symbolProvider: JKSymbolProvider,
nullability: Nullability = Nullability.Default
): JKType =
JKClassTypeImpl(symbolProvider.provideByFqName(this), emptyList(), nullability)
fun PsiType.toJK(symbolProvider: JKSymbolProvider, nullability: Nullability = Nullability.Default): JKType {
return when (this) {
is PsiClassType -> {
val target = resolve()
val parameters = parameters.map { it.toJK(symbolProvider, nullability) }
when (target) {
null ->
JKClassTypeImpl(JKUnresolvedClassSymbol(rawType().canonicalText), parameters, nullability)
is PsiTypeParameter ->
JKTypeParameterTypeImpl(target.name!!)
else -> {
JKClassTypeImpl(
target.let { symbolProvider.provideDirectSymbol(it) as JKClassSymbol },
parameters,
nullability
)
}
}
}
is PsiArrayType -> JKJavaArrayTypeImpl(componentType.toJK(symbolProvider, nullability), nullability)
is PsiPrimitiveType -> JKJavaPrimitiveTypeImpl.KEYWORD_TO_INSTANCE[presentableText]
?: error("Invalid primitive type $presentableText")
is PsiDisjunctionType ->
JKJavaDisjunctionTypeImpl(disjunctions.map { it.toJK(symbolProvider) })
is PsiWildcardType ->
when {
isExtends ->
JKVarianceTypeParameterTypeImpl(
JKVarianceTypeParameterType.Variance.OUT,
extendsBound.toJK(symbolProvider)
)
isSuper ->
JKVarianceTypeParameterTypeImpl(
JKVarianceTypeParameterType.Variance.IN,
superBound.toJK(symbolProvider)
)
else -> JKStarProjectionTypeImpl()
}
else -> throw Exception("Invalid PSI ${this::class.java}")
}
}
fun JKType.asTypeElement() =
JKTypeElementImpl(this)
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
fun KotlinType.toJK(symbolProvider: JKSymbolProvider): JKClassTypeImpl =
JKClassTypeImpl(
symbolProvider.provideByFqName(getJetTypeFqName(false)),
arguments.map { it.type.toJK(symbolProvider) },
if (isNullable()) Nullability.Nullable else Nullability.NotNull
)
fun KtTypeReference.toJK(symbolProvider: JKSymbolProvider): JKType? =
analyze()
.get(BindingContext.TYPE, this)
?.toJK(symbolProvider)
fun JKType.toKtType(symbolProvider: JKSymbolProvider): KotlinType? =
when (this) {
is JKClassType -> classReference.toKtType()
is JKJavaPrimitiveType ->
kotlinTypeByName(
jvmPrimitiveType.primitiveType.typeFqName.asString(),
symbolProvider
).toKtType(symbolProvider)
else -> null
// else -> TODO(this::class.java.toString())
}
infix fun JKJavaPrimitiveType.isStrongerThan(other: JKJavaPrimitiveType) =
jvmPrimitivePrioritypriority.getValue(this.jvmPrimitiveType.primitiveType) >
jvmPrimitivePrioritypriority.getValue(other.jvmPrimitiveType.primitiveType)
private val jvmPrimitivePrioritypriority =
mapOf(
PrimitiveType.BOOLEAN to -1,
PrimitiveType.CHAR to 0,
PrimitiveType.BYTE to 1,
PrimitiveType.SHORT to 2,
PrimitiveType.INT to 3,
PrimitiveType.LONG to 4,
PrimitiveType.FLOAT to 5,
PrimitiveType.DOUBLE to 6
)
fun JKClassSymbol.toKtType(): KotlinType? {
val classDescriptor = when (this) {
is JKMultiverseKtClassSymbol -> {
val bindingContext = target.analyze()
bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, target] as ClassDescriptor
}
is JKMultiverseClassSymbol ->
target.getJavaClassDescriptor()
is JKUniverseClassSymbol ->
target.psi<PsiClass>()?.getJavaClassDescriptor()//TODO null in case of a fake package
else -> TODO(this::class.java.toString())
}
return classDescriptor?.defaultType
}
fun JKType.applyRecursive(transform: (JKType) -> JKType?): JKType =
transform(this) ?: when (this) {
is JKTypeParameterTypeImpl -> this
is JKClassTypeImpl ->
JKClassTypeImpl(
classReference,
parameters.map { it.applyRecursive(transform) },
nullability
)
is JKNoType -> this
is JKJavaVoidType -> this
is JKJavaPrimitiveType -> this
is JKJavaArrayType -> JKJavaArrayTypeImpl(type.applyRecursive(transform), nullability)
is JKContextType -> JKContextType
is JKJavaDisjunctionType ->
JKJavaDisjunctionTypeImpl(disjunctions.map { it.applyRecursive(transform) }, nullability)
is JKStarProjectionType -> this
else -> TODO(this::class.toString())
}
inline fun <reified T : JKType> T.updateNullability(newNullability: Nullability): T =
if (nullability == newNullability) this
else when (this) {
is JKTypeParameterTypeImpl -> JKTypeParameterTypeImpl(name, newNullability)
is JKClassTypeImpl -> JKClassTypeImpl(classReference, parameters, newNullability)
is JKNoType -> this
is JKJavaVoidType -> this
is JKJavaPrimitiveType -> this
is JKJavaArrayType -> JKJavaArrayTypeImpl(type, newNullability)
is JKContextType -> JKContextType
is JKJavaDisjunctionType -> this
else -> TODO(this::class.toString())
} as T
fun <T : JKType> T.updateNullabilityRecursively(newNullability: Nullability): T =
applyRecursive {
when (it) {
is JKTypeParameterTypeImpl -> JKTypeParameterTypeImpl(it.name, newNullability)
is JKClassTypeImpl ->
JKClassTypeImpl(
it.classReference,
it.parameters.map { it.updateNullabilityRecursively(newNullability) },
newNullability
)
is JKJavaArrayType -> JKJavaArrayTypeImpl(it.type.updateNullabilityRecursively(newNullability), newNullability)
else -> null
}
} as T
fun JKJavaMethod.returnTypeNullability(context: ConversionContext): Nullability =
context.typeFlavorCalculator.methodNullability(psi()!!)
fun JKType.isCollectionType(symbolProvider: JKSymbolProvider): Boolean {
if (this !is JKClassType) return false
val collectionType = JKClassTypeImpl(symbolProvider.provideByFqName("java.util.Collection"), emptyList())
return this.isSubtypeOf(collectionType, symbolProvider)
}
fun JKType.isStringType(): Boolean =
(this as? JKClassType)?.classReference?.name == "String"
fun JKLiteralExpression.LiteralType.toPrimitiveType(): JKJavaPrimitiveType? =
when (this) {
JKLiteralExpression.LiteralType.CHAR -> JKJavaPrimitiveTypeImpl.CHAR
JKLiteralExpression.LiteralType.BOOLEAN -> JKJavaPrimitiveTypeImpl.BOOLEAN
JKLiteralExpression.LiteralType.INT -> JKJavaPrimitiveTypeImpl.INT
JKLiteralExpression.LiteralType.LONG -> JKJavaPrimitiveTypeImpl.LONG
JKLiteralExpression.LiteralType.FLOAT -> JKJavaPrimitiveTypeImpl.FLOAT
JKLiteralExpression.LiteralType.DOUBLE -> JKJavaPrimitiveTypeImpl.DOUBLE
JKLiteralExpression.LiteralType.STRING -> null
JKLiteralExpression.LiteralType.NULL -> null
}
fun JKJavaPrimitiveType.toLiteralType(): JKLiteralExpression.LiteralType? =
when (this) {
JKJavaPrimitiveTypeImpl.CHAR -> JKLiteralExpression.LiteralType.CHAR
JKJavaPrimitiveTypeImpl.BOOLEAN -> JKLiteralExpression.LiteralType.BOOLEAN
JKJavaPrimitiveTypeImpl.INT -> JKLiteralExpression.LiteralType.INT
JKJavaPrimitiveTypeImpl.LONG -> JKLiteralExpression.LiteralType.LONG
JKJavaPrimitiveTypeImpl.CHAR -> JKLiteralExpression.LiteralType.CHAR
JKJavaPrimitiveTypeImpl.DOUBLE -> JKLiteralExpression.LiteralType.DOUBLE
JKJavaPrimitiveTypeImpl.FLOAT -> JKLiteralExpression.LiteralType.FLOAT
else -> null
}
fun JKType.asPrimitiveType(): JKJavaPrimitiveType? =
if (this is JKJavaPrimitiveType) this
else when ((this as? JKClassType)?.classReference?.fqName) {
KotlinBuiltIns.FQ_NAMES._char.asString(), CommonClassNames.JAVA_LANG_CHARACTER -> JKJavaPrimitiveTypeImpl.CHAR
KotlinBuiltIns.FQ_NAMES._boolean.asString(), CommonClassNames.JAVA_LANG_BOOLEAN -> JKJavaPrimitiveTypeImpl.BOOLEAN
KotlinBuiltIns.FQ_NAMES._int.asString(), CommonClassNames.JAVA_LANG_INTEGER -> JKJavaPrimitiveTypeImpl.INT
KotlinBuiltIns.FQ_NAMES._long.asString(), CommonClassNames.JAVA_LANG_LONG -> JKJavaPrimitiveTypeImpl.LONG
KotlinBuiltIns.FQ_NAMES._float.asString(), CommonClassNames.JAVA_LANG_FLOAT -> JKJavaPrimitiveTypeImpl.FLOAT
KotlinBuiltIns.FQ_NAMES._double.asString(), CommonClassNames.JAVA_LANG_DOUBLE -> JKJavaPrimitiveTypeImpl.DOUBLE
KotlinBuiltIns.FQ_NAMES._byte.asString(), CommonClassNames.JAVA_LANG_BYTE -> JKJavaPrimitiveTypeImpl.BYTE
KotlinBuiltIns.FQ_NAMES._short.asString(), CommonClassNames.JAVA_LANG_SHORT -> JKJavaPrimitiveTypeImpl.SHORT
else -> null
}
fun JKJavaPrimitiveType.isNumberType() =
this == JKJavaPrimitiveTypeImpl.INT ||
this == JKJavaPrimitiveTypeImpl.LONG ||
this == JKJavaPrimitiveTypeImpl.FLOAT ||
this == JKJavaPrimitiveTypeImpl.DOUBLE
inline fun <reified T : JKType> T.addTypeParametersToRawProjectionType(typeParameter: JKType): T =
if (this is JKClassType && parameters.isEmpty()) {
val parametersCount = classReference.expectedTypeParametersCount()
val typeParameters = List(parametersCount) { typeParameter }
JKClassTypeImpl(
classReference,
typeParameters,
nullability
) as T
} else this
fun JKClassSymbol.expectedTypeParametersCount(): Int {
val resolvedClass = target
return when (resolvedClass) {
is PsiClass -> resolvedClass.typeParameters.size
is KtClass -> resolvedClass.typeParameters.size
else -> 0
}
}
val primitiveTypes =
listOf(
JvmPrimitiveType.BOOLEAN,
JvmPrimitiveType.CHAR,
JvmPrimitiveType.BYTE,
JvmPrimitiveType.SHORT,
JvmPrimitiveType.INT,
JvmPrimitiveType.FLOAT,
JvmPrimitiveType.LONG,
JvmPrimitiveType.DOUBLE
)
fun JKType.arrayFqName(): String =
if (this is JKJavaPrimitiveType)
PrimitiveType.valueOf(jvmPrimitiveType.name).arrayTypeFqName.asString()
else KotlinBuiltIns.FQ_NAMES.array.asString()
fun JKClassSymbol.isArrayType(): Boolean =
fqName in
JKJavaPrimitiveTypeImpl.KEYWORD_TO_INSTANCE.values
.filterIsInstance<JKJavaPrimitiveType>()
.map { PrimitiveType.valueOf(it.jvmPrimitiveType.name).arrayTypeFqName.asString() } +
KotlinBuiltIns.FQ_NAMES.array.asString()
fun JKType.isArrayType() =
when (this) {
is JKClassType -> classReference.isArrayType()
is JKJavaArrayType -> true
else -> false
}
fun JKType.arrayInnerType(): JKType? =
when (this) {
is JKJavaArrayType -> type
is JKClassType ->
if (this.classReference.isArrayType()) this.parameters.singleOrNull()
else null
else -> null
}
val namesOfPrimitiveTypes by lazy {
KotlinBuiltIns.FQ_NAMES.primitiveTypeShortNames.map { it.identifier.decapitalize() }
}
fun JKClassSymbol.isInterface(): Boolean {
val target = target
return when (target) {
is PsiClass -> target.isInterface
is KtClass -> target.isInterface()
is JKClass -> target.classKind == JKClass.ClassKind.INTERFACE
else -> false
}
}
fun JKType.isInterface(): Boolean =
(this as? JKClassType)?.classReference?.isInterface() ?: false
fun JKMethod.nullabilityBySuperMethod(symbolProvider: JKSymbolProvider): Nullability {
if (modality != Modality.OVERRIDE) return Nullability.Default
val superMethodSymbol = findSuperMethodSymbol(symbolProvider) ?: return Nullability.Default
return superMethodSymbol.returnType?.nullability ?: return Nullability.Default
}
private fun JKMethod.findSuperMethodSymbol(symbolProvider: JKSymbolProvider): JKMethodSymbol? =
psi<PsiMethod>()
?.findSuperMethods()
?.firstOrNull()
?.let {
symbolProvider.provideDirectSymbol(it) as? JKMethodSymbol
}
fun JKType.replaceJavaClassWithKotlinClassType(symbolProvider: JKSymbolProvider): JKType =
applyRecursive { type ->
if (type is JKClassType && type.classReference.fqName == "java.lang.Class") {
JKClassTypeImpl(
symbolProvider.provideByFqName(KotlinBuiltIns.FQ_NAMES.kClass),
type.parameters.map { it.replaceJavaClassWithKotlinClassType(symbolProvider) },
Nullability.NotNull
)
} else null
}
@@ -1,185 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.File
val JK_ROOT = File("./j2k/newSrc/org/jetbrains/kotlin/j2k/tree")
val JK_OUT_ROOT = File(JK_ROOT, "visitors")
val JK_KT_FILE = File(JK_ROOT, "k.kt")
val JK_JAVA_FILE = File(JK_ROOT, "j.kt")
val JK_COMMON_FILE = File(JK_ROOT, "jk.kt")
val interfaceRegex = "interface (JK[a-zA-Z]+)\\s?:?\\s?(JK[a-zA-Z]+)?".toRegex()
data class InterfaceData(val name: String, val extends: String?)
fun File.interfaceNames() =
sequenceOf(this)
.map { it.readText() }
.flatMap { interfaceRegex.findAll(it) }
.map { match -> InterfaceData(match.groupValues[1], match.groupValues.getOrNull(2)) }
.toList()
fun String.safeVarName() = when (this) {
"class" -> "klass"
else -> this
}
fun genVisitors(commonData: List<InterfaceData>, uncommonData: List<InterfaceData>, visitorName: String, transformerName: String) {
val interfaceData = commonData + uncommonData
val pkg = "package org.jetbrains.kotlin.j2k.tree.visitors"
fun String.firstCommonInterfaceName(): String {
val data = interfaceData.find { it.name == this }!!
if (commonData.contains(data))
return this
return data.extends!!.firstCommonInterfaceName()
}
File(JK_OUT_ROOT, "$visitorName.kt").writeText(buildString {
appendln(pkg)
appendln()
appendln("import org.jetbrains.kotlin.j2k.tree.*")
appendln()
appendln("interface $visitorName<out R, in D> {")
interfaceData.joinTo(this, separator = "\n") { (name, ext) ->
val nameWithoutPrefix = name.removePrefix("JK")
val argName = nameWithoutPrefix.decapitalize().safeVarName()
val generifyCall = if (name != "JKTreeElement") "= visit${ext!!.removePrefix("JK")}($argName, data)" else ""
"""
| fun visit$nameWithoutPrefix($argName: $name, data: D): R $generifyCall
""".trimMargin()
}
appendln()
appendln("}")
})
File(JK_OUT_ROOT, "${visitorName}Void.kt").writeText(buildString {
appendln(pkg)
appendln()
appendln("import org.jetbrains.kotlin.j2k.tree.*")
appendln()
appendln("interface ${visitorName}Void : $visitorName<Unit, Nothing?> {")
interfaceData.joinTo(this, separator = "\n") { (name, ext) ->
val nameWithoutPrefix = name.removePrefix("JK")
val argName = nameWithoutPrefix.decapitalize().safeVarName()
val arg = "$argName: $name"
val generifyCall = if (name != "JKTreeElement") "= visit${ext!!.removePrefix("JK")}($argName, null)" else ""
"""
| fun visit$nameWithoutPrefix($arg) $generifyCall
| override fun visit$nameWithoutPrefix($arg, data: Nothing?) = visit$nameWithoutPrefix($argName)
""".trimMargin()
}
appendln()
appendln("}")
})
/*File(JK_OUT_ROOT, "$transformerName.kt").writeText(buildString {
appendln(pkg)
appendln()
appendln("import org.jetbrains.kotlin.j2k.tree.*")
appendln()
appendln("interface $transformerName<in D> : JKVisitor<JKTreeElement, D> {")
interfaceData.joinTo(this, separator = "\n") { (name, ext) ->
val nameWithoutPrefix = name.removePrefix("JK")
val argName = nameWithoutPrefix.decapitalize().safeVarName()
val leastCommonName = name.firstCommonInterfaceName()
val cast = "as $leastCommonName".takeIf { leastCommonName == name } ?: ""
val generifyCall = if (name != "JKTreeElement") "= visit${ext!!.removePrefix("JK")}($argName, data) $cast" else ""
"""
| override fun visit$nameWithoutPrefix($argName: $name, data: D): $leastCommonName $generifyCall
""".trimMargin()
}
appendln()
appendln("}")
})
File(JK_OUT_ROOT, "${transformerName}Void.kt").writeText(buildString {
appendln(pkg)
appendln()
appendln("import org.jetbrains.kotlin.j2k.tree.*")
appendln()
appendln("interface ${transformerName}Void : $transformerName<Nothing?> {")
interfaceData.joinTo(this, separator = "\n") { (name, ext) ->
val nameWithoutPrefix = name.removePrefix("JK")
val argName = nameWithoutPrefix.decapitalize().safeVarName()
val arg = "$argName: $name"
val leastCommonName = name.firstCommonInterfaceName()
val cast = "as $leastCommonName".takeIf { leastCommonName == name } ?: ""
val generifyCall = if (name != "JKTreeElement") "= visit${ext!!.removePrefix("JK")}($argName) $cast" else ""
"""
| fun visit$nameWithoutPrefix($arg): $leastCommonName $generifyCall
| override fun visit$nameWithoutPrefix($arg, data: Nothing?): $leastCommonName = visit$nameWithoutPrefix($argName)
""".trimMargin()
}
appendln()
appendln("}")
})*/
}
genVisitors(JK_COMMON_FILE.interfaceNames(), JK_JAVA_FILE.interfaceNames() + JK_KT_FILE.interfaceNames(), "JKVisitor", "JKTransformer")
@@ -1,131 +0,0 @@
package org.jetbrains.kotlin.j2k.tree.visitors
import org.jetbrains.kotlin.j2k.tree.*
interface JKVisitor<out R, in D> {
fun visitTreeElement(treeElement: JKTreeElement, data: D): R
fun visitDeclaration(declaration: JKDeclaration, data: D): R = visitTreeElement(declaration, data)
fun visitImportStatement(importStatement: JKImportStatement, data: D): R = visitTreeElement(importStatement, data)
fun visitFile(file: JKFile, data: D): R = visitTreeElement(file, data)
fun visitClass(klass: JKClass, data: D): R = visitDeclaration(klass, data)
fun visitInheritanceInfo(inheritanceInfo: JKInheritanceInfo, data: D): R = visitTreeElement(inheritanceInfo, data)
fun visitAnnotationList(annotationList: JKAnnotationList, data: D): R = visitTreeElement(annotationList, data)
fun visitAnnotation(annotation: JKAnnotation, data: D): R = visitAnnotationMemberValue(annotation, data)
fun visitAnnotationParameter(annotationParameter: JKAnnotationParameter, data: D): R = visitTreeElement(annotationParameter, data)
fun visitAnnotationNameParameter(annotationNameParameter: JKAnnotationNameParameter, data: D): R = visitAnnotationParameter(annotationNameParameter, data)
fun visitAnnotationListOwner(annotationListOwner: JKAnnotationListOwner, data: D): R = visitTreeElement(annotationListOwner, data)
fun visitMethod(method: JKMethod, data: D): R = visitDeclaration(method, data)
fun visitVariable(variable: JKVariable, data: D): R = visitDeclaration(variable, data)
fun visitForLoopVariable(forLoopVariable: JKForLoopVariable, data: D): R = visitVariable(forLoopVariable, data)
fun visitLocalVariable(localVariable: JKLocalVariable, data: D): R = visitVariable(localVariable, data)
fun visitExtraModifiersOwner(extraModifiersOwner: JKExtraModifiersOwner, data: D): R = visitModifiersListOwner(extraModifiersOwner, data)
fun visitVisibilityOwner(visibilityOwner: JKVisibilityOwner, data: D): R = visitModifiersListOwner(visibilityOwner, data)
fun visitModalityOwner(modalityOwner: JKModalityOwner, data: D): R = visitModifiersListOwner(modalityOwner, data)
fun visitMutabilityOwner(mutabilityOwner: JKMutabilityOwner, data: D): R = visitModifiersListOwner(mutabilityOwner, data)
fun visitModifiersListOwner(modifiersListOwner: JKModifiersListOwner, data: D): R = visitTreeElement(modifiersListOwner, data)
fun visitTypeElement(typeElement: JKTypeElement, data: D): R = visitTreeElement(typeElement, data)
fun visitStatement(statement: JKStatement, data: D): R = visitTreeElement(statement, data)
fun visitBlock(block: JKBlock, data: D): R = visitTreeElement(block, data)
fun visitIdentifier(identifier: JKIdentifier, data: D): R = visitTreeElement(identifier, data)
fun visitNameIdentifier(nameIdentifier: JKNameIdentifier, data: D): R = visitIdentifier(nameIdentifier, data)
fun visitExpression(expression: JKExpression, data: D): R = visitTreeElement(expression, data)
fun visitExpressionStatement(expressionStatement: JKExpressionStatement, data: D): R = visitStatement(expressionStatement, data)
fun visitDeclarationStatement(declarationStatement: JKDeclarationStatement, data: D): R = visitStatement(declarationStatement, data)
fun visitOperatorExpression(operatorExpression: JKOperatorExpression, data: D): R = visitExpression(operatorExpression, data)
fun visitBinaryExpression(binaryExpression: JKBinaryExpression, data: D): R = visitOperatorExpression(binaryExpression, data)
fun visitUnaryExpression(unaryExpression: JKUnaryExpression, data: D): R = visitOperatorExpression(unaryExpression, data)
fun visitPrefixExpression(prefixExpression: JKPrefixExpression, data: D): R = visitUnaryExpression(prefixExpression, data)
fun visitPostfixExpression(postfixExpression: JKPostfixExpression, data: D): R = visitUnaryExpression(postfixExpression, data)
fun visitQualifiedExpression(qualifiedExpression: JKQualifiedExpression, data: D): R = visitExpression(qualifiedExpression, data)
fun visitTypeArgumentList(typeArgumentList: JKTypeArgumentList, data: D): R = visitTreeElement(typeArgumentList, data)
fun visitTypeArgumentListOwner(typeArgumentListOwner: JKTypeArgumentListOwner, data: D): R = visitTreeElement(typeArgumentListOwner, data)
fun visitMethodCallExpression(methodCallExpression: JKMethodCallExpression, data: D): R = visitExpression(methodCallExpression, data)
fun visitFieldAccessExpression(fieldAccessExpression: JKFieldAccessExpression, data: D): R = visitAssignableExpression(fieldAccessExpression, data)
fun visitClassAccessExpression(classAccessExpression: JKClassAccessExpression, data: D): R = visitExpression(classAccessExpression, data)
fun visitArrayAccessExpression(arrayAccessExpression: JKArrayAccessExpression, data: D): R = visitAssignableExpression(arrayAccessExpression, data)
fun visitParenthesizedExpression(parenthesizedExpression: JKParenthesizedExpression, data: D): R = visitExpression(parenthesizedExpression, data)
fun visitTypeCastExpression(typeCastExpression: JKTypeCastExpression, data: D): R = visitExpression(typeCastExpression, data)
fun visitExpressionList(expressionList: JKExpressionList, data: D): R = visitTreeElement(expressionList, data)
fun visitLiteralExpression(literalExpression: JKLiteralExpression, data: D): R = visitExpression(literalExpression, data)
fun visitParameter(parameter: JKParameter, data: D): R = visitVariable(parameter, data)
fun visitStringLiteralExpression(stringLiteralExpression: JKStringLiteralExpression, data: D): R = visitLiteralExpression(stringLiteralExpression, data)
fun visitStubExpression(stubExpression: JKStubExpression, data: D): R = visitExpression(stubExpression, data)
fun visitLoopStatement(loopStatement: JKLoopStatement, data: D): R = visitStatement(loopStatement, data)
fun visitBlockStatement(blockStatement: JKBlockStatement, data: D): R = visitStatement(blockStatement, data)
fun visitBlockStatementWithoutBrackets(blockStatementWithoutBrackets: JKBlockStatementWithoutBrackets, data: D): R = visitStatement(blockStatementWithoutBrackets, data)
fun visitThisExpression(thisExpression: JKThisExpression, data: D): R = visitExpression(thisExpression, data)
fun visitSuperExpression(superExpression: JKSuperExpression, data: D): R = visitExpression(superExpression, data)
fun visitWhileStatement(whileStatement: JKWhileStatement, data: D): R = visitLoopStatement(whileStatement, data)
fun visitDoWhileStatement(doWhileStatement: JKDoWhileStatement, data: D): R = visitLoopStatement(doWhileStatement, data)
fun visitBreakStatement(breakStatement: JKBreakStatement, data: D): R = visitStatement(breakStatement, data)
fun visitBreakWithLabelStatement(breakWithLabelStatement: JKBreakWithLabelStatement, data: D): R = visitBreakStatement(breakWithLabelStatement, data)
fun visitIfStatement(ifStatement: JKIfStatement, data: D): R = visitStatement(ifStatement, data)
fun visitIfElseStatement(ifElseStatement: JKIfElseStatement, data: D): R = visitIfStatement(ifElseStatement, data)
fun visitIfElseExpression(ifElseExpression: JKIfElseExpression, data: D): R = visitExpression(ifElseExpression, data)
fun visitAssignableExpression(assignableExpression: JKAssignableExpression, data: D): R = visitExpression(assignableExpression, data)
fun visitLambdaExpression(lambdaExpression: JKLambdaExpression, data: D): R = visitExpression(lambdaExpression, data)
fun visitDelegationConstructorCall(delegationConstructorCall: JKDelegationConstructorCall, data: D): R = visitMethodCallExpression(delegationConstructorCall, data)
fun visitLabel(label: JKLabel, data: D): R = visitTreeElement(label, data)
fun visitLabelEmpty(labelEmpty: JKLabelEmpty, data: D): R = visitLabel(labelEmpty, data)
fun visitLabelText(labelText: JKLabelText, data: D): R = visitLabel(labelText, data)
fun visitContinueStatement(continueStatement: JKContinueStatement, data: D): R = visitStatement(continueStatement, data)
fun visitLabeledStatement(labeledStatement: JKLabeledStatement, data: D): R = visitStatement(labeledStatement, data)
fun visitEmptyStatement(emptyStatement: JKEmptyStatement, data: D): R = visitStatement(emptyStatement, data)
fun visitTypeParameterList(typeParameterList: JKTypeParameterList, data: D): R = visitTreeElement(typeParameterList, data)
fun visitTypeParameter(typeParameter: JKTypeParameter, data: D): R = visitTreeElement(typeParameter, data)
fun visitTypeParameterListOwner(typeParameterListOwner: JKTypeParameterListOwner, data: D): R = visitTreeElement(typeParameterListOwner, data)
fun visitEnumConstant(enumConstant: JKEnumConstant, data: D): R = visitVariable(enumConstant, data)
fun visitForInStatement(forInStatement: JKForInStatement, data: D): R = visitStatement(forInStatement, data)
fun visitPackageDeclaration(packageDeclaration: JKPackageDeclaration, data: D): R = visitDeclaration(packageDeclaration, data)
fun visitClassLiteralExpression(classLiteralExpression: JKClassLiteralExpression, data: D): R = visitExpression(classLiteralExpression, data)
fun visitAnnotationMemberValue(annotationMemberValue: JKAnnotationMemberValue, data: D): R = visitTreeElement(annotationMemberValue, data)
fun visitField(field: JKField, data: D): R = visitVariable(field, data)
fun visitJavaField(javaField: JKJavaField, data: D): R = visitField(javaField, data)
fun visitJavaMethod(javaMethod: JKJavaMethod, data: D): R = visitMethod(javaMethod, data)
fun visitJavaMethodCallExpression(javaMethodCallExpression: JKJavaMethodCallExpression, data: D): R = visitMethodCallExpression(javaMethodCallExpression, data)
fun visitClassBody(classBody: JKClassBody, data: D): R = visitTreeElement(classBody, data)
fun visitEmptyClassBody(emptyClassBody: JKEmptyClassBody, data: D): R = visitClassBody(emptyClassBody, data)
fun visitJavaNewExpression(javaNewExpression: JKJavaNewExpression, data: D): R = visitExpression(javaNewExpression, data)
fun visitJavaDefaultNewExpression(javaDefaultNewExpression: JKJavaDefaultNewExpression, data: D): R = visitExpression(javaDefaultNewExpression, data)
fun visitJavaNewEmptyArray(javaNewEmptyArray: JKJavaNewEmptyArray, data: D): R = visitExpression(javaNewEmptyArray, data)
fun visitJavaNewArray(javaNewArray: JKJavaNewArray, data: D): R = visitExpression(javaNewArray, data)
fun visitJavaLiteralExpression(javaLiteralExpression: JKJavaLiteralExpression, data: D): R = visitLiteralExpression(javaLiteralExpression, data)
fun visitReturnStatement(returnStatement: JKReturnStatement, data: D): R = visitStatement(returnStatement, data)
fun visitJavaAssertStatement(javaAssertStatement: JKJavaAssertStatement, data: D): R = visitStatement(javaAssertStatement, data)
fun visitJavaForLoopStatement(javaForLoopStatement: JKJavaForLoopStatement, data: D): R = visitLoopStatement(javaForLoopStatement, data)
fun visitJavaPolyadicExpression(javaPolyadicExpression: JKJavaPolyadicExpression, data: D): R = visitExpression(javaPolyadicExpression, data)
fun visitJavaAssignmentExpression(javaAssignmentExpression: JKJavaAssignmentExpression, data: D): R = visitExpression(javaAssignmentExpression, data)
fun visitJavaThrowStatement(javaThrowStatement: JKJavaThrowStatement, data: D): R = visitStatement(javaThrowStatement, data)
fun visitJavaTryStatement(javaTryStatement: JKJavaTryStatement, data: D): R = visitStatement(javaTryStatement, data)
fun visitJavaTryCatchSection(javaTryCatchSection: JKJavaTryCatchSection, data: D): R = visitTreeElement(javaTryCatchSection, data)
fun visitJavaSwitchStatement(javaSwitchStatement: JKJavaSwitchStatement, data: D): R = visitStatement(javaSwitchStatement, data)
fun visitJavaSwitchCase(javaSwitchCase: JKJavaSwitchCase, data: D): R = visitTreeElement(javaSwitchCase, data)
fun visitJavaDefaultSwitchCase(javaDefaultSwitchCase: JKJavaDefaultSwitchCase, data: D): R = visitJavaSwitchCase(javaDefaultSwitchCase, data)
fun visitJavaLabelSwitchCase(javaLabelSwitchCase: JKJavaLabelSwitchCase, data: D): R = visitJavaSwitchCase(javaLabelSwitchCase, data)
fun visitJavaContinueStatement(javaContinueStatement: JKJavaContinueStatement, data: D): R = visitStatement(javaContinueStatement, data)
fun visitJavaSynchronizedStatement(javaSynchronizedStatement: JKJavaSynchronizedStatement, data: D): R = visitStatement(javaSynchronizedStatement, data)
fun visitJavaAnnotationMethod(javaAnnotationMethod: JKJavaAnnotationMethod, data: D): R = visitMethod(javaAnnotationMethod, data)
fun visitKtGetterOrSetter(ktGetterOrSetter: JKKtGetterOrSetter, data: D): R = visitTreeElement(ktGetterOrSetter, data)
fun visitKtEmptyGetterOrSetter(ktEmptyGetterOrSetter: JKKtEmptyGetterOrSetter, data: D): R = visitKtGetterOrSetter(ktEmptyGetterOrSetter, data)
fun visitKtProperty(ktProperty: JKKtProperty, data: D): R = visitField(ktProperty, data)
fun visitKtFunction(ktFunction: JKKtFunction, data: D): R = visitMethod(ktFunction, data)
fun visitKtConstructor(ktConstructor: JKKtConstructor, data: D): R = visitDeclaration(ktConstructor, data)
fun visitKtPrimaryConstructor(ktPrimaryConstructor: JKKtPrimaryConstructor, data: D): R = visitKtConstructor(ktPrimaryConstructor, data)
fun visitKtAssignmentStatement(ktAssignmentStatement: JKKtAssignmentStatement, data: D): R = visitStatement(ktAssignmentStatement, data)
fun visitKtCall(ktCall: JKKtCall, data: D): R = visitMethodCallExpression(ktCall, data)
fun visitKtMethodCallExpression(ktMethodCallExpression: JKKtMethodCallExpression, data: D): R = visitMethodCallExpression(ktMethodCallExpression, data)
fun visitKtAlsoCallExpression(ktAlsoCallExpression: JKKtAlsoCallExpression, data: D): R = visitKtMethodCallExpression(ktAlsoCallExpression, data)
fun visitKtLiteralExpression(ktLiteralExpression: JKKtLiteralExpression, data: D): R = visitLiteralExpression(ktLiteralExpression, data)
fun visitKtWhenStatement(ktWhenStatement: JKKtWhenStatement, data: D): R = visitStatement(ktWhenStatement, data)
fun visitKtWhenCase(ktWhenCase: JKKtWhenCase, data: D): R = visitTreeElement(ktWhenCase, data)
fun visitKtWhenLabel(ktWhenLabel: JKKtWhenLabel, data: D): R = visitTreeElement(ktWhenLabel, data)
fun visitKtElseWhenLabel(ktElseWhenLabel: JKKtElseWhenLabel, data: D): R = visitKtWhenLabel(ktElseWhenLabel, data)
fun visitKtValueWhenLabel(ktValueWhenLabel: JKKtValueWhenLabel, data: D): R = visitKtWhenLabel(ktValueWhenLabel, data)
fun visitKtIsExpression(ktIsExpression: JKKtIsExpression, data: D): R = visitExpression(ktIsExpression, data)
fun visitKtInitDeclaration(ktInitDeclaration: JKKtInitDeclaration, data: D): R = visitDeclaration(ktInitDeclaration, data)
fun visitKtConvertedFromForLoopSyntheticWhileStatement(ktConvertedFromForLoopSyntheticWhileStatement: JKKtConvertedFromForLoopSyntheticWhileStatement, data: D): R = visitStatement(ktConvertedFromForLoopSyntheticWhileStatement, data)
fun visitKtThrowExpression(ktThrowExpression: JKKtThrowExpression, data: D): R = visitExpression(ktThrowExpression, data)
fun visitKtTryExpression(ktTryExpression: JKKtTryExpression, data: D): R = visitExpression(ktTryExpression, data)
fun visitKtTryCatchSection(ktTryCatchSection: JKKtTryCatchSection, data: D): R = visitTreeElement(ktTryCatchSection, data)
fun visitKtAnnotationArrayInitializerExpression(ktAnnotationArrayInitializerExpression: JKKtAnnotationArrayInitializerExpression, data: D): R = visitExpression(ktAnnotationArrayInitializerExpression, data)
}
@@ -1,256 +0,0 @@
package org.jetbrains.kotlin.j2k.tree.visitors
import org.jetbrains.kotlin.j2k.tree.*
interface JKVisitorVoid : JKVisitor<Unit, Nothing?> {
fun visitTreeElement(treeElement: JKTreeElement)
override fun visitTreeElement(treeElement: JKTreeElement, data: Nothing?) = visitTreeElement(treeElement)
fun visitDeclaration(declaration: JKDeclaration) = visitTreeElement(declaration, null)
override fun visitDeclaration(declaration: JKDeclaration, data: Nothing?) = visitDeclaration(declaration)
fun visitImportStatement(importStatement: JKImportStatement) = visitTreeElement(importStatement, null)
override fun visitImportStatement(importStatement: JKImportStatement, data: Nothing?) = visitImportStatement(importStatement)
fun visitFile(file: JKFile) = visitTreeElement(file, null)
override fun visitFile(file: JKFile, data: Nothing?) = visitFile(file)
fun visitClass(klass: JKClass) = visitDeclaration(klass, null)
override fun visitClass(klass: JKClass, data: Nothing?) = visitClass(klass)
fun visitInheritanceInfo(inheritanceInfo: JKInheritanceInfo) = visitTreeElement(inheritanceInfo, null)
override fun visitInheritanceInfo(inheritanceInfo: JKInheritanceInfo, data: Nothing?) = visitInheritanceInfo(inheritanceInfo)
fun visitAnnotationList(annotationList: JKAnnotationList) = visitTreeElement(annotationList, null)
override fun visitAnnotationList(annotationList: JKAnnotationList, data: Nothing?) = visitAnnotationList(annotationList)
fun visitAnnotation(annotation: JKAnnotation) = visitAnnotationMemberValue(annotation, null)
override fun visitAnnotation(annotation: JKAnnotation, data: Nothing?) = visitAnnotation(annotation)
fun visitAnnotationParameter(annotationParameter: JKAnnotationParameter) = visitTreeElement(annotationParameter, null)
override fun visitAnnotationParameter(annotationParameter: JKAnnotationParameter, data: Nothing?) = visitAnnotationParameter(annotationParameter)
fun visitAnnotationNameParameter(annotationNameParameter: JKAnnotationNameParameter) = visitAnnotationParameter(annotationNameParameter, null)
override fun visitAnnotationNameParameter(annotationNameParameter: JKAnnotationNameParameter, data: Nothing?) = visitAnnotationNameParameter(annotationNameParameter)
fun visitAnnotationListOwner(annotationListOwner: JKAnnotationListOwner) = visitTreeElement(annotationListOwner, null)
override fun visitAnnotationListOwner(annotationListOwner: JKAnnotationListOwner, data: Nothing?) = visitAnnotationListOwner(annotationListOwner)
fun visitMethod(method: JKMethod) = visitDeclaration(method, null)
override fun visitMethod(method: JKMethod, data: Nothing?) = visitMethod(method)
fun visitVariable(variable: JKVariable) = visitDeclaration(variable, null)
override fun visitVariable(variable: JKVariable, data: Nothing?) = visitVariable(variable)
fun visitForLoopVariable(forLoopVariable: JKForLoopVariable) = visitVariable(forLoopVariable, null)
override fun visitForLoopVariable(forLoopVariable: JKForLoopVariable, data: Nothing?) = visitForLoopVariable(forLoopVariable)
fun visitLocalVariable(localVariable: JKLocalVariable) = visitVariable(localVariable, null)
override fun visitLocalVariable(localVariable: JKLocalVariable, data: Nothing?) = visitLocalVariable(localVariable)
fun visitExtraModifiersOwner(extraModifiersOwner: JKExtraModifiersOwner) = visitModifiersListOwner(extraModifiersOwner, null)
override fun visitExtraModifiersOwner(extraModifiersOwner: JKExtraModifiersOwner, data: Nothing?) = visitExtraModifiersOwner(extraModifiersOwner)
fun visitVisibilityOwner(visibilityOwner: JKVisibilityOwner) = visitModifiersListOwner(visibilityOwner, null)
override fun visitVisibilityOwner(visibilityOwner: JKVisibilityOwner, data: Nothing?) = visitVisibilityOwner(visibilityOwner)
fun visitModalityOwner(modalityOwner: JKModalityOwner) = visitModifiersListOwner(modalityOwner, null)
override fun visitModalityOwner(modalityOwner: JKModalityOwner, data: Nothing?) = visitModalityOwner(modalityOwner)
fun visitMutabilityOwner(mutabilityOwner: JKMutabilityOwner) = visitModifiersListOwner(mutabilityOwner, null)
override fun visitMutabilityOwner(mutabilityOwner: JKMutabilityOwner, data: Nothing?) = visitMutabilityOwner(mutabilityOwner)
fun visitModifiersListOwner(modifiersListOwner: JKModifiersListOwner) = visitTreeElement(modifiersListOwner, null)
override fun visitModifiersListOwner(modifiersListOwner: JKModifiersListOwner, data: Nothing?) = visitModifiersListOwner(modifiersListOwner)
fun visitTypeElement(typeElement: JKTypeElement) = visitTreeElement(typeElement, null)
override fun visitTypeElement(typeElement: JKTypeElement, data: Nothing?) = visitTypeElement(typeElement)
fun visitStatement(statement: JKStatement) = visitTreeElement(statement, null)
override fun visitStatement(statement: JKStatement, data: Nothing?) = visitStatement(statement)
fun visitBlock(block: JKBlock) = visitTreeElement(block, null)
override fun visitBlock(block: JKBlock, data: Nothing?) = visitBlock(block)
fun visitIdentifier(identifier: JKIdentifier) = visitTreeElement(identifier, null)
override fun visitIdentifier(identifier: JKIdentifier, data: Nothing?) = visitIdentifier(identifier)
fun visitNameIdentifier(nameIdentifier: JKNameIdentifier) = visitIdentifier(nameIdentifier, null)
override fun visitNameIdentifier(nameIdentifier: JKNameIdentifier, data: Nothing?) = visitNameIdentifier(nameIdentifier)
fun visitExpression(expression: JKExpression) = visitTreeElement(expression, null)
override fun visitExpression(expression: JKExpression, data: Nothing?) = visitExpression(expression)
fun visitExpressionStatement(expressionStatement: JKExpressionStatement) = visitStatement(expressionStatement, null)
override fun visitExpressionStatement(expressionStatement: JKExpressionStatement, data: Nothing?) = visitExpressionStatement(expressionStatement)
fun visitDeclarationStatement(declarationStatement: JKDeclarationStatement) = visitStatement(declarationStatement, null)
override fun visitDeclarationStatement(declarationStatement: JKDeclarationStatement, data: Nothing?) = visitDeclarationStatement(declarationStatement)
fun visitOperatorExpression(operatorExpression: JKOperatorExpression) = visitExpression(operatorExpression, null)
override fun visitOperatorExpression(operatorExpression: JKOperatorExpression, data: Nothing?) = visitOperatorExpression(operatorExpression)
fun visitBinaryExpression(binaryExpression: JKBinaryExpression) = visitOperatorExpression(binaryExpression, null)
override fun visitBinaryExpression(binaryExpression: JKBinaryExpression, data: Nothing?) = visitBinaryExpression(binaryExpression)
fun visitUnaryExpression(unaryExpression: JKUnaryExpression) = visitOperatorExpression(unaryExpression, null)
override fun visitUnaryExpression(unaryExpression: JKUnaryExpression, data: Nothing?) = visitUnaryExpression(unaryExpression)
fun visitPrefixExpression(prefixExpression: JKPrefixExpression) = visitUnaryExpression(prefixExpression, null)
override fun visitPrefixExpression(prefixExpression: JKPrefixExpression, data: Nothing?) = visitPrefixExpression(prefixExpression)
fun visitPostfixExpression(postfixExpression: JKPostfixExpression) = visitUnaryExpression(postfixExpression, null)
override fun visitPostfixExpression(postfixExpression: JKPostfixExpression, data: Nothing?) = visitPostfixExpression(postfixExpression)
fun visitQualifiedExpression(qualifiedExpression: JKQualifiedExpression) = visitExpression(qualifiedExpression, null)
override fun visitQualifiedExpression(qualifiedExpression: JKQualifiedExpression, data: Nothing?) = visitQualifiedExpression(qualifiedExpression)
fun visitTypeArgumentList(typeArgumentList: JKTypeArgumentList) = visitTreeElement(typeArgumentList, null)
override fun visitTypeArgumentList(typeArgumentList: JKTypeArgumentList, data: Nothing?) = visitTypeArgumentList(typeArgumentList)
fun visitTypeArgumentListOwner(typeArgumentListOwner: JKTypeArgumentListOwner) = visitTreeElement(typeArgumentListOwner, null)
override fun visitTypeArgumentListOwner(typeArgumentListOwner: JKTypeArgumentListOwner, data: Nothing?) = visitTypeArgumentListOwner(typeArgumentListOwner)
fun visitMethodCallExpression(methodCallExpression: JKMethodCallExpression) = visitExpression(methodCallExpression, null)
override fun visitMethodCallExpression(methodCallExpression: JKMethodCallExpression, data: Nothing?) = visitMethodCallExpression(methodCallExpression)
fun visitFieldAccessExpression(fieldAccessExpression: JKFieldAccessExpression) = visitAssignableExpression(fieldAccessExpression, null)
override fun visitFieldAccessExpression(fieldAccessExpression: JKFieldAccessExpression, data: Nothing?) = visitFieldAccessExpression(fieldAccessExpression)
fun visitClassAccessExpression(classAccessExpression: JKClassAccessExpression) = visitExpression(classAccessExpression, null)
override fun visitClassAccessExpression(classAccessExpression: JKClassAccessExpression, data: Nothing?) = visitClassAccessExpression(classAccessExpression)
fun visitArrayAccessExpression(arrayAccessExpression: JKArrayAccessExpression) = visitAssignableExpression(arrayAccessExpression, null)
override fun visitArrayAccessExpression(arrayAccessExpression: JKArrayAccessExpression, data: Nothing?) = visitArrayAccessExpression(arrayAccessExpression)
fun visitParenthesizedExpression(parenthesizedExpression: JKParenthesizedExpression) = visitExpression(parenthesizedExpression, null)
override fun visitParenthesizedExpression(parenthesizedExpression: JKParenthesizedExpression, data: Nothing?) = visitParenthesizedExpression(parenthesizedExpression)
fun visitTypeCastExpression(typeCastExpression: JKTypeCastExpression) = visitExpression(typeCastExpression, null)
override fun visitTypeCastExpression(typeCastExpression: JKTypeCastExpression, data: Nothing?) = visitTypeCastExpression(typeCastExpression)
fun visitExpressionList(expressionList: JKExpressionList) = visitTreeElement(expressionList, null)
override fun visitExpressionList(expressionList: JKExpressionList, data: Nothing?) = visitExpressionList(expressionList)
fun visitLiteralExpression(literalExpression: JKLiteralExpression) = visitExpression(literalExpression, null)
override fun visitLiteralExpression(literalExpression: JKLiteralExpression, data: Nothing?) = visitLiteralExpression(literalExpression)
fun visitParameter(parameter: JKParameter) = visitVariable(parameter, null)
override fun visitParameter(parameter: JKParameter, data: Nothing?) = visitParameter(parameter)
fun visitStringLiteralExpression(stringLiteralExpression: JKStringLiteralExpression) = visitLiteralExpression(stringLiteralExpression, null)
override fun visitStringLiteralExpression(stringLiteralExpression: JKStringLiteralExpression, data: Nothing?) = visitStringLiteralExpression(stringLiteralExpression)
fun visitStubExpression(stubExpression: JKStubExpression) = visitExpression(stubExpression, null)
override fun visitStubExpression(stubExpression: JKStubExpression, data: Nothing?) = visitStubExpression(stubExpression)
fun visitLoopStatement(loopStatement: JKLoopStatement) = visitStatement(loopStatement, null)
override fun visitLoopStatement(loopStatement: JKLoopStatement, data: Nothing?) = visitLoopStatement(loopStatement)
fun visitBlockStatement(blockStatement: JKBlockStatement) = visitStatement(blockStatement, null)
override fun visitBlockStatement(blockStatement: JKBlockStatement, data: Nothing?) = visitBlockStatement(blockStatement)
fun visitBlockStatementWithoutBrackets(blockStatementWithoutBrackets: JKBlockStatementWithoutBrackets) = visitStatement(blockStatementWithoutBrackets, null)
override fun visitBlockStatementWithoutBrackets(blockStatementWithoutBrackets: JKBlockStatementWithoutBrackets, data: Nothing?) = visitBlockStatementWithoutBrackets(blockStatementWithoutBrackets)
fun visitThisExpression(thisExpression: JKThisExpression) = visitExpression(thisExpression, null)
override fun visitThisExpression(thisExpression: JKThisExpression, data: Nothing?) = visitThisExpression(thisExpression)
fun visitSuperExpression(superExpression: JKSuperExpression) = visitExpression(superExpression, null)
override fun visitSuperExpression(superExpression: JKSuperExpression, data: Nothing?) = visitSuperExpression(superExpression)
fun visitWhileStatement(whileStatement: JKWhileStatement) = visitLoopStatement(whileStatement, null)
override fun visitWhileStatement(whileStatement: JKWhileStatement, data: Nothing?) = visitWhileStatement(whileStatement)
fun visitDoWhileStatement(doWhileStatement: JKDoWhileStatement) = visitLoopStatement(doWhileStatement, null)
override fun visitDoWhileStatement(doWhileStatement: JKDoWhileStatement, data: Nothing?) = visitDoWhileStatement(doWhileStatement)
fun visitBreakStatement(breakStatement: JKBreakStatement) = visitStatement(breakStatement, null)
override fun visitBreakStatement(breakStatement: JKBreakStatement, data: Nothing?) = visitBreakStatement(breakStatement)
fun visitBreakWithLabelStatement(breakWithLabelStatement: JKBreakWithLabelStatement) = visitBreakStatement(breakWithLabelStatement, null)
override fun visitBreakWithLabelStatement(breakWithLabelStatement: JKBreakWithLabelStatement, data: Nothing?) = visitBreakWithLabelStatement(breakWithLabelStatement)
fun visitIfStatement(ifStatement: JKIfStatement) = visitStatement(ifStatement, null)
override fun visitIfStatement(ifStatement: JKIfStatement, data: Nothing?) = visitIfStatement(ifStatement)
fun visitIfElseStatement(ifElseStatement: JKIfElseStatement) = visitIfStatement(ifElseStatement, null)
override fun visitIfElseStatement(ifElseStatement: JKIfElseStatement, data: Nothing?) = visitIfElseStatement(ifElseStatement)
fun visitIfElseExpression(ifElseExpression: JKIfElseExpression) = visitExpression(ifElseExpression, null)
override fun visitIfElseExpression(ifElseExpression: JKIfElseExpression, data: Nothing?) = visitIfElseExpression(ifElseExpression)
fun visitAssignableExpression(assignableExpression: JKAssignableExpression) = visitExpression(assignableExpression, null)
override fun visitAssignableExpression(assignableExpression: JKAssignableExpression, data: Nothing?) = visitAssignableExpression(assignableExpression)
fun visitLambdaExpression(lambdaExpression: JKLambdaExpression) = visitExpression(lambdaExpression, null)
override fun visitLambdaExpression(lambdaExpression: JKLambdaExpression, data: Nothing?) = visitLambdaExpression(lambdaExpression)
fun visitDelegationConstructorCall(delegationConstructorCall: JKDelegationConstructorCall) = visitMethodCallExpression(delegationConstructorCall, null)
override fun visitDelegationConstructorCall(delegationConstructorCall: JKDelegationConstructorCall, data: Nothing?) = visitDelegationConstructorCall(delegationConstructorCall)
fun visitLabel(label: JKLabel) = visitTreeElement(label, null)
override fun visitLabel(label: JKLabel, data: Nothing?) = visitLabel(label)
fun visitLabelEmpty(labelEmpty: JKLabelEmpty) = visitLabel(labelEmpty, null)
override fun visitLabelEmpty(labelEmpty: JKLabelEmpty, data: Nothing?) = visitLabelEmpty(labelEmpty)
fun visitLabelText(labelText: JKLabelText) = visitLabel(labelText, null)
override fun visitLabelText(labelText: JKLabelText, data: Nothing?) = visitLabelText(labelText)
fun visitContinueStatement(continueStatement: JKContinueStatement) = visitStatement(continueStatement, null)
override fun visitContinueStatement(continueStatement: JKContinueStatement, data: Nothing?) = visitContinueStatement(continueStatement)
fun visitLabeledStatement(labeledStatement: JKLabeledStatement) = visitStatement(labeledStatement, null)
override fun visitLabeledStatement(labeledStatement: JKLabeledStatement, data: Nothing?) = visitLabeledStatement(labeledStatement)
fun visitEmptyStatement(emptyStatement: JKEmptyStatement) = visitStatement(emptyStatement, null)
override fun visitEmptyStatement(emptyStatement: JKEmptyStatement, data: Nothing?) = visitEmptyStatement(emptyStatement)
fun visitTypeParameterList(typeParameterList: JKTypeParameterList) = visitTreeElement(typeParameterList, null)
override fun visitTypeParameterList(typeParameterList: JKTypeParameterList, data: Nothing?) = visitTypeParameterList(typeParameterList)
fun visitTypeParameter(typeParameter: JKTypeParameter) = visitTreeElement(typeParameter, null)
override fun visitTypeParameter(typeParameter: JKTypeParameter, data: Nothing?) = visitTypeParameter(typeParameter)
fun visitTypeParameterListOwner(typeParameterListOwner: JKTypeParameterListOwner) = visitTreeElement(typeParameterListOwner, null)
override fun visitTypeParameterListOwner(typeParameterListOwner: JKTypeParameterListOwner, data: Nothing?) = visitTypeParameterListOwner(typeParameterListOwner)
fun visitEnumConstant(enumConstant: JKEnumConstant) = visitVariable(enumConstant, null)
override fun visitEnumConstant(enumConstant: JKEnumConstant, data: Nothing?) = visitEnumConstant(enumConstant)
fun visitForInStatement(forInStatement: JKForInStatement) = visitStatement(forInStatement, null)
override fun visitForInStatement(forInStatement: JKForInStatement, data: Nothing?) = visitForInStatement(forInStatement)
fun visitPackageDeclaration(packageDeclaration: JKPackageDeclaration) = visitDeclaration(packageDeclaration, null)
override fun visitPackageDeclaration(packageDeclaration: JKPackageDeclaration, data: Nothing?) = visitPackageDeclaration(packageDeclaration)
fun visitClassLiteralExpression(classLiteralExpression: JKClassLiteralExpression) = visitExpression(classLiteralExpression, null)
override fun visitClassLiteralExpression(classLiteralExpression: JKClassLiteralExpression, data: Nothing?) = visitClassLiteralExpression(classLiteralExpression)
fun visitAnnotationMemberValue(annotationMemberValue: JKAnnotationMemberValue) = visitTreeElement(annotationMemberValue, null)
override fun visitAnnotationMemberValue(annotationMemberValue: JKAnnotationMemberValue, data: Nothing?) = visitAnnotationMemberValue(annotationMemberValue)
fun visitField(field: JKField) = visitVariable(field, null)
override fun visitField(field: JKField, data: Nothing?) = visitField(field)
fun visitJavaField(javaField: JKJavaField) = visitField(javaField, null)
override fun visitJavaField(javaField: JKJavaField, data: Nothing?) = visitJavaField(javaField)
fun visitJavaMethod(javaMethod: JKJavaMethod) = visitMethod(javaMethod, null)
override fun visitJavaMethod(javaMethod: JKJavaMethod, data: Nothing?) = visitJavaMethod(javaMethod)
fun visitJavaMethodCallExpression(javaMethodCallExpression: JKJavaMethodCallExpression) = visitMethodCallExpression(javaMethodCallExpression, null)
override fun visitJavaMethodCallExpression(javaMethodCallExpression: JKJavaMethodCallExpression, data: Nothing?) = visitJavaMethodCallExpression(javaMethodCallExpression)
fun visitClassBody(classBody: JKClassBody) = visitTreeElement(classBody, null)
override fun visitClassBody(classBody: JKClassBody, data: Nothing?) = visitClassBody(classBody)
fun visitEmptyClassBody(emptyClassBody: JKEmptyClassBody) = visitClassBody(emptyClassBody, null)
override fun visitEmptyClassBody(emptyClassBody: JKEmptyClassBody, data: Nothing?) = visitEmptyClassBody(emptyClassBody)
fun visitJavaNewExpression(javaNewExpression: JKJavaNewExpression) = visitExpression(javaNewExpression, null)
override fun visitJavaNewExpression(javaNewExpression: JKJavaNewExpression, data: Nothing?) = visitJavaNewExpression(javaNewExpression)
fun visitJavaDefaultNewExpression(javaDefaultNewExpression: JKJavaDefaultNewExpression) = visitExpression(javaDefaultNewExpression, null)
override fun visitJavaDefaultNewExpression(javaDefaultNewExpression: JKJavaDefaultNewExpression, data: Nothing?) = visitJavaDefaultNewExpression(javaDefaultNewExpression)
fun visitJavaNewEmptyArray(javaNewEmptyArray: JKJavaNewEmptyArray) = visitExpression(javaNewEmptyArray, null)
override fun visitJavaNewEmptyArray(javaNewEmptyArray: JKJavaNewEmptyArray, data: Nothing?) = visitJavaNewEmptyArray(javaNewEmptyArray)
fun visitJavaNewArray(javaNewArray: JKJavaNewArray) = visitExpression(javaNewArray, null)
override fun visitJavaNewArray(javaNewArray: JKJavaNewArray, data: Nothing?) = visitJavaNewArray(javaNewArray)
fun visitJavaLiteralExpression(javaLiteralExpression: JKJavaLiteralExpression) = visitLiteralExpression(javaLiteralExpression, null)
override fun visitJavaLiteralExpression(javaLiteralExpression: JKJavaLiteralExpression, data: Nothing?) = visitJavaLiteralExpression(javaLiteralExpression)
fun visitReturnStatement(returnStatement: JKReturnStatement) = visitStatement(returnStatement, null)
override fun visitReturnStatement(returnStatement: JKReturnStatement, data: Nothing?) = visitReturnStatement(returnStatement)
fun visitJavaAssertStatement(javaAssertStatement: JKJavaAssertStatement) = visitStatement(javaAssertStatement, null)
override fun visitJavaAssertStatement(javaAssertStatement: JKJavaAssertStatement, data: Nothing?) = visitJavaAssertStatement(javaAssertStatement)
fun visitJavaForLoopStatement(javaForLoopStatement: JKJavaForLoopStatement) = visitLoopStatement(javaForLoopStatement, null)
override fun visitJavaForLoopStatement(javaForLoopStatement: JKJavaForLoopStatement, data: Nothing?) = visitJavaForLoopStatement(javaForLoopStatement)
fun visitJavaPolyadicExpression(javaPolyadicExpression: JKJavaPolyadicExpression) = visitExpression(javaPolyadicExpression, null)
override fun visitJavaPolyadicExpression(javaPolyadicExpression: JKJavaPolyadicExpression, data: Nothing?) = visitJavaPolyadicExpression(javaPolyadicExpression)
fun visitJavaAssignmentExpression(javaAssignmentExpression: JKJavaAssignmentExpression) = visitExpression(javaAssignmentExpression, null)
override fun visitJavaAssignmentExpression(javaAssignmentExpression: JKJavaAssignmentExpression, data: Nothing?) = visitJavaAssignmentExpression(javaAssignmentExpression)
fun visitJavaThrowStatement(javaThrowStatement: JKJavaThrowStatement) = visitStatement(javaThrowStatement, null)
override fun visitJavaThrowStatement(javaThrowStatement: JKJavaThrowStatement, data: Nothing?) = visitJavaThrowStatement(javaThrowStatement)
fun visitJavaTryStatement(javaTryStatement: JKJavaTryStatement) = visitStatement(javaTryStatement, null)
override fun visitJavaTryStatement(javaTryStatement: JKJavaTryStatement, data: Nothing?) = visitJavaTryStatement(javaTryStatement)
fun visitJavaTryCatchSection(javaTryCatchSection: JKJavaTryCatchSection) = visitTreeElement(javaTryCatchSection, null)
override fun visitJavaTryCatchSection(javaTryCatchSection: JKJavaTryCatchSection, data: Nothing?) = visitJavaTryCatchSection(javaTryCatchSection)
fun visitJavaSwitchStatement(javaSwitchStatement: JKJavaSwitchStatement) = visitStatement(javaSwitchStatement, null)
override fun visitJavaSwitchStatement(javaSwitchStatement: JKJavaSwitchStatement, data: Nothing?) = visitJavaSwitchStatement(javaSwitchStatement)
fun visitJavaSwitchCase(javaSwitchCase: JKJavaSwitchCase) = visitTreeElement(javaSwitchCase, null)
override fun visitJavaSwitchCase(javaSwitchCase: JKJavaSwitchCase, data: Nothing?) = visitJavaSwitchCase(javaSwitchCase)
fun visitJavaDefaultSwitchCase(javaDefaultSwitchCase: JKJavaDefaultSwitchCase) = visitJavaSwitchCase(javaDefaultSwitchCase, null)
override fun visitJavaDefaultSwitchCase(javaDefaultSwitchCase: JKJavaDefaultSwitchCase, data: Nothing?) = visitJavaDefaultSwitchCase(javaDefaultSwitchCase)
fun visitJavaLabelSwitchCase(javaLabelSwitchCase: JKJavaLabelSwitchCase) = visitJavaSwitchCase(javaLabelSwitchCase, null)
override fun visitJavaLabelSwitchCase(javaLabelSwitchCase: JKJavaLabelSwitchCase, data: Nothing?) = visitJavaLabelSwitchCase(javaLabelSwitchCase)
fun visitJavaContinueStatement(javaContinueStatement: JKJavaContinueStatement) = visitStatement(javaContinueStatement, null)
override fun visitJavaContinueStatement(javaContinueStatement: JKJavaContinueStatement, data: Nothing?) = visitJavaContinueStatement(javaContinueStatement)
fun visitJavaSynchronizedStatement(javaSynchronizedStatement: JKJavaSynchronizedStatement) = visitStatement(javaSynchronizedStatement, null)
override fun visitJavaSynchronizedStatement(javaSynchronizedStatement: JKJavaSynchronizedStatement, data: Nothing?) = visitJavaSynchronizedStatement(javaSynchronizedStatement)
fun visitJavaAnnotationMethod(javaAnnotationMethod: JKJavaAnnotationMethod) = visitMethod(javaAnnotationMethod, null)
override fun visitJavaAnnotationMethod(javaAnnotationMethod: JKJavaAnnotationMethod, data: Nothing?) = visitJavaAnnotationMethod(javaAnnotationMethod)
fun visitKtGetterOrSetter(ktGetterOrSetter: JKKtGetterOrSetter) = visitTreeElement(ktGetterOrSetter, null)
override fun visitKtGetterOrSetter(ktGetterOrSetter: JKKtGetterOrSetter, data: Nothing?) = visitKtGetterOrSetter(ktGetterOrSetter)
fun visitKtEmptyGetterOrSetter(ktEmptyGetterOrSetter: JKKtEmptyGetterOrSetter) = visitKtGetterOrSetter(ktEmptyGetterOrSetter, null)
override fun visitKtEmptyGetterOrSetter(ktEmptyGetterOrSetter: JKKtEmptyGetterOrSetter, data: Nothing?) = visitKtEmptyGetterOrSetter(ktEmptyGetterOrSetter)
fun visitKtProperty(ktProperty: JKKtProperty) = visitField(ktProperty, null)
override fun visitKtProperty(ktProperty: JKKtProperty, data: Nothing?) = visitKtProperty(ktProperty)
fun visitKtFunction(ktFunction: JKKtFunction) = visitMethod(ktFunction, null)
override fun visitKtFunction(ktFunction: JKKtFunction, data: Nothing?) = visitKtFunction(ktFunction)
fun visitKtConstructor(ktConstructor: JKKtConstructor) = visitDeclaration(ktConstructor, null)
override fun visitKtConstructor(ktConstructor: JKKtConstructor, data: Nothing?) = visitKtConstructor(ktConstructor)
fun visitKtPrimaryConstructor(ktPrimaryConstructor: JKKtPrimaryConstructor) = visitKtConstructor(ktPrimaryConstructor, null)
override fun visitKtPrimaryConstructor(ktPrimaryConstructor: JKKtPrimaryConstructor, data: Nothing?) = visitKtPrimaryConstructor(ktPrimaryConstructor)
fun visitKtAssignmentStatement(ktAssignmentStatement: JKKtAssignmentStatement) = visitStatement(ktAssignmentStatement, null)
override fun visitKtAssignmentStatement(ktAssignmentStatement: JKKtAssignmentStatement, data: Nothing?) = visitKtAssignmentStatement(ktAssignmentStatement)
fun visitKtCall(ktCall: JKKtCall) = visitMethodCallExpression(ktCall, null)
override fun visitKtCall(ktCall: JKKtCall, data: Nothing?) = visitKtCall(ktCall)
fun visitKtMethodCallExpression(ktMethodCallExpression: JKKtMethodCallExpression) = visitMethodCallExpression(ktMethodCallExpression, null)
override fun visitKtMethodCallExpression(ktMethodCallExpression: JKKtMethodCallExpression, data: Nothing?) = visitKtMethodCallExpression(ktMethodCallExpression)
fun visitKtAlsoCallExpression(ktAlsoCallExpression: JKKtAlsoCallExpression) = visitKtMethodCallExpression(ktAlsoCallExpression, null)
override fun visitKtAlsoCallExpression(ktAlsoCallExpression: JKKtAlsoCallExpression, data: Nothing?) = visitKtAlsoCallExpression(ktAlsoCallExpression)
fun visitKtLiteralExpression(ktLiteralExpression: JKKtLiteralExpression) = visitLiteralExpression(ktLiteralExpression, null)
override fun visitKtLiteralExpression(ktLiteralExpression: JKKtLiteralExpression, data: Nothing?) = visitKtLiteralExpression(ktLiteralExpression)
fun visitKtWhenStatement(ktWhenStatement: JKKtWhenStatement) = visitStatement(ktWhenStatement, null)
override fun visitKtWhenStatement(ktWhenStatement: JKKtWhenStatement, data: Nothing?) = visitKtWhenStatement(ktWhenStatement)
fun visitKtWhenCase(ktWhenCase: JKKtWhenCase) = visitTreeElement(ktWhenCase, null)
override fun visitKtWhenCase(ktWhenCase: JKKtWhenCase, data: Nothing?) = visitKtWhenCase(ktWhenCase)
fun visitKtWhenLabel(ktWhenLabel: JKKtWhenLabel) = visitTreeElement(ktWhenLabel, null)
override fun visitKtWhenLabel(ktWhenLabel: JKKtWhenLabel, data: Nothing?) = visitKtWhenLabel(ktWhenLabel)
fun visitKtElseWhenLabel(ktElseWhenLabel: JKKtElseWhenLabel) = visitKtWhenLabel(ktElseWhenLabel, null)
override fun visitKtElseWhenLabel(ktElseWhenLabel: JKKtElseWhenLabel, data: Nothing?) = visitKtElseWhenLabel(ktElseWhenLabel)
fun visitKtValueWhenLabel(ktValueWhenLabel: JKKtValueWhenLabel) = visitKtWhenLabel(ktValueWhenLabel, null)
override fun visitKtValueWhenLabel(ktValueWhenLabel: JKKtValueWhenLabel, data: Nothing?) = visitKtValueWhenLabel(ktValueWhenLabel)
fun visitKtIsExpression(ktIsExpression: JKKtIsExpression) = visitExpression(ktIsExpression, null)
override fun visitKtIsExpression(ktIsExpression: JKKtIsExpression, data: Nothing?) = visitKtIsExpression(ktIsExpression)
fun visitKtInitDeclaration(ktInitDeclaration: JKKtInitDeclaration) = visitDeclaration(ktInitDeclaration, null)
override fun visitKtInitDeclaration(ktInitDeclaration: JKKtInitDeclaration, data: Nothing?) = visitKtInitDeclaration(ktInitDeclaration)
fun visitKtConvertedFromForLoopSyntheticWhileStatement(ktConvertedFromForLoopSyntheticWhileStatement: JKKtConvertedFromForLoopSyntheticWhileStatement) = visitStatement(ktConvertedFromForLoopSyntheticWhileStatement, null)
override fun visitKtConvertedFromForLoopSyntheticWhileStatement(ktConvertedFromForLoopSyntheticWhileStatement: JKKtConvertedFromForLoopSyntheticWhileStatement, data: Nothing?) = visitKtConvertedFromForLoopSyntheticWhileStatement(ktConvertedFromForLoopSyntheticWhileStatement)
fun visitKtThrowExpression(ktThrowExpression: JKKtThrowExpression) = visitExpression(ktThrowExpression, null)
override fun visitKtThrowExpression(ktThrowExpression: JKKtThrowExpression, data: Nothing?) = visitKtThrowExpression(ktThrowExpression)
fun visitKtTryExpression(ktTryExpression: JKKtTryExpression) = visitExpression(ktTryExpression, null)
override fun visitKtTryExpression(ktTryExpression: JKKtTryExpression, data: Nothing?) = visitKtTryExpression(ktTryExpression)
fun visitKtTryCatchSection(ktTryCatchSection: JKKtTryCatchSection) = visitTreeElement(ktTryCatchSection, null)
override fun visitKtTryCatchSection(ktTryCatchSection: JKKtTryCatchSection, data: Nothing?) = visitKtTryCatchSection(ktTryCatchSection)
fun visitKtAnnotationArrayInitializerExpression(ktAnnotationArrayInitializerExpression: JKKtAnnotationArrayInitializerExpression) = visitExpression(ktAnnotationArrayInitializerExpression, null)
override fun visitKtAnnotationArrayInitializerExpression(ktAnnotationArrayInitializerExpression: JKKtAnnotationArrayInitializerExpression, data: Nothing?) = visitKtAnnotationArrayInitializerExpression(ktAnnotationArrayInitializerExpression)
}
@@ -33,6 +33,6 @@ class AfterConversionPass(val project: Project, val postProcessor: PostProcessor
null
}
postProcessor.doAdditionalProcessing(kotlinFile, rangeMarker, null)
postProcessor.doAdditionalProcessing(kotlinFile, rangeMarker)
}
}
@@ -39,7 +39,7 @@ import java.util.*
interface PostProcessor {
fun insertImport(file: KtFile, fqName: FqName)
fun doAdditionalProcessing(file: KtFile, rangeMarker: RangeMarker?, settings: ConverterSettings?)
fun doAdditionalProcessing(file: KtFile, rangeMarker: RangeMarker?)
}
enum class ParseContext {
@@ -48,9 +48,9 @@ enum class ParseContext {
}
class JavaToKotlinConverter(
private val project: Project,
private val settings: ConverterSettings,
private val services: JavaToKotlinConverterServices
private val project: Project,
private val settings: ConverterSettings,
private val services: JavaToKotlinConverterServices
) {
private val LOG = Logger.getInstance("#org.jetbrains.kotlin.j2k.JavaToKotlinConverter")
@@ -141,25 +141,25 @@ class JavaToKotlinConverter(
}
private data class ReferenceInfo(
val reference: PsiReference,
val target: PsiElement,
val file: PsiFile,
val processings: Collection<UsageProcessing>
val reference: PsiReference,
val target: PsiElement,
val file: PsiFile,
val processings: Collection<UsageProcessing>
) {
val depth: Int by lazy(LazyThreadSafetyMode.NONE) { target.parentsWithSelf.takeWhile { it !is PsiFile }.count() }
val offset: Int by lazy(LazyThreadSafetyMode.NONE) { reference.element.textRange.startOffset }
}
private fun buildExternalCodeProcessing(
usageProcessings: Map<PsiElement, Collection<UsageProcessing>>,
inConversionScope: (PsiElement) -> Boolean
usageProcessings: Map<PsiElement, Collection<UsageProcessing>>,
inConversionScope: (PsiElement) -> Boolean
): ExternalCodeProcessing? {
if (usageProcessings.isEmpty()) return null
val map: Map<PsiElement, Collection<UsageProcessing>> = usageProcessings.values
.flatten()
.filter { it.javaCodeProcessors.isNotEmpty() || it.kotlinCodeProcessors.isNotEmpty() }
.groupBy { it.targetElement }
.flatten()
.filter { it.javaCodeProcessors.isNotEmpty() || it.kotlinCodeProcessors.isNotEmpty() }
.groupBy { it.targetElement }
if (map.isEmpty()) return null
return object: ExternalCodeProcessing {
@@ -176,14 +176,14 @@ class JavaToKotlinConverter(
progress.checkCanceled()
ProgressManager.getInstance().runProcess(
{
val searchJava = processings.any { it.javaCodeProcessors.isNotEmpty() }
val searchKotlin = processings.any { it.kotlinCodeProcessors.isNotEmpty() }
services.referenceSearcher.findUsagesForExternalCodeProcessing(psiElement, searchJava, searchKotlin)
.filterNot { inConversionScope(it.element) }
.mapTo(refs) { ReferenceInfo(it, psiElement, it.element.containingFile, processings) }
},
ProgressPortionReporter(progress, i / map.size.toDouble(), 1.0 / map.size))
{
val searchJava = processings.any { it.javaCodeProcessors.isNotEmpty() }
val searchKotlin = processings.any { it.kotlinCodeProcessors.isNotEmpty() }
services.referenceSearcher.findUsagesForExternalCodeProcessing(psiElement, searchJava, searchKotlin)
.filterNot { inConversionScope(it.element) }
.mapTo(refs) { ReferenceInfo(it, psiElement, it.element.containingFile, processings) }
},
ProgressPortionReporter(progress, i / map.size.toDouble(), 1.0 / map.size))
}
@@ -245,37 +245,37 @@ class JavaToKotlinConverter(
private var pass = 1
fun <TInputItem, TOutputItem> processItems(
fractionPortion: Double,
inputItems: Iterable<TInputItem>,
processItem: (TInputItem) -> TOutputItem
fractionPortion: Double,
inputItems: Iterable<TInputItem>,
processItem: (TInputItem) -> TOutputItem
): List<TOutputItem> {
val outputItems = ArrayList<TOutputItem>()
// we use special process with EmptyProgressIndicator to avoid changing text in our progress by inheritors search inside etc
ProgressManager.getInstance().runProcess(
{
progress?.text = "$progressText ($fileCountText) - pass $pass of 3"
{
progress?.text = "$progressText ($fileCountText) - pass $pass of 3"
for ((i, item) in inputItems.withIndex()) {
progress?.checkCanceled()
progress?.fraction = fraction + fractionPortion * i / fileCount
for ((i, item) in inputItems.withIndex()) {
progress?.checkCanceled()
progress?.fraction = fraction + fractionPortion * i / fileCount
progress?.text2 = files!![i].virtualFile.presentableUrl
progress?.text2 = files!![i].virtualFile.presentableUrl
outputItems.add(processItem(item))
}
outputItems.add(processItem(item))
}
pass++
fraction += fractionPortion
},
EmptyProgressIndicator())
pass++
fraction += fractionPortion
},
EmptyProgressIndicator())
return outputItems
}
}
private class ProgressPortionReporter(
indicator: ProgressIndicator,
private val start: Double,
private val portion: Double
indicator: ProgressIndicator,
private val start: Double,
private val portion: Double
) : DelegatingProgressIndicator(indicator) {
init {
@@ -1,5 +1,6 @@
// !forceNotNullTypes: false
// !specifyLocalVariableTypeByDefault: true
import java.util.HashSet;
class Foo {
void foo(HashSet o) {
+1 -1
View File
@@ -1,6 +1,6 @@
package test
import javaApi.Listener
import javaApi.*
class Test {
private val listener = Listener { visibility -> val a = visibility and 1 }
@@ -1,19 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k
abstract class AbstractNewJavaToKotlinConverterNewSingleFileTest : AbstractNewJavaToKotlinConverterSingleFileTest()
@@ -1,48 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.j2k.IdeaNewJavaToKotlinServices
import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor
import org.jetbrains.kotlin.idea.j2k.NewJ2KPostProcessingRegistrarImpl
import org.jetbrains.kotlin.psi.KtPsiFactory
import java.io.File
abstract class AbstractNewJavaToKotlinConverterSingleFileTest : AbstractJavaToKotlinConverterSingleFileTest() {
override fun fileToKotlin(text: String, settings: ConverterSettings, project: Project): String {
val file = createJavaFile(text)
val factory = KtPsiFactory(project, true)
val postProcessor = J2kPostProcessor(true, NewJ2KPostProcessingRegistrarImpl)
return NewJavaToKotlinConverter(project, settings, IdeaNewJavaToKotlinServices).filesToKotlin(listOf(file)).map {
factory.createFileWithLightClassSupport("Dummy.kt", it, file)
}.map {
CommandProcessor.getInstance().runUndoTransparentAction {
postProcessor.doAdditionalProcessing(it, null, settings)
}
it.text
}.single()
}
override fun provideExpectedFile(javaPath: String): File =
File(javaPath.replace(".java", ".new.kt")).takeIf { it.exists() }
?: super.provideExpectedFile(javaPath)
}
@@ -1,107 +0,0 @@
/*
* Copyright 2010-2018 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.google.gson.Gson
import com.intellij.openapi.util.registry.Registry
import com.intellij.rt.execution.junit.FileComparisonFailure
import com.intellij.util.diff.Diff
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
import java.text.SimpleDateFormat
import java.util.*
import kotlin.concurrent.thread
import org.jetbrains.kotlin.j2k.NewJ2KTestView.stat
abstract class AbstractNewJavaToKotlinConverterStructureSingleFileTest : AbstractNewJavaToKotlinConverterSingleFileTest() {
override fun compareResults(expectedFile: File, actual: String) {
results.totalExpected += expectedFile.readLines().count()
results.totalActual += actual.lines().count()
val beforeReg = Registry.`is`("diff.patience.alg")
Registry.get("diff.patience.alg").setValue(true)
Diff.buildChanges(expectedFile.readText(), actual)?.toList().orEmpty().forEach { change ->
results.totalDiffPlus += change.inserted
results.totalDiffMinus += change.deleted
}
Registry.get("diff.patience.alg").setValue(beforeReg)
KotlinTestUtils.assertEqualsToFile(expectedFile, actual) {
val file = createKotlinFile(it)
file.dumpStructureText()
}
}
override fun doTest(javaPath: String) {
val testName = Thread.currentThread().stackTrace[5].let { "${it.className}.${it.methodName}" }
try {
super.doTest(javaPath)
results.passes += testName
} catch (e: AssertionError) {
results.assertionFailures += testName
throw e
} catch (e: FileComparisonFailure) {
results.assertionFailures += testName
throw e
} catch (e: Throwable) {
results.exceptionFailures += testName
throw e
}
}
companion object {
fun initializeForTests() {
Runtime.getRuntime().addShutdownHook(thread(start = false) {
println("CLOSED")
val dateString = dateFormat.format(Date())
File("./test_report/$dateString.txt").apply {
parentFile.mkdirs()
writeText(results.stat())
}
File("./test_report/$dateString.json").apply {
writeText(
results.serialize()
)
}
})
}
data class TestResults(
val assertionFailures: MutableSet<String> = mutableSetOf(),
val exceptionFailures: MutableSet<String> = mutableSetOf(),
val passes: MutableSet<String> = mutableSetOf(),
var totalDiffPlus: Int = 0,
var totalDiffMinus: Int = 0,
var totalExpected: Int = 0,
var totalActual: Int = 0
) {
fun serialize(): String {
return Gson().toJson(this)
}
}
fun loadTestResults(text: String): TestResults {
return Gson().fromJson(text, TestResults::class.java)
}
val results: TestResults by lazy {
initializeForTests()
TestResults()
}
val dateFormat = SimpleDateFormat("yyyy-MM-dd__HH-mm-ss")
}
}
@@ -1,412 +0,0 @@
/*
* Copyright 2010-2018 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.icons.AllIcons
import com.intellij.ui.components.JBLabel
import com.intellij.ui.components.JBList
import com.intellij.ui.components.JBScrollPane
import com.intellij.ui.components.JBTabbedPane
import com.intellij.uiDesigner.core.GridConstraints
import com.intellij.uiDesigner.core.GridLayoutManager
import org.jetbrains.kotlin.j2k.AbstractNewJavaToKotlinConverterStructureSingleFileTest.Companion.TestResults
import org.jetbrains.kotlin.j2k.AbstractNewJavaToKotlinConverterStructureSingleFileTest.Companion.dateFormat
import org.jetbrains.kotlin.j2k.AbstractNewJavaToKotlinConverterStructureSingleFileTest.Companion.loadTestResults
import java.awt.Component
import java.awt.Graphics
import java.awt.event.ActionEvent
import java.awt.event.KeyEvent
import java.awt.event.KeyListener
import java.io.File
import java.util.*
import javax.swing.*
import javax.swing.SwingUtilities.invokeLater
import java.awt.Toolkit
import java.awt.datatransfer.StringSelection
object NewJ2KTestView {
private fun Int.percentOf(b: Int, format: String = "%.2f%%"): String = String.format(format, this * 100F / b)
private infix fun Int.signedPercentOf(b: Int): String = this.percentOf(b, "%+.2f%%")
private val Int.signedStr get() = String.format("%+d", this)
fun TestResults.stat(): String {
return """
+++ $totalDiffPlus(${totalDiffPlus.percentOf(totalExpected)}, ${totalDiffPlus.percentOf(totalActual)})
--- $totalDiffMinus(${totalDiffMinus.percentOf(totalExpected)}, ${totalDiffMinus.percentOf(totalActual)})
Expected: $totalExpected
Actual: $totalActual
${shortStat()}
""".trimIndent()
}
fun TestResults.shortStat(): String {
return "P: ${passes.size}, A: ${assertionFailures.size}, E: ${exceptionFailures.size}"
}
private enum class TestState(val s: String? = null) {
Removed("-"),
New("+"),
Passed("P"),
Assert("A"),
Exception("E");
override fun toString(): String {
return s ?: this.name
}
}
private val TestResults.tests: Map<String, TestState>
get() {
return (passes.map { it to TestState.Passed } +
assertionFailures.map { it to TestState.Assert } +
exceptionFailures.map { it to TestState.Exception }).toMap()
}
private data class TestResultsDiff(val before: TestResults, val after: TestResults) {
val testsDiff: List<Pair<String, Pair<TestState, TestState>>>
val minusDiff = after.totalDiffMinus - before.totalDiffMinus
val plusDiff = after.totalDiffPlus - before.totalDiffPlus
val actualDiff = after.totalActual - before.totalActual
val expectedDiff = after.totalExpected - before.totalExpected
val testsAfter = after.tests
val testsBefore = before.tests
init {
val removedTests =
testsBefore.entries.asSequence()
.filter { it.key !in testsAfter.keys }
.mapNotNull { (name, oldState) -> name to (TestState.Removed to oldState) }
testsDiff =
(testsAfter.entries - testsBefore.entries)
.map { (name, newState) ->
name to (newState to (testsBefore[name] ?: TestState.New))
} + removedTests
}
val testDiffByState =
testsDiff
.groupBy({ (_, state) -> state }, { (name, _) -> name })
.toSortedMap(Comparator { (f1, s1), (f2, s2) ->
if (f1 != f2) return@Comparator f1.compareTo(f2)
return@Comparator s1.compareTo(s2)
})
.map { (stateDiff, names) -> stateDiff to names.sorted() }
}
private class CompareSelectTab(tabs: JBTabbedPane, val after: TestResults) : IndexTab(tabs) {
override fun action() {
val before = variants[list.selectedIndex].second
tabs.removeTabAt(tabs.selectedIndex)
val tabIndex = tabs.tabCount
tabs.addTab("Compare", DiffTab(tabs, TestResultsDiff(before, after)))
tabs.selectedIndex = tabIndex
}
}
private class DiffTab(tabs: JBTabbedPane, val diff: TestResultsDiff) : BaseReportTab(tabs) {
init {
initComponents()
}
override fun listTests(): String {
return diff.testDiffByState.joinToString(separator = "\n") { (stateDiff, names) ->
val (a, b) = stateDiff
names.joinToString(separator = "\n") { "$b/$a: $it" }
}
}
private inline fun countTestDiffWithStates(crossinline predicate: (Pair<TestState, TestState>) -> Boolean): Int {
return diff.testDiffByState
.filter { (stateDiff, _) -> predicate(stateDiff) }
.sumBy { (_, names) -> names.size }
}
override fun stat(): String {
fun countTestDiffPlusMinus(state: TestState): Pair<Int, Int> =
countTestDiffWithStates { (a, _) -> a == state } to countTestDiffWithStates { (_, b) -> b == state }
fun testCountLine(state: TestState): String {
val (has, had) = countTestDiffPlusMinus(state)
val testCountAfter = diff.testsAfter.size
val testCountBefore = diff.testsBefore.size
return "$state: " +
"${(-had).signedStr} (${had.percentOf(testCountBefore)}), " +
"${has.signedStr} (${has.percentOf(testCountAfter)})"
}
return """
+++ ${diff.plusDiff.signedStr} (${diff.plusDiff signedPercentOf diff.after.totalExpected}, ${diff.plusDiff signedPercentOf diff.after.totalActual})
--- ${diff.minusDiff.signedStr} (${diff.minusDiff signedPercentOf diff.after.totalExpected}, ${diff.minusDiff signedPercentOf diff.after.totalActual})
Expected: ${diff.expectedDiff.signedStr} (${diff.expectedDiff signedPercentOf diff.after.totalExpected}) (${diff.after.totalExpected})
Actual: ${diff.actualDiff.signedStr} (${diff.actualDiff signedPercentOf diff.after.totalActual}) (${diff.after.totalActual})
${testCountLine(TestState.Passed)}
${testCountLine(TestState.Assert)}
${testCountLine(TestState.Exception)}
""".trimIndent()
}
override fun fillTests(addWithIcon: (List<String>, icon: Icon) -> Unit) {
fun iconFor(state: TestState): Icon = when (state) {
TestState.New -> AllIcons.General.Add
TestState.Removed -> AllIcons.General.Remove
TestState.Passed -> AllIcons.RunConfigurations.TestPassed
TestState.Assert -> AllIcons.RunConfigurations.TestFailed
TestState.Exception -> AllIcons.RunConfigurations.TestError
}
fun iconFor(stateChange: Pair<TestState, TestState>): Icon {
val (after, before) = stateChange
val icon1 = iconFor(before)
val icon2 = iconFor(after)
return object : Icon {
override fun getIconHeight(): Int {
return maxOf(icon1.iconHeight, icon2.iconHeight)
}
override fun paintIcon(c: Component?, g: Graphics?, x: Int, y: Int) {
icon1.paintIcon(c, g, x, y)
icon2.paintIcon(c, g, x + icon1.iconWidth, y)
}
override fun getIconWidth(): Int {
return icon1.iconWidth + icon2.iconWidth
}
}
}
diff.testDiffByState.forEach { (state, names) ->
addWithIcon(names, iconFor(state))
}
}
}
private class ReportTab(tabs: JBTabbedPane, val results: TestResults) : BaseReportTab(tabs) {
init {
initComponents()
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_C, 0), "COMPARE")
actionMap.put("COMPARE", object : AbstractAction() {
override fun actionPerformed(e: ActionEvent) {
val index = tabs.tabCount
val tab = CompareSelectTab(tabs, results)
tab.fillData()
tabs.addTab("Select", tab)
tabs.selectedIndex = index
}
})
}
override fun listTests(): String {
return results.tests
.entries
.groupBy({ it.value }, { it.key }).toSortedMap()
.entries
.joinToString(separator = "\n") { (state, names) ->
names.sorted().joinToString(separator = "\n") { "$state: $it" }
}
}
override fun stat(): String {
return results.stat()
}
override fun fillTests(addWithIcon: (List<String>, icon: Icon) -> Unit) {
addWithIcon(results.passes.sorted(), AllIcons.RunConfigurations.TestState.Green2)
addWithIcon(results.assertionFailures.sorted(), AllIcons.RunConfigurations.TestState.Yellow2)
addWithIcon(results.exceptionFailures.sorted(), AllIcons.RunConfigurations.TestState.Red2)
}
}
private abstract class BaseReportTab(val tabs: JBTabbedPane) : JPanel() {
abstract fun stat(): String
abstract fun fillTests(addWithIcon: (List<String>, icon: Icon) -> Unit)
abstract fun listTests(): String
fun initComponents() {
layout = GridLayoutManager(2, 1)
val report = JBLabel("<html>" + stat().replace("\n", "<br>") + "</html>")
add(report, GridConstraints().also {
it.row = 0
it.fill = GridConstraints.FILL_HORIZONTAL
it.anchor = GridConstraints.ANCHOR_NORTH
})
val testsScroll = run {
val model = DefaultListModel<JBLabel>()
fun addWithIcon(list: List<String>, icon: Icon) {
for (i in list) {
model.addElement(JBLabel(i.substringAfter("$"), icon, SwingConstants.LEFT))
}
}
fillTests(addWithIcon = ::addWithIcon)
val list = JBList(model)
list.cellRenderer = ListCellRenderer<JBLabel> { list, value, index, isSelected, cellHasFocus -> value!! }
JBScrollPane(list)
}
add(testsScroll, GridConstraints().also {
it.row = 1
it.anchor = GridConstraints.ANCHOR_NORTH
it.fill = GridConstraints.FILL_BOTH
})
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_E, 0), "EXPORT")
actionMap.put("EXPORT", object : AbstractAction() {
override fun actionPerformed(e: ActionEvent) {
val selection = StringSelection("${stat()}\nTests:\n${listTests()}")
val clipboard = Toolkit.getDefaultToolkit().systemClipboard
clipboard.setContents(selection, selection)
}
})
}
}
private open class IndexTab(val tabs: JBTabbedPane) : JPanel() {
val model = DefaultListModel<String>()
val list = JBList(model)
open fun action() {
val (date, report) = variants[list.selectedIndex]
val tabIndex = tabs.tabCount
tabs.addTab("$date", ReportTab(tabs, report))
tabs.selectedIndex = tabIndex
}
fun fillData() {
model.clear()
for ((index, variant) in variants.withIndex()) {
val (date, results) = variant
model.addElement("$index -> $date (${results.shortStat()})")
}
}
init {
layout = GridLayoutManager(1, 1)
add(list, GridConstraints().apply { fill = GridConstraints.FILL_BOTH })
list.addKeyListener(object : KeyListener {
var typed = ""
fun upd() {
if (typed.isEmpty()) {
list.selectedIndex = -1
} else {
list.selectedIndex = variants.indices.firstOrNull { it.toString().startsWith(typed) } ?: -1
}
}
override fun keyTyped(e: KeyEvent) {
val c = e.keyChar
when {
Character.isDigit(c) -> {
typed += c
upd()
e.consume()
}
e.extendedKeyCode == KeyEvent.VK_ENTER -> {
action()
e.consume()
}
}
}
override fun keyPressed(e: KeyEvent) {
if (e.extendedKeyCode == KeyEvent.VK_BACK_SPACE) {
typed = typed.dropLast(1)
upd()
e.consume()
}
}
override fun keyReleased(e: KeyEvent?) {
}
})
}
}
private val variants: MutableList<Pair<Date, TestResults>> = mutableListOf()
private fun load() {
variants.clear()
variants.addAll(File("./test_report").walkTopDown().filter { it.extension == "json" }.map {
dateFormat.parse(it.nameWithoutExtension) to loadTestResults(
it.readText()
)
})
variants.sortBy { it.first }
}
@JvmStatic
fun main(args: Array<String>) {
invokeLater {
val frame = object : JFrame("New J2K Test View") {
val tabs = JBTabbedPane()
val index = IndexTab(tabs)
init {
tabs.addTab("Index", index)
this.rootPane.actionMap.put("ESCAPE", object : AbstractAction() {
override fun actionPerformed(e: ActionEvent) {
tabs.selectedIndex = 0
}
})
this.rootPane.actionMap.put("CLOSE_TAB", object : AbstractAction() {
override fun actionPerformed(e: ActionEvent) {
if (tabs.selectedIndex != 0) {
tabs.removeTabAt(tabs.selectedIndex)
}
}
})
this.rootPane.actionMap.put("RELOAD", object : AbstractAction() {
override fun actionPerformed(e: ActionEvent) {
load()
index.fillData()
}
})
this.rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, KeyEvent.META_DOWN_MASK), "CLOSE_TAB")
this.rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.META_DOWN_MASK), "RELOAD")
this.rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "ESCAPE")
contentPane = tabs
}
}
frame.pack()
frame.setSize(800, 800)
frame.defaultCloseOperation = JFrame.EXIT_ON_CLOSE
frame.isVisible = true
load()
frame.index.fillData()
}
}
}
@@ -1,54 +0,0 @@
/*
* Copyright 2010-2018 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.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("j2k/testData/newFileOrElement")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class NewJavaToKotlinConverterNewSingleFileTestGenerated extends AbstractNewJavaToKotlinConverterNewSingleFileTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInNewFileOrElement() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("j2k/testData/newFileOrElement"), Pattern.compile("^(.+)\\.java$"), TargetBackend.ANY, true);
}
@TestMetadata("j2k/testData/newFileOrElement/first")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class First extends AbstractNewJavaToKotlinConverterNewSingleFileTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInFirst() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("j2k/testData/newFileOrElement/first"), Pattern.compile("^(.+)\\.java$"), TargetBackend.ANY, true);
}
@TestMetadata("First.java")
public void testFirst() throws Exception {
runTest("j2k/testData/newFileOrElement/first/First.java");
}
@TestMetadata("Modifiers.java")
public void testModifiers() throws Exception {
runTest("j2k/testData/newFileOrElement/first/Modifiers.java");
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,38 +0,0 @@
/*
* Copyright 2010-2018 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.psi.PsiComment
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.psi.KtFile
internal fun KtFile.dumpStructureText(): String {
val sb = StringBuilder()
this.accept(object : PsiElementVisitor() {
override fun visitElement(element: PsiElement?) {
if (element is PsiComment) {
return
}
if (element is PsiWhiteSpace) {
if (sb.lastOrNull() !in listOf(' ', '{', '}', '(', ')')) {
sb.append(" ")
}
return
}
if (element is LeafPsiElement) {
sb.append(element.text)
return
}
element?.acceptChildren(this)
}
})
return sb.toString().trim()
}