From 704b3bd2e6706dd1663e3ef3ca0bc5536a5b3410 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Tue, 24 Sep 2019 12:00:51 +0300 Subject: [PATCH] New J2K: always print real fqNames for static calls As fqNames of some symbols may change during conversion E.g, when moving Java static method to Kotlin companion object #KT-19607 fixed #KT-32903 fixed #KT-33743 fixed #KT-33556 fixed --- .../kotlin/nj2k/ConversionsRunner.kt | 10 ++- .../jetbrains/kotlin/nj2k/JKSymbolProvider.kt | 38 ++++++++--- .../jetbrains/kotlin/nj2k/NewCodeBuilder.kt | 28 ++++---- ...veRedundantQualifiersForCallsConversion.kt | 36 +++++++++++ .../StaticMemberAccessConversion.kt | 64 +++---------------- .../nj2k/conversions/TypeMappingConversion.kt | 9 ++- .../org/jetbrains/kotlin/nj2k/expressions.kt | 14 ++++ .../kotlin/nj2k/symbols/JKClassSymbol.kt | 5 +- .../kotlin/nj2k/symbols/JKPackageSymbol.kt | 20 ++++-- .../jetbrains/kotlin/nj2k/symbols/JKSymbol.kt | 5 +- .../jetbrains/kotlin/nj2k/symbols/utils.kt | 37 ++++++++--- .../jetbrains/kotlin/nj2k/tree/elements.kt | 4 +- .../staticMembers/StaticImport.external.kt | 4 ++ .../newJ2k/staticMembers/StaticImport.java | 7 ++ .../newJ2k/staticMembers/StaticImport.kt | 7 ++ .../StaticMemmberAccessedViaInstance.java | 12 ++++ .../StaticMemmberAccessedViaInstance.kt | 16 +++++ .../StaticQualifiedByInheritor.java | 13 ++++ .../StaticQualifiedByInheritor.kt | 12 ++++ ...otlinConverterSingleFileTestGenerated.java | 15 +++++ 20 files changed, 258 insertions(+), 98 deletions(-) create mode 100644 nj2k/src/org/jetbrains/kotlin/nj2k/conversions/RemoveRedundantQualifiersForCallsConversion.kt create mode 100644 nj2k/testData/newJ2k/staticMembers/StaticImport.external.kt create mode 100644 nj2k/testData/newJ2k/staticMembers/StaticImport.java create mode 100644 nj2k/testData/newJ2k/staticMembers/StaticImport.kt create mode 100644 nj2k/testData/newJ2k/staticMembers/StaticMemmberAccessedViaInstance.java create mode 100644 nj2k/testData/newJ2k/staticMembers/StaticMemmberAccessedViaInstance.kt create mode 100644 nj2k/testData/newJ2k/staticMembers/StaticQualifiedByInheritor.java create mode 100644 nj2k/testData/newJ2k/staticMembers/StaticQualifiedByInheritor.kt diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/ConversionsRunner.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/ConversionsRunner.kt index 0981f7dadea..2e732e60074 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/ConversionsRunner.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/ConversionsRunner.kt @@ -17,10 +17,12 @@ package org.jetbrains.kotlin.nj2k import org.jetbrains.kotlin.nj2k.conversions.* +import org.jetbrains.kotlin.nj2k.tree.JKLambdaExpression +import org.jetbrains.kotlin.nj2k.tree.JKParameter import org.jetbrains.kotlin.nj2k.tree.JKTreeRoot +import org.jetbrains.kotlin.utils.addToStdlib.safeAs object ConversionsRunner { - private fun createConversions(context: NewJ2kConverterContext) = listOf( NonCodeElementsConversion(context), JavaModifiersConversion(context), @@ -38,7 +40,6 @@ object ConversionsRunner { ArrayInitializerConversion(context), TryStatementConversion(context), EnumFieldAccessConversion(context), - StaticMemberAccessConversion(context), SynchronizedStatementConversion(context), JetbrainsNullableAnnotationsConverter(context), DefaultArgumentsConversion(context), @@ -69,9 +70,14 @@ object ConversionsRunner { ClassToObjectPromotionConversion(context), RemoveWrongExtraModifiersForSingleFunctionsConversion(context), MethodReferenceToLambdaConversion(context), + TypeMappingConversion(context) { typeElement -> + typeElement.parent.safeAs()?.parent is JKLambdaExpression + }, BuiltinMembersConversion(context), ImplicitCastsConversion(context), LiteralConversion(context), + StaticMemberAccessConversion(context), + RemoveRedundantQualifiersForCallsConversion(context), FilterImportsConversion(context), MoveInitBlocksToTheEndConversion(context), AddElementsInfoConversion(context) diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/JKSymbolProvider.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/JKSymbolProvider.kt index 7ba199ae3ac..35ffaa725dd 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/JKSymbolProvider.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/JKSymbolProvider.kt @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.psi.* class JKSymbolProvider(project: Project, module: Module, contextElement: PsiElement) { private val symbolsByFqName = mutableMapOf() val symbolsByPsi = mutableMapOf() - val symbolsByJK = mutableMapOf() + private val symbolsByJK = mutableMapOf() private val resolver = JKResolver(project, module, contextElement) private val elementVisitor = ElementVisitor() @@ -68,14 +68,15 @@ class JKSymbolProvider(project: Project, module: Module, contextElement: PsiElem ) else JKUnresolvedMethod(reference, typeFactory)) 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 - is JKUniverseTypeParameterSymbol -> it.target = jk as JKTypeParameter + fun provideUniverseSymbol(psi: PsiElement, declaration: JKDeclaration): JKSymbol = provideUniverseSymbol(psi).also { symbol -> + when (symbol) { + is JKUniverseClassSymbol -> symbol.target = declaration as JKClass + is JKUniverseFieldSymbol -> symbol.target = declaration as JKVariable + is JKUniverseMethodSymbol -> symbol.target = declaration as JKMethod + is JKUniverseTypeParameterSymbol -> symbol.target = declaration as JKTypeParameter + is JKUniversePackageSymbol -> symbol.target = declaration as JKPackageDeclaration } - symbolsByJK[jk] = it + symbolsByJK[declaration] = symbol } fun provideUniverseSymbol(psi: PsiElement): JKSymbol = @@ -85,6 +86,7 @@ class JKSymbolProvider(project: Project, module: Module, contextElement: PsiElem is PsiMethod -> JKUniverseMethodSymbol(typeFactory) is PsiTypeParameter -> JKUniverseTypeParameterSymbol(typeFactory) is PsiClass -> JKUniverseClassSymbol(typeFactory) + is PsiPackageStatement -> JKUniversePackageSymbol(typeFactory) else -> TODO() } } @@ -108,6 +110,22 @@ class JKSymbolProvider(project: Project, module: Module, contextElement: PsiElem JKUniverseMethodSymbol(typeFactory).also { it.target = jk } } as JKMethodSymbol + fun provideUniverseSymbol(jk: JKTypeParameter): JKTypeParameterSymbol = symbolsByJK.getOrPut(jk) { + JKUniverseTypeParameterSymbol(typeFactory).also { it.target = jk } + } as JKTypeParameterSymbol + + fun provideUniverseSymbol(jk: JKPackageDeclaration): JKPackageSymbol = symbolsByJK.getOrPut(jk) { + JKUniversePackageSymbol(typeFactory).also { it.target = jk } + } as JKPackageSymbol + + fun provideUniverseSymbol(jk: JKDeclaration): JKUniverseSymbol<*>? = when (jk) { + is JKClass -> provideUniverseSymbol(jk) + is JKVariable -> provideUniverseSymbol(jk) + is JKMethod -> provideUniverseSymbol(jk) + is JKTypeParameter -> provideUniverseSymbol(jk) + else -> null + } as? JKUniverseSymbol<*> + fun provideClassSymbol(fqName: FqName): JKClassSymbol = symbolsByFqName.getOrPutIfNotNull(fqName.asString()) { @@ -175,6 +193,10 @@ class JKSymbolProvider(project: Project, module: Module, contextElement: PsiElem provideUniverseSymbol(classParameter) } + override fun visitPackageStatement(statement: PsiPackageStatement) { + provideUniverseSymbol(statement) + } + override fun visitFile(file: PsiFile) { file.acceptChildren(this) } diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/NewCodeBuilder.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/NewCodeBuilder.kt index 8b40e235c60..f2830483a1f 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/NewCodeBuilder.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/NewCodeBuilder.kt @@ -6,9 +6,7 @@ package org.jetbrains.kotlin.nj2k import org.jetbrains.kotlin.j2k.ast.Nullability -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.nj2k.symbols.JKClassSymbol -import org.jetbrains.kotlin.nj2k.symbols.getDisplayName +import org.jetbrains.kotlin.nj2k.symbols.* import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.visitors.JKVisitorWithCommentsPrinting import org.jetbrains.kotlin.nj2k.types.* @@ -160,7 +158,7 @@ class NewCodeBuilder(context: NewJ2kConverterContext) { } override fun visitClassAccessExpressionRaw(classAccessExpression: JKClassAccessExpression) { - printer.renderClassSymbol(classAccessExpression.identifier, classAccessExpression) + printer.renderSymbol(classAccessExpression.identifier, classAccessExpression) } override fun visitFileRaw(file: JKFile) { @@ -522,7 +520,7 @@ class NewCodeBuilder(context: NewJ2kConverterContext) { } override fun visitCallExpressionRaw(callExpression: JKCallExpression) { - printer.printWithNoIndent(FqName(callExpression.identifier.fqName).shortName().asString().escaped()) + printer.renderSymbol(callExpression.identifier, callExpression) callExpression.typeArgumentList.accept(this) printer.par { callExpression.arguments.accept(this) @@ -603,7 +601,7 @@ class NewCodeBuilder(context: NewJ2kConverterContext) { if (newExpression.isAnonymousClass) { printer.printWithNoIndent("object : ") } - printer.renderClassSymbol(newExpression.classSymbol, newExpression) + printer.renderSymbol(newExpression.classSymbol, newExpression) newExpression.typeArgumentList.accept(this) if (!newExpression.classSymbol.isInterface() || newExpression.arguments.arguments.isNotEmpty()) { printer.par(ParenthesisKind.ROUND) { @@ -667,11 +665,11 @@ class NewCodeBuilder(context: NewJ2kConverterContext) { } override fun visitFieldAccessExpressionRaw(fieldAccessExpression: JKFieldAccessExpression) { - printer.printWithNoIndent(fieldAccessExpression.identifier.name.escaped()) + printer.renderSymbol(fieldAccessExpression.identifier, fieldAccessExpression) } override fun visitPackageAccessExpressionRaw(packageAccessExpression: JKPackageAccessExpression) { - printer.printWithNoIndent(packageAccessExpression.identifier.name.escaped()) + printer.renderSymbol(packageAccessExpression.identifier, packageAccessExpression) } override fun visitMethodReferenceExpressionRaw(methodReferenceExpression: JKMethodReferenceExpression) { @@ -896,8 +894,10 @@ private class JKPrinter( printWithNoIndent(kind.close) } - private fun JKClassSymbol.needFqName(): Boolean = - fqName !in mappedToKotlinFqNames + private fun JKSymbol.needFqName(): Boolean { + if (this !is JKClassSymbol && !isStaticMember && !isEnumConstant) return false + return fqName !in mappedToKotlinFqNames + } private fun JKType.renderTypeInfo() { print(elementInfoStorage.getOrCreateInfoForElement(this).render()) @@ -920,7 +920,7 @@ private class JKPrinter( type.renderTypeInfo() when (type) { is JKClassType -> { - renderClassSymbol(type.classReference, owner) + renderSymbol(type.classReference, owner) } is JKContextType -> return is JKStarProjectionType -> @@ -951,9 +951,9 @@ private class JKPrinter( } } - fun renderClassSymbol(classSymbol: JKClassSymbol, owner: JKTreeElement?) { - val needFqName = classSymbol.needFqName() && owner?.isSelectorOfQualifiedExpression() != true - val displayName = if (needFqName) classSymbol.getDisplayName() else classSymbol.name + fun renderSymbol(symbol: JKSymbol, owner: JKTreeElement?) { + val needFqName = symbol.needFqName() && owner?.isSelectorOfQualifiedExpression() != true + val displayName = if (needFqName) symbol.getDisplayName() else symbol.name printWithNoIndent(displayName.escapedAsQualifiedName()) } diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/RemoveRedundantQualifiersForCallsConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/RemoveRedundantQualifiersForCallsConversion.kt new file mode 100644 index 00000000000..c18f7b44e22 --- /dev/null +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/RemoveRedundantQualifiersForCallsConversion.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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 org.jetbrains.kotlin.nj2k.NewJ2kConverterContext +import org.jetbrains.kotlin.nj2k.identifier +import org.jetbrains.kotlin.nj2k.symbols.JKUniverseClassSymbol +import org.jetbrains.kotlin.nj2k.symbols.isStaticMember +import org.jetbrains.kotlin.nj2k.tree.* + + +class RemoveRedundantQualifiersForCallsConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) { + override fun applyToElement(element: JKTreeElement): JKTreeElement { + if (element !is JKQualifiedExpression) return recurse(element) + val needRemoveQualifier = when (val receiver = element.receiver.receiverExpression()) { + is JKClassAccessExpression -> receiver.identifier is JKUniverseClassSymbol + is JKFieldAccessExpression, is JKCallExpression -> + receiver !is JKClassAccessExpression && element.selector.identifier?.isStaticMember == true + else -> false + } + if (needRemoveQualifier) { + element.invalidate() + return recurse(element.selector.withNonCodeElementsFrom(element.receiver).withNonCodeElementsFrom(element)) + } + return recurse(element) + } + + private fun JKExpression.receiverExpression() = when (this) { + is JKQualifiedExpression -> selector + else -> this + } +} \ 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 index 39ea85ab25f..97b3670fffc 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/StaticMemberAccessConversion.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/StaticMemberAccessConversion.kt @@ -5,35 +5,23 @@ package org.jetbrains.kotlin.nj2k.conversions - -import com.intellij.lang.jvm.JvmModifier -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiModifierListOwner -import org.jetbrains.kotlin.j2k.getContainingClass import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext import org.jetbrains.kotlin.nj2k.asQualifierWithThisAsSelector import org.jetbrains.kotlin.nj2k.symbols.JKClassSymbol -import org.jetbrains.kotlin.nj2k.symbols.JKSymbol +import org.jetbrains.kotlin.nj2k.symbols.isStaticMember import org.jetbrains.kotlin.nj2k.tree.* -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.psi.psiUtil.getStrictParentOfType -import org.jetbrains.kotlin.utils.addToStdlib.safeAs - class StaticMemberAccessConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) { override fun applyToElement(element: JKTreeElement): JKTreeElement { - val symbol = - when (element) { - is JKFieldAccessExpression -> element.identifier - is JKCallExpression -> element.identifier - else -> null - } ?: return recurse(element) + if (element !is JKQualifiedExpression) return recurse(element) + val symbol = when (element) { + is JKFieldAccessExpression -> element.identifier + is JKCallExpression -> element.identifier + else -> null + } ?: return recurse(element) if (element.asQualifierWithThisAsSelector() != null) return recurse(element) - if (symbol.isStaticMember()) { - val containingClassSymbol = symbol.containingClassSymbol() ?: return recurse(element) + if (symbol.isStaticMember) { + val containingClassSymbol = symbol.declaredIn as? JKClassSymbol ?: return recurse(element) return recurse( JKQualifiedExpression( JKClassAccessExpression(containingClassSymbol), @@ -43,39 +31,5 @@ class StaticMemberAccessConversion(context: NewJ2kConverterContext) : RecursiveA } return recurse(element) } - - private fun JKSymbol.isStaticMember(): Boolean = when (val target = target) { - is PsiModifierListOwner -> target.hasModifier(JvmModifier.STATIC) - is KtElement -> target.getStrictParentOfType() - ?.safeAs() - ?.isCompanion() == true - is JKTreeElement -> - target.safeAs()?.hasOtherModifier(OtherModifier.STATIC) == true - || target.parentOfType()?.classKind == JKClass.ClassKind.OBJECT - else -> false - } - - private fun JKSymbol.containingClassSymbol(): JKClassSymbol? { - val target = target - return when (target) { - is KtElement -> - target.getStrictParentOfType()?.let { klass -> - if (klass is KtObjectDeclaration && klass.isCompanion()) klass.containingClass() - else klass - }?.let { symbolProvider.provideDirectSymbol(it) } - - is PsiElement -> target.getContainingClass()?.let { - symbolProvider.provideDirectSymbol(it) - } - - is JKTreeElement -> - target.parentOfType()?.let { klass -> - if (klass.classKind == JKClass.ClassKind.COMPANION) klass.parentOfType() - else klass - }?.let { symbolProvider.provideUniverseSymbol(it) } - else -> error("bad isStaticMember") - } as JKClassSymbol? - } - } diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/TypeMappingConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/TypeMappingConversion.kt index 4baa8d2638b..321da24b0fe 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/TypeMappingConversion.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/TypeMappingConversion.kt @@ -17,11 +17,16 @@ import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.types.* import org.jetbrains.kotlin.psi.KtClass -class TypeMappingConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) { +class TypeMappingConversion( + context: NewJ2kConverterContext, + inline val filter: (typeElement: JKTypeElement) -> Boolean = { true } +) : RecursiveApplicableConversionBase(context) { override fun applyToElement(element: JKTreeElement): JKTreeElement { when (element) { is JKTypeElement -> { - element.type = element.type.mapType(element) + if (filter(element)) { + element.type = element.type.mapType(element) + } } is JKNewExpression -> { val newClassSymbol = element.classSymbol.mapClassSymbol() diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/expressions.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/expressions.kt index 1cb4ce25f40..6d05fa4c095 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/expressions.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/expressions.kt @@ -10,6 +10,7 @@ import com.intellij.psi.tree.TokenSet import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.nj2k.conversions.RecursiveApplicableConversionBase import org.jetbrains.kotlin.nj2k.symbols.JKMethodSymbol +import org.jetbrains.kotlin.nj2k.symbols.JKSymbol import org.jetbrains.kotlin.nj2k.symbols.JKUnresolvedMethod import org.jetbrains.kotlin.nj2k.tree.* @@ -339,3 +340,16 @@ fun JKClass.isLocalClass(): Boolean = val JKClass.declarationList: List get() = classBody.declarations + +val JKTreeElement.identifier: JKSymbol? + get() = when (this) { + is JKFieldAccessExpression -> identifier + is JKCallExpression -> identifier + is JKClassAccessExpression -> identifier + is JKPackageAccessExpression -> identifier + is JKNewExpression -> classSymbol + else -> null + } + +val JKClass.isObjectOrCompanionObject + get() = classKind == JKClass.ClassKind.OBJECT || classKind == JKClass.ClassKind.COMPANION \ No newline at end of file diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/JKClassSymbol.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/JKClassSymbol.kt index f6728058e84..09cb3220bf4 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/JKClassSymbol.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/JKClassSymbol.kt @@ -17,7 +17,10 @@ sealed class JKClassSymbol : JKSymbol class JKUniverseClassSymbol(override val typeFactory: JKTypeFactory) : JKClassSymbol(), JKUniverseSymbol { override lateinit var target: JKClass override val name: String - get() = target.name.value + get() = when { + target.classKind == JKClass.ClassKind.COMPANION -> "Companion" + else -> target.name.value + } } class JKMultiverseClassSymbol( diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/JKPackageSymbol.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/JKPackageSymbol.kt index 35bf6f946d8..237b8df0d5e 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/JKPackageSymbol.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/JKPackageSymbol.kt @@ -6,15 +6,25 @@ package org.jetbrains.kotlin.nj2k.symbols import com.intellij.psi.PsiPackage -import org.jetbrains.kotlin.nj2k.JKSymbolProvider +import org.jetbrains.kotlin.nj2k.tree.JKPackageDeclaration import org.jetbrains.kotlin.nj2k.types.JKTypeFactory -sealed class JKPackageSymbol : JKSymbol { - abstract override val target: PsiPackage -} +sealed class JKPackageSymbol : JKSymbol class JKMultiversePackageSymbol( override val target: PsiPackage, override val typeFactory: JKTypeFactory -) : JKPackageSymbol(), JKMultiverseSymbol \ No newline at end of file +) : JKPackageSymbol(), JKMultiverseSymbol { + override val declaredIn: JKSymbol? + get() = null +} + +class JKUniversePackageSymbol( + override val typeFactory: JKTypeFactory +) : JKPackageSymbol(), JKUniverseSymbol { + override lateinit var target: JKPackageDeclaration + + override val declaredIn: JKSymbol? + get() = null +} \ No newline at end of file diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/JKSymbol.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/JKSymbol.kt index d854597a850..5c4b67faf0b 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/JKSymbol.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/JKSymbol.kt @@ -48,7 +48,10 @@ interface JKUniverseSymbol : JKSymbol { get() = target.name.value override val declaredIn: JKSymbol? - get() = target.parentOfType()?.let { symbolProvider.symbolsByJK[it] } + get() = target.parentOfType()?.let { symbolProvider.provideUniverseSymbol(it) } + ?: target.parentOfType()?.packageDeclaration + ?.takeIf { it.name.value.isNotEmpty() } + ?.let { symbolProvider.provideUniverseSymbol(it) } } interface JKMultiverseSymbol : JKSymbol where T : PsiNamedElement, T : PsiElement { diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/utils.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/utils.kt index 4bfbde98362..f60316eaa3e 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/utils.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/utils.kt @@ -5,18 +5,18 @@ package org.jetbrains.kotlin.nj2k.symbols +import com.intellij.lang.jvm.JvmModifier import com.intellij.psi.PsiElement +import com.intellij.psi.PsiEnumConstant import com.intellij.psi.PsiMethod -import com.intellij.psi.PsiModifier +import com.intellij.psi.PsiModifierListOwner import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName import org.jetbrains.kotlin.idea.search.declarationsSearch.findDeepestSuperMethodsNoWrapping +import org.jetbrains.kotlin.nj2k.isObjectOrCompanionObject import org.jetbrains.kotlin.nj2k.psi import org.jetbrains.kotlin.nj2k.tree.* -import org.jetbrains.kotlin.nj2k.types.JKType -import org.jetbrains.kotlin.nj2k.types.arrayInnerType - -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.KtObjectDeclaration +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -24,9 +24,10 @@ val JKSymbol.isUnresolved get() = this is JKUnresolvedSymbol fun JKSymbol.getDisplayName(): String { + fun JKSymbol.isDisplayable() = this is JKClassSymbol || this is JKPackageSymbol if (this !is JKUniverseSymbol<*>) return fqName - return generateSequence(declaredIn as? JKUniverseClassSymbol) { symbol -> - symbol.declaredIn.safeAs()?.takeIf { !it.target.hasOtherModifier(OtherModifier.INNER) } + return generateSequence(declaredIn?.takeIf { it.isDisplayable() }) { symbol -> + symbol.declaredIn?.takeIf { it.isDisplayable() } }.fold(name) { acc, symbol -> "${symbol.name}.$acc" } } @@ -45,3 +46,23 @@ fun JKSymbol.deepestFqName(): String? { } return target.deepestFqNameForTarget() ?: fqName } + +val JKSymbol.isStaticMember + get() = when (val target = target) { + is PsiModifierListOwner -> target.hasModifier(JvmModifier.STATIC) + is KtElement -> target.getStrictParentOfType() + ?.safeAs() + ?.isCompanion() == true + is JKTreeElement -> + target.safeAs()?.hasOtherModifier(OtherModifier.STATIC) == true + || target.parentOfType()?.isObjectOrCompanionObject == true + else -> false + } + +val JKSymbol.isEnumConstant + get() = when (target) { + is JKEnumConstant -> true + is PsiEnumConstant -> true + is KtEnumEntry -> true + else -> false + } diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/elements.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/elements.kt index 17a33594e2f..9be65637c0e 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/elements.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/elements.kt @@ -71,8 +71,8 @@ class JKInheritanceInfo( override fun accept(visitor: JKVisitor) = visitor.visitInheritanceInfo(this) } -class JKPackageDeclaration(name: JKNameIdentifier) : JKTreeElement() { - var name: JKNameIdentifier by child(name) +class JKPackageDeclaration(name: JKNameIdentifier) : JKDeclaration() { + override var name: JKNameIdentifier by child(name) override fun accept(visitor: JKVisitor) = visitor.visitPackageDeclaration(this) } diff --git a/nj2k/testData/newJ2k/staticMembers/StaticImport.external.kt b/nj2k/testData/newJ2k/staticMembers/StaticImport.external.kt new file mode 100644 index 00000000000..4addda9cdc4 --- /dev/null +++ b/nj2k/testData/newJ2k/staticMembers/StaticImport.external.kt @@ -0,0 +1,4 @@ +@file:JvmName("Bar") +package p +fun bar() {} +fun bar(x:Int) {} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/staticMembers/StaticImport.java b/nj2k/testData/newJ2k/staticMembers/StaticImport.java new file mode 100644 index 00000000000..0635984c346 --- /dev/null +++ b/nj2k/testData/newJ2k/staticMembers/StaticImport.java @@ -0,0 +1,7 @@ +import static p.Bar.bar; + +class Impl { + void foo() { + bar(); + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/staticMembers/StaticImport.kt b/nj2k/testData/newJ2k/staticMembers/StaticImport.kt new file mode 100644 index 00000000000..e12a24e2591 --- /dev/null +++ b/nj2k/testData/newJ2k/staticMembers/StaticImport.kt @@ -0,0 +1,7 @@ +import p.bar + +internal class Impl { + fun foo() { + bar() + } +} diff --git a/nj2k/testData/newJ2k/staticMembers/StaticMemmberAccessedViaInstance.java b/nj2k/testData/newJ2k/staticMembers/StaticMemmberAccessedViaInstance.java new file mode 100644 index 00000000000..b69bcc198fe --- /dev/null +++ b/nj2k/testData/newJ2k/staticMembers/StaticMemmberAccessedViaInstance.java @@ -0,0 +1,12 @@ +public class Rectangle { + public static int x = 0; + public int y; +} + +public class Main { + public static void main(String[] args) { + Rectangle rectangle = new Rectangle(); + rectangle.x = 1; + rectangle.y = 2; + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/staticMembers/StaticMemmberAccessedViaInstance.kt b/nj2k/testData/newJ2k/staticMembers/StaticMemmberAccessedViaInstance.kt new file mode 100644 index 00000000000..b464ed60be5 --- /dev/null +++ b/nj2k/testData/newJ2k/staticMembers/StaticMemmberAccessedViaInstance.kt @@ -0,0 +1,16 @@ +class Rectangle { + var y = 0 + + companion object { + var x = 0 + } +} + +object Main { + @JvmStatic + fun main(args: Array) { + val rectangle = Rectangle() + Rectangle.x = 1 + rectangle.y = 2 + } +} diff --git a/nj2k/testData/newJ2k/staticMembers/StaticQualifiedByInheritor.java b/nj2k/testData/newJ2k/staticMembers/StaticQualifiedByInheritor.java new file mode 100644 index 00000000000..2e44f0fc08b --- /dev/null +++ b/nj2k/testData/newJ2k/staticMembers/StaticQualifiedByInheritor.java @@ -0,0 +1,13 @@ +public class Base { + public static void foo() { + } +} + +public class Derived extends Base { +} + +public class User { + public static void test() { + Derived.foo(); + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/staticMembers/StaticQualifiedByInheritor.kt b/nj2k/testData/newJ2k/staticMembers/StaticQualifiedByInheritor.kt new file mode 100644 index 00000000000..fc212d06f4d --- /dev/null +++ b/nj2k/testData/newJ2k/staticMembers/StaticQualifiedByInheritor.kt @@ -0,0 +1,12 @@ +open class Base { + companion object { + fun foo() {} + } +} + +class Derived : Base() +object User { + fun test() { + Base.foo() + } +} diff --git a/nj2k/tests/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java b/nj2k/tests/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java index db033b45f7c..02b220fd064 100644 --- a/nj2k/tests/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java +++ b/nj2k/tests/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java @@ -4475,6 +4475,21 @@ public class NewJavaToKotlinConverterSingleFileTestGenerated extends AbstractNew public void testPrivateStaticMethods4() throws Exception { runTest("nj2k/testData/newJ2k/staticMembers/PrivateStaticMethods4.java"); } + + @TestMetadata("StaticImport.java") + public void testStaticImport() throws Exception { + runTest("nj2k/testData/newJ2k/staticMembers/StaticImport.java"); + } + + @TestMetadata("StaticMemmberAccessedViaInstance.java") + public void testStaticMemmberAccessedViaInstance() throws Exception { + runTest("nj2k/testData/newJ2k/staticMembers/StaticMemmberAccessedViaInstance.java"); + } + + @TestMetadata("StaticQualifiedByInheritor.java") + public void testStaticQualifiedByInheritor() throws Exception { + runTest("nj2k/testData/newJ2k/staticMembers/StaticQualifiedByInheritor.java"); + } } @TestMetadata("nj2k/testData/newJ2k/strings")