New J2K: Add qualifiers for static methods, fields & enum consts

This commit is contained in:
Ilya Kirillov
2019-02-13 12:52:19 +03:00
committed by Ilya Kirillov
parent b355572aab
commit 1fa0ddcbe8
3 changed files with 127 additions and 0 deletions
@@ -41,6 +41,8 @@ object ConversionsRunner {
+ThrowStatementConversion()
+ArrayInitializerConversion(context)
+TryStatementConversion(context)
+EnumFieldAccessConversion(context)
+StaticMemberAccessConversion(context)
+SynchronizedStatementConversion(context)
+DefaultArgumentsConversion(context)
+ConstructorConversion(context)
@@ -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<JKClass>()!!) as JKClassSymbol
else -> null
}
}
@@ -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<KtClassOrObject>()
?.safeAs<KtObjectDeclaration>()
?.isCompanion() == true
is JKTreeElement ->
target.safeAs<JKModalityOwner>()?.modifiers()?.contains(ExtraModifier.STATIC) == true
|| target.parentOfType<JKClass>()?.classKind == JKClass.ClassKind.OBJECT
else -> false
}
}
private fun JKSymbol.containingClassSymbol(): JKClassSymbol? {
val target = target
return when (target) {
is KtElement ->
target.parentOfType<KtClassOrObject>()?.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<JKClass>()?.let { klass ->
if (klass.classKind == JKClass.ClassKind.COMPANION) klass.parentOfType()
else klass
}?.let { context.symbolProvider.provideUniverseSymbol(it) }
else -> error("bad isStaticMember")
} as JKClassSymbol?
}
}