diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/ConversionsRunner.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/ConversionsRunner.kt index 364cc7684ae..79155c60214 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/ConversionsRunner.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/ConversionsRunner.kt @@ -41,6 +41,8 @@ object ConversionsRunner { +ThrowStatementConversion() +ArrayInitializerConversion(context) +TryStatementConversion(context) + +EnumFieldAccessConversion(context) + +StaticMemberAccessConversion(context) +SynchronizedStatementConversion(context) +DefaultArgumentsConversion(context) +ConstructorConversion(context) diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/EnumFieldAccessConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/EnumFieldAccessConversion.kt new file mode 100644 index 00000000000..d614e2c6ae7 --- /dev/null +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/EnumFieldAccessConversion.kt @@ -0,0 +1,40 @@ +/* + * 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.nj2k.conversions + +import com.intellij.psi.PsiEnumConstant +import org.jetbrains.kotlin.nj2k.ConversionContext +import org.jetbrains.kotlin.nj2k.tree.* +import org.jetbrains.kotlin.nj2k.tree.impl.* +import org.jetbrains.kotlin.psi.psiUtil.containingClass + + +class EnumFieldAccessConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() { + override fun applyToElement(element: JKTreeElement): JKTreeElement { + if (element !is JKFieldAccessExpression) return recurse(element) + if ((element.parent as? JKQualifiedExpression)?.selector == element) return recurse(element) + val enumsClassSymbol = element.identifier.enumClassSymbol() ?: return recurse(element) + + return recurse( + JKQualifiedExpressionImpl( + JKClassAccessExpressionImpl(enumsClassSymbol), + JKKtQualifierImpl.DOT, + JKFieldAccessExpressionImpl(element.identifier) + ) + ) + } + + private fun JKFieldSymbol.enumClassSymbol(): JKClassSymbol? = + when { + this is JKMultiverseFieldSymbol && target is PsiEnumConstant -> + context.symbolProvider.provideUniverseSymbol(target.containingClass!!) as JKClassSymbol + this is JKMultiverseKtEnumEntrySymbol -> + context.symbolProvider.provideDirectSymbol(target.containingClass()!!) as JKClassSymbol + this is JKUniverseFieldSymbol && target is JKEnumConstant -> + context.symbolProvider.provideUniverseSymbol(target.parentOfType()!!) as JKClassSymbol + else -> null + } +} \ No newline at end of file diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/StaticMemberAccessConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/StaticMemberAccessConversion.kt new file mode 100644 index 00000000000..0881e984665 --- /dev/null +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/StaticMemberAccessConversion.kt @@ -0,0 +1,85 @@ +/* + * 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.nj2k.conversions + +import com.intellij.lang.jvm.JvmModifier +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiModifierListOwner +import com.intellij.psi.util.parentOfType +import org.jetbrains.kotlin.j2k.getContainingClass +import org.jetbrains.kotlin.nj2k.ConversionContext +import org.jetbrains.kotlin.nj2k.asQualifierWithThisAsSelector +import org.jetbrains.kotlin.nj2k.copyTreeAndDetach +import org.jetbrains.kotlin.nj2k.tree.* +import org.jetbrains.kotlin.nj2k.tree.impl.* +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtObjectDeclaration +import org.jetbrains.kotlin.psi.psiUtil.containingClass +import org.jetbrains.kotlin.utils.addToStdlib.safeAs + + +class StaticMemberAccessConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() { + override fun applyToElement(element: JKTreeElement): JKTreeElement { + val symbol = + when (element) { + is JKFieldAccessExpression -> element.identifier + is JKMethodCallExpression -> element.identifier + else -> null + } ?: return recurse(element) + if (element.asQualifierWithThisAsSelector() != null) return recurse(element) + if (symbol.isStaticMember()) { + val containingClassSymbol = symbol.containingClassSymbol() ?: return recurse(element) + return recurse( + JKQualifiedExpressionImpl( + JKClassAccessExpressionImpl(containingClassSymbol), + JKKtQualifierImpl.DOT, + element.copyTreeAndDetach() as JKExpression + ) + ) + } + return recurse(element) + + } + + private fun JKSymbol.isStaticMember(): Boolean { + val target = target + return when (target) { + is PsiModifierListOwner -> target.hasModifier(JvmModifier.STATIC) + is KtElement -> target.parentOfType() + ?.safeAs() + ?.isCompanion() == true + is JKTreeElement -> + target.safeAs()?.modifiers()?.contains(ExtraModifier.STATIC) == true + || target.parentOfType()?.classKind == JKClass.ClassKind.OBJECT + else -> false + } + } + + private fun JKSymbol.containingClassSymbol(): JKClassSymbol? { + val target = target + return when (target) { + is KtElement -> + target.parentOfType()?.let { klass -> + if (klass is KtObjectDeclaration && klass.isCompanion()) klass.containingClass() + else klass + }?.let { context.symbolProvider.provideDirectSymbol(it) } + + is PsiElement -> target.getContainingClass()?.let { + context.symbolProvider.provideDirectSymbol(it) + } + + is JKTreeElement -> + target.parentOfType()?.let { klass -> + if (klass.classKind == JKClass.ClassKind.COMPANION) klass.parentOfType() + else klass + }?.let { context.symbolProvider.provideUniverseSymbol(it) } + else -> error("bad isStaticMember") + } as JKClassSymbol? + } + +} +