New J2K: Separate new j2k from old j2k
This commit is contained in:
committed by
Ilya Kirillov
parent
e6f0a242fd
commit
c827247272
@@ -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
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
-39
@@ -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
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
-43
@@ -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] }
|
||||
}
|
||||
-29
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
-45
@@ -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() }
|
||||
}
|
||||
}
|
||||
-78
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
-67
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-20
@@ -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)
|
||||
}
|
||||
}
|
||||
-53
@@ -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()
|
||||
}
|
||||
}
|
||||
-70
@@ -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
|
||||
}
|
||||
}
|
||||
-53
@@ -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)
|
||||
}
|
||||
}
|
||||
-56
@@ -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
|
||||
}
|
||||
-33
@@ -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)
|
||||
}
|
||||
}
|
||||
-30
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
-63
@@ -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
|
||||
}
|
||||
-185
@@ -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
@@ -1,6 +1,6 @@
|
||||
package test
|
||||
|
||||
import javaApi.Listener
|
||||
import javaApi.*
|
||||
|
||||
class Test {
|
||||
private val listener = Listener { visibility -> val a = visibility and 1 }
|
||||
|
||||
-19
@@ -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)
|
||||
}
|
||||
-107
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
-54
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
-4751
File diff suppressed because it is too large
Load Diff
Generated
-4751
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()
|
||||
}
|
||||
Reference in New Issue
Block a user