New J2K: use IDEA indexes for resolving

Related to #KT-31848
This commit is contained in:
Ilya Kirillov
2019-06-08 21:02:40 +03:00
parent 5f8b5efd66
commit 417717914d
38 changed files with 282 additions and 228 deletions
@@ -9,6 +9,7 @@ import com.intellij.lang.java.JavaLanguage
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiExpression
import com.intellij.psi.PsiMember
import org.jetbrains.kotlin.idea.util.module
import org.jetbrains.kotlin.j2k.ConverterSettings
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtNamedDeclaration
@@ -23,6 +24,7 @@ fun PsiElement.convertToKotlin(): org.jetbrains.kotlin.j2k.Result? {
val j2kConverter =
JavaToKotlinConverterFactory.createJavaToKotlinConverter(
project,
module,
ConverterSettings.defaultSettings,
IdeaJavaToKotlinServices
)
@@ -14,10 +14,11 @@ import org.jetbrains.kotlin.j2k.*
object JavaToKotlinConverterFactory {
fun createJavaToKotlinConverter(
project: Project,
targetModule: Module?,
settings: ConverterSettings,
services: JavaToKotlinConverterServices
): JavaToKotlinConverter =
J2kConverterExtension.extension.createJavaToKotlinConverter(project, settings, services)
J2kConverterExtension.extension.createJavaToKotlinConverter(project, targetModule, settings, services)
fun createPostProcessor(formatCode: Boolean): PostProcessor =
J2kConverterExtension.extension.createPostProcessor(formatCode)
@@ -1,5 +1,6 @@
package org.jetbrains.kotlin.idea.j2k
import com.intellij.openapi.module.Module
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiJavaFile
@@ -10,6 +11,7 @@ class OldJ2kConverterExtension : J2kConverterExtension() {
override fun createJavaToKotlinConverter(
project: Project,
targetModule: Module?,
settings: ConverterSettings,
services: JavaToKotlinConverterServices
): JavaToKotlinConverter =
@@ -21,10 +21,14 @@ import com.intellij.ide.highlighter.ArchiveFileType
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.ide.scratch.ScratchFileService
import com.intellij.ide.scratch.ScratchRootType
import com.intellij.openapi.actionSystem.*
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.LangDataKeys
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.module.Module
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.MessageType
@@ -103,7 +107,9 @@ class JavaToKotlinAction : AnAction() {
}
fun convertFiles(
javaFiles: List<PsiJavaFile>, project: Project,
javaFiles: List<PsiJavaFile>,
project: Project,
module: Module,
enableExternalCodeProcessing: Boolean = true,
askExternalCodeProcessing: Boolean = true
): List<KtFile> {
@@ -112,6 +118,7 @@ class JavaToKotlinAction : AnAction() {
val converter =
JavaToKotlinConverterFactory.createJavaToKotlinConverter(
project,
module,
ConverterSettings.defaultSettings,
IdeaJavaToKotlinServices
)
@@ -217,7 +224,7 @@ class JavaToKotlinAction : AnAction() {
}
}
convertFiles(javaFiles, project)
convertFiles(javaFiles, project, module)
}
override fun update(e: AnActionEvent) {
@@ -21,6 +21,7 @@ import com.intellij.codeInsight.editorActions.TextBlockTransferableData
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.RangeMarker
import com.intellij.openapi.module.Module
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.DumbService
import com.intellij.openapi.project.Project
@@ -41,6 +42,7 @@ import org.jetbrains.kotlin.idea.j2k.JavaToKotlinConverterFactory
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.idea.util.module
import org.jetbrains.kotlin.j2k.AfterConversionPass
import org.jetbrains.kotlin.j2k.ConverterContext
import org.jetbrains.kotlin.j2k.ConverterSettings
@@ -85,6 +87,7 @@ class ConvertJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransferab
val document = editor.document
val targetFile = PsiDocumentManager.getInstance(project).getPsiFile(document) as? KtFile ?: return
val targetModule = targetFile.module
if (isNoConversionPosition(targetFile, bounds.startOffset)) return
@@ -97,7 +100,7 @@ class ConvertJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransferab
fun doConversion(): Result {
val dataForConversion = DataForConversion.prepare(data, project)
val result = dataForConversion.elementsAndTexts.convertCodeToKotlin(project)
val result = dataForConversion.elementsAndTexts.convertCodeToKotlin(project, targetModule)
val referenceData = buildReferenceData(result.text, result.parseContext, dataForConversion.importsAndPackage, targetFile)
val text = if (result.textChanged) result.text else null
return Result(text, referenceData, result.importsToAdd, result.converterContext)
@@ -214,10 +217,11 @@ internal class ConversionResult(
val converterContext: ConverterContext?
)
internal fun ElementAndTextList.convertCodeToKotlin(project: Project): ConversionResult {
internal fun ElementAndTextList.convertCodeToKotlin(project: Project, targetModule: Module?): ConversionResult {
val converter =
JavaToKotlinConverterFactory.createJavaToKotlinConverter(
project,
targetModule,
ConverterSettings.defaultSettings,
IdeaJavaToKotlinServices
)
@@ -23,6 +23,7 @@ import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.RangeMarker
import com.intellij.openapi.fileTypes.LanguageFileType
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.DumbService
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Ref
@@ -37,6 +38,7 @@ import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.editor.KotlinEditorOptions
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.idea.util.projectStructure.module
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
@@ -94,6 +96,7 @@ class ConvertTextJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransf
val psiDocumentManager = PsiDocumentManager.getInstance(project)
psiDocumentManager.commitDocument(editor.document)
val targetFile = psiDocumentManager.getPsiFile(editor.document) as? KtFile ?: return
val targetModule = targetFile.module
val pasteTarget = detectPasteTarget(targetFile, bounds.startOffset, bounds.endOffset) ?: return
@@ -105,9 +108,9 @@ class ConvertTextJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransf
val dataForConversion = DataForConversion.prepare(copiedJavaCode, project)
val additionalImports = dataForConversion.tryResolveImports(targetFile)
var convertedImportsText = additionalImports.convertCodeToKotlin(project).text
var convertedImportsText = additionalImports.convertCodeToKotlin(project, targetModule).text
val convertedResult = dataForConversion.convertCodeToKotlin(project)
val convertedResult = dataForConversion.convertCodeToKotlin(project, targetModule)
val convertedText = convertedResult.text
val newBounds = runWriteAction {
@@ -133,8 +136,8 @@ class ConvertTextJavaCopyPasteProcessor : CopyPastePostProcessor<TextBlockTransf
conversionPerformed = true
}
private fun DataForConversion.convertCodeToKotlin(project: Project): ConversionResult {
return elementsAndTexts.convertCodeToKotlin(project)
private fun DataForConversion.convertCodeToKotlin(project: Project, targetModule: Module?): ConversionResult {
return elementsAndTexts.convertCodeToKotlin(project, targetModule)
}
private val KtElement.pasteContext: KotlinContext
@@ -188,7 +188,7 @@ class KotlinCreateTestIntention : SelfTargetingRangeIntention<KtNamedDeclaration
getDocument(generatedFile)?.let { doPostponedOperationsAndUnblockDocument(it) }
}
JavaToKotlinAction.convertFiles(listOf(generatedFile), project, false).singleOrNull()
JavaToKotlinAction.convertFiles(listOf(generatedFile), project, srcModule, false).singleOrNull()
}
}
}
@@ -13,6 +13,7 @@ abstract class J2kConverterExtension : AbstractExtensionPointBean() {
abstract fun createJavaToKotlinConverter(
project: Project,
targetModule: Module?,
settings: ConverterSettings,
services: JavaToKotlinConverterServices
): JavaToKotlinConverter
@@ -18,10 +18,11 @@ class NewJ2kConverterExtension : J2kConverterExtension() {
override fun createJavaToKotlinConverter(
project: Project,
targetModule: Module?,
settings: ConverterSettings,
services: JavaToKotlinConverterServices
): JavaToKotlinConverter =
NewJavaToKotlinConverter(project, settings, services)
NewJavaToKotlinConverter(project, targetModule, settings, services)
override fun createPostProcessor(formatCode: Boolean): PostProcessor =
NewJ2kPostProcessor()
@@ -42,7 +42,7 @@ internal class LabelToFunctionTypeVariableMapper(analysisContext: AnalysisContex
internal class ConstraintsCollector(
private val analysisContext: AnalysisContext,
private val converterContext: NewJ2kConverterContext,
private val converterContext: NewJ2kConverterContext?,
printConstraints: Boolean
) {
private val boundTypeStorage = BoundTypeStorage(analysisContext, printConstraints)
@@ -51,7 +51,7 @@ internal class ConstraintsCollector(
private val PsiElement.elementInfo: List<JKElementInfo>?
get() = getLabel()?.let { label ->
converterContext.elementsInfoStorage.getInfoForLabel(label)
converterContext?.elementsInfoStorage?.getInfoForLabel(label)
}
private inline val KtExpression.boundType
@@ -21,10 +21,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
internal class ContextCreator(
private val conversionContext: NewJ2kConverterContext,
private val getNullability: (KtTypeElement, NewJ2kConverterContext) -> Nullability
) {
internal class ContextCreator(private val getNullability: (KtTypeElement) -> Nullability) {
private fun KtCallableDeclaration.typeElement(): KtTypeElement? =
typeReference?.typeElement
@@ -80,7 +77,7 @@ internal class ContextCreator(
}
private fun KtTypeElement.asTypeVariable(): TypeVariable {
val nullability = getNullability(this, conversionContext)
val nullability = getNullability(this)
val classReference: ClassReference = classReference()
val typeParameters: List<TypeVariableTypeParameter> =
typeArgumentsAsTypes.mapIndexed { index, typeRef ->
@@ -142,7 +139,7 @@ fun prepareTypeElementByMakingAllTypesNullableConsideringNullabilityComment(type
}
}
fun prepareTypeElementByMakingAllTypesNullable(typeElement: KtTypeElement, conversionContext: NewJ2kConverterContext) {
fun prepareTypeElementByMakingAllTypesNullable(typeElement: KtTypeElement) {
typeElement.changeNullability(toNullable = true)
}
@@ -76,16 +76,16 @@ internal fun KtTypeElement.classReference(): ClassReference {
}
class NullabilityAnalysisFacade(
private val conversionContext: NewJ2kConverterContext,
private val getTypeElementNullability: (KtTypeElement, NewJ2kConverterContext) -> Nullability,
private val prepareTypeElement: (KtTypeElement, NewJ2kConverterContext) -> Unit,
private val conversionContext: NewJ2kConverterContext?,
private val getTypeElementNullability: (KtTypeElement) -> Nullability,
private val prepareTypeElement: (KtTypeElement) -> Unit,
private val debugPrint: Boolean
) {
fun fixNullability(analysisScope: AnalysisScope) {
CommandProcessor.getInstance().runUndoTransparentAction {
runWriteAction {
analysisScope.prepareTypeElements(prepareTypeElement, conversionContext)
val context = ContextCreator(conversionContext, getTypeElementNullability).createContext(analysisScope)
analysisScope.prepareTypeElements(prepareTypeElement)
val context = ContextCreator(getTypeElementNullability).createContext(analysisScope)
if (debugPrint) {
with(Printer(context)) {
analysisScope.forEach { it.addTypeVariablesNames() }
@@ -101,15 +101,12 @@ class NullabilityAnalysisFacade(
}
}
private fun AnalysisScope.prepareTypeElements(
prepareTypeElement: (KtTypeElement, NewJ2kConverterContext) -> Unit,
conversionContext: NewJ2kConverterContext
) {
private fun AnalysisScope.prepareTypeElements(prepareTypeElement: (KtTypeElement) -> Unit) {
val typeElements = flatMap { it.collectDescendantsOfType<KtTypeReference>() }
typeElements.forEach { typeReference ->
val typeElement = typeReference.typeElement ?: return@forEach
if (typeElement.parentOfType<KtSuperTypeCallEntry>() == null) {
prepareTypeElement(typeElement, conversionContext)
prepareTypeElement(typeElement)
}
}
}
@@ -38,8 +38,8 @@ val nullabilityProcessing =
postProcessing("Inferring declarations nullability") { file, rangeMarker, converterContext ->
NullabilityAnalysisFacade(
converterContext,
getTypeElementNullability = ::nullabilityByUndefinedNullabilityComment,
prepareTypeElement = ::prepareTypeElementByMakingAllTypesNullableConsideringNullabilityComment,
getTypeElementNullability = { nullabilityByUndefinedNullabilityComment(it, converterContext) },
prepareTypeElement = { prepareTypeElementByMakingAllTypesNullableConsideringNullabilityComment(it, converterContext) },
debugPrint = false
).fixNullability(AnalysisScope(file, rangeMarker))
}
@@ -5,23 +5,22 @@
package org.jetbrains.kotlin.nj2k
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.nj2k.conversions.multiResolveFqName
import org.jetbrains.kotlin.nj2k.conversions.resolveFqName
import org.jetbrains.kotlin.nj2k.conversions.JKResolver
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class JKSymbolProvider {
val symbolsByFqName = mutableMapOf<String, JKSymbol>()
class JKSymbolProvider(project: Project, module: Module, contextElement: PsiElement) {
private val symbolsByFqName = mutableMapOf<String, JKSymbol>()
val symbolsByPsi = mutableMapOf<PsiElement, JKSymbol>()
val symbolsByJK = mutableMapOf<JKDeclaration, JKSymbol>()
private val resolver = JKResolver(project, module, contextElement)
private val elementVisitor = ElementVisitor()
@@ -102,50 +101,36 @@ class JKSymbolProvider {
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)
fun provideClassSymbol(fqName: FqName): JKClassSymbol =
symbolsByFqName.getOrPutIfNotNull(fqName.asString()) {
resolver.resolveClass(fqName)?.let {
provideDirectSymbol(it) as? JKClassSymbol
}
} as? JKClassSymbol ?: JKUnresolvedClassSymbol(fqName.asString())
internal inline fun <reified T : JKSymbol> provideByFqName(
fqName: String,
multiResolve: Boolean = false,
context: PsiElement = symbolsByPsi.keys.first()
): T =
provideByFqName(ClassId.fromString(fqName), multiResolve, context)
fun provideClassSymbol(fqName: String): JKClassSymbol =
provideClassSymbol(FqName(fqName.asSafeFqNameString()))
internal inline fun <reified T : JKSymbol> provideByFqName(
fqName: FqName,
multiResolve: Boolean = false,
context: PsiElement = symbolsByPsi.keys.first()
): T =
provideByFqName(fqName.asString(), multiResolve, context)
fun provideMethodSymbol(fqName: FqName): JKMethodSymbol =
symbolsByFqName.getOrPutIfNotNull(fqName.asString()) {
resolver.resolveMethod(fqName)?.let {
provideDirectSymbol(it) as? JKMethodSymbol
}
} as? JKMethodSymbol ?: JKUnresolvedMethod(fqName.asString())
internal inline fun <reified T : JKSymbol> provideByFqName(
fqName: FqNameUnsafe,
multiResolve: Boolean = false,
context: PsiElement = symbolsByPsi.keys.first()
): T =
provideByFqName(fqName.asString(), multiResolve, context)
fun provideMethodSymbol(fqName: String): JKMethodSymbol =
provideMethodSymbol(FqName(fqName.asSafeFqNameString()))
fun provideFieldSymbol(fqName: FqName): JKFieldSymbol =
symbolsByFqName.getOrPutIfNotNull(fqName.asString()) {
resolver.resolveField(fqName)?.let {
provideDirectSymbol(it) as? JKFieldSymbol
}
} as? JKFieldSymbol ?: JKUnresolvedField(fqName.asString(), this)
fun provideFieldSymbol(fqName: String): JKFieldSymbol =
provideFieldSymbol(FqName(fqName.asSafeFqNameString()))
private inner class ElementVisitor : JavaElementVisitor() {
@@ -182,4 +167,18 @@ class JKSymbolProvider {
}
internal inline fun <reified A, reified B> isAssignable(): Boolean = A::class.java.isAssignableFrom(B::class.java)
}
}
private inline fun <K, V : Any> MutableMap<K, V>.getOrPutIfNotNull(key: K, defaultValue: () -> V?): V? {
val value = get(key)
return if (value == null) {
val answer = defaultValue() ?: return null
put(key, answer)
answer
} else {
value
}
}
private fun String.asSafeFqNameString() =
replace('/', '.')
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.nj2k
import com.intellij.codeInsight.daemon.impl.quickfix.AddTypeArgumentsFix
import com.intellij.lang.jvm.JvmAnnotatedElement
import com.intellij.lang.jvm.JvmModifier
import com.intellij.psi.*
@@ -673,7 +672,7 @@ class JavaToJKTreeBuilder constructor(
fun PsiDocComment.deprecatedAnnotation(): JKAnnotation? =
findTagByName("deprecated")?.let { tag ->
JKAnnotationImpl(
symbolProvider.provideByFqName("kotlin.Deprecated"),
symbolProvider.provideClassSymbol("kotlin.Deprecated"),
listOf(
JKAnnotationParameterImpl(stringLiteral(tag.content(), symbolProvider))
)
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.nj2k
import com.intellij.openapi.command.impl.DummyProject
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.j2k.*
@@ -28,21 +27,5 @@ data class NewJ2kConverterContext(
override fun inConversionScope(element: PsiElement): Boolean = inConversionContext(element)
})
companion object {
val DUMMY =
NewJ2kConverterContext(
JKSymbolProvider(),
NewJavaToKotlinConverter(
DummyProject.getInstance(),
ConverterSettings.defaultSettings,
EmptyJavaToKotlinServices
),
{ false },
ImportStorage(),
JKElementInfoStorage()
)
}
}
@@ -20,6 +20,7 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.module.Module
import com.intellij.openapi.progress.EmptyProgressIndicator
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.progress.ProgressIndicator
@@ -38,6 +39,7 @@ import org.jetbrains.kotlin.psi.KtPsiFactory
class NewJavaToKotlinConverter(
val project: Project,
private val targetModule: Module?,
val settings: ConverterSettings,
val oldConverterServices: JavaToKotlinConverterServices
) : JavaToKotlinConverter() {
@@ -101,7 +103,9 @@ class NewJavaToKotlinConverter(
val processor = processor as NewJ2kWithProgressProcessor
val phaseDescription = "Converting Java code to Kotlin code"
val symbolProvider = JKSymbolProvider()
val module = targetModule ?: error("Module should not be null for new J2K")
val contextElement = inputElements.firstOrNull() ?: return Result(emptyList(), null, null)
val symbolProvider = JKSymbolProvider(project, module, contextElement)
symbolProvider.preBuildTree(inputElements)
val importStorage = ImportStorage()
val treeBuilder = JavaToJKTreeBuilder(symbolProvider, converterServices, importStorage)
@@ -29,7 +29,7 @@ class ArrayInitializerConversion(private val context: NewJ2kConverterContext) :
if (primitiveArrayType == null) JKTypeArgumentListImpl(listOf(element::type.detached()))
else JKTypeArgumentListImpl()
newElement = JKJavaMethodCallExpressionImpl(
context.symbolProvider.provideByFqName("kotlin.$arrayConstructorName"),
context.symbolProvider.provideMethodSymbol("kotlin.$arrayConstructorName"),
element.initializer.also { element.initializer = emptyList() }.toArgumentList(),
typeArguments
)
@@ -46,13 +46,13 @@ class ArrayInitializerConversion(private val context: NewJ2kConverterContext) :
if (dimensions.size == 1) {
return if (type !is JKJavaPrimitiveType) {
JKJavaMethodCallExpressionImpl(
context.symbolProvider.provideByFqName("kotlin/arrayOfNulls"),
context.symbolProvider.provideMethodSymbol("kotlin.arrayOfNulls"),
JKArgumentListImpl(dimensions[0]),
JKTypeArgumentListImpl(listOf(JKTypeElementImpl(type)))
)
} else {
JKJavaNewExpressionImpl(
context.symbolProvider.provideByFqName(type.arrayFqName()),
context.symbolProvider.provideClassSymbol(type.arrayFqName()),
JKArgumentListImpl(dimensions[0]),
JKTypeArgumentListImpl(emptyList())
)
@@ -62,8 +62,8 @@ class ArrayInitializerConversion(private val context: NewJ2kConverterContext) :
val arrayType = dimensions.drop(1).fold(type) { currentType, _ ->
JKJavaArrayTypeImpl(currentType)
}
return JKJavaMethodCallExpressionImpl(
context.symbolProvider.provideByFqName("kotlin.Array"),
return JKJavaNewExpressionImpl(
context.symbolProvider.provideClassSymbol("kotlin.Array"),
JKArgumentListImpl(
dimensions[0],
JKLambdaExpressionImpl(
@@ -75,19 +75,19 @@ class ArrayInitializerConversion(private val context: NewJ2kConverterContext) :
)
}
var resultType = JKClassTypeImpl(
context.symbolProvider.provideByFqName(type.arrayFqName()),
context.symbolProvider.provideClassSymbol(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()),
context.symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.array.toSafe()),
listOf(resultType),
Nullability.Default
)
}
return JKJavaMethodCallExpressionImpl(
context.symbolProvider.provideByFqName("kotlin/arrayOfNulls"),
context.symbolProvider.provideMethodSymbol("kotlin.arrayOfNulls"),
JKArgumentListImpl(dimensions[0]),
JKTypeArgumentListImpl(listOf(JKTypeElementImpl(resultType)))
)
@@ -22,9 +22,9 @@ class ArrayOperationsConversion(private val context: NewJ2kConverterContext) : R
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")
)
JKFieldAccessExpressionImpl(
context.symbolProvider.provideFieldSymbol("kotlin.Array.size")
)
element.selector = sizeCall
}
return recurse(element)
@@ -6,7 +6,10 @@
package org.jetbrains.kotlin.nj2k.conversions
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.JKBlockStatement
import org.jetbrains.kotlin.nj2k.tree.JKJavaAssignmentExpression
import org.jetbrains.kotlin.nj2k.tree.JKKtAssignmentStatement
import org.jetbrains.kotlin.nj2k.tree.JKTreeElement
import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.utils.addToStdlib.cast
@@ -18,7 +21,7 @@ class AssignmentAsExpressionToAlsoConversion(val context: NewJ2kConverterContext
val alsoExpression = JKKtAlsoCallExpressionImpl(
JKBlockStatementImpl(
JKBlockImpl(listOf(JKKtAssignmentStatementImpl(element.field, JKStubExpressionImpl(), element.operator)))
), context.symbolProvider.provideByFqName("kotlin/also")
), context.symbolProvider.provideMethodSymbol("kotlin.also")
).also {
it.statement.cast<JKBlockStatement>().block.statements.first().cast<JKKtAssignmentStatement>().expression =
JKFieldAccessExpressionImpl(
@@ -23,7 +23,10 @@ class BlockToRunConversion(private val context: NewJ2kConverterContext) : Recurs
JKBlockStatementImpl(element.block),
emptyList()
)
val call = JKKtCallExpressionImpl(context.symbolProvider.provideByFqName("kotlin.run", true), JKArgumentListImpl(lambda))
val call = JKKtCallExpressionImpl(
context.symbolProvider.provideMethodSymbol("kotlin.run"),
JKArgumentListImpl(lambda)
)
return recurse(JKExpressionStatementImpl(call).withNonCodeElementsFrom(element))
}
@@ -39,7 +39,7 @@ class BoxedTypeOperationsConversion(private val context: NewJ2kConverterContext)
val primitiveTypeName = boxedTypeToPrimitiveType[boxedJavaType] ?: return null
if (operationType !in primitiveTypeNames) return null
return JKKtCallExpressionImpl(
context.symbolProvider.provideByFqName(
context.symbolProvider.provideMethodSymbol(
"kotlin.${primitiveTypeName.capitalize()}.to${operationType.capitalize()}"
),
JKArgumentListImpl()
@@ -78,13 +78,13 @@ class BuiltinMembersConversion(private val context: NewJ2kConverterContext) : Re
when (from) {
is JKMethodCallExpression ->
JKKtCallExpressionImpl(
context.symbolProvider.provideByFqName(fqName, true),
context.symbolProvider.provideMethodSymbol(fqName),
argumentsProvider(from::arguments.detached()),
from::typeArgumentList.detached()
).withNonCodeElementsFrom(from)
is JKFieldAccessExpression ->
JKKtCallExpressionImpl(
context.symbolProvider.provideByFqName(fqName, true),
context.symbolProvider.provideMethodSymbol(fqName),
JKArgumentListImpl(),
JKTypeArgumentListImpl()
).withNonCodeElementsFrom(from)
@@ -99,11 +99,11 @@ class BuiltinMembersConversion(private val context: NewJ2kConverterContext) : Re
when (from) {
is JKMethodCallExpression ->
JKFieldAccessExpressionImpl(
context.symbolProvider.provideByFqName(fqName, true)
context.symbolProvider.provideFieldSymbol(fqName)
).withNonCodeElementsFrom(from)
is JKFieldAccessExpression ->
JKFieldAccessExpressionImpl(
context.symbolProvider.provideByFqName(fqName, true)
context.symbolProvider.provideFieldSymbol(fqName)
).withNonCodeElementsFrom(from)
else -> error("Bad conversion")
}
@@ -120,7 +120,7 @@ class BuiltinMembersConversion(private val context: NewJ2kConverterContext) : Re
arguments.first()::value.detached().parenthesizeIfBinaryExpression(),
JKKtQualifierImpl.DOT,
JKKtCallExpressionImpl(
context.symbolProvider.provideByFqName(fqName, true),
context.symbolProvider.provideMethodSymbol(fqName),
JKArgumentListImpl(arguments.drop(1)),
from::typeArgumentList.detached()
)
@@ -240,7 +240,7 @@ class BuiltinMembersConversion(private val context: NewJ2kConverterContext) : Re
withArgumentsProvider { arguments ->
val argument = arguments.arguments.single()::value.detached()
val call = JKKtCallExpressionImpl(
context.symbolProvider.provideByFqName("kotlin.text.charset"),
context.symbolProvider.provideMethodSymbol("kotlin.text.charset"),
JKArgumentListImpl(argument)
)
JKArgumentListImpl(call)
@@ -278,10 +278,7 @@ class BuiltinMembersConversion(private val context: NewJ2kConverterContext) : Re
val detachedArguments = arguments::arguments.detached()
val first =
detachedArguments.first()::value.detached().callOn(
context.symbolProvider.provideByFqName(
"kotlin.text.toRegex",
multiResolve = true
)
context.symbolProvider.provideMethodSymbol("kotlin.text.toRegex")
)
JKArgumentListImpl(listOf(JKArgumentImpl(first)) + detachedArguments.drop(1))
},
@@ -291,10 +288,8 @@ class BuiltinMembersConversion(private val context: NewJ2kConverterContext) : Re
val detachedArguments = arguments::arguments.detached()
val first =
detachedArguments.first()::value.detached().callOn(
context.symbolProvider.provideByFqName(
"kotlin.text.toRegex",
multiResolve = true
)
context.symbolProvider.provideMethodSymbol("kotlin.text.toRegex")
)
JKArgumentListImpl(listOf(JKArgumentImpl(first)) + detachedArguments.drop(1))
},
@@ -366,19 +361,15 @@ class BuiltinMembersConversion(private val context: NewJ2kConverterContext) : Re
arguments.arguments = arguments.arguments.dropLast(1)
}.let {
it.callOn(
context.symbolProvider.provideByFqName("kotlin.collections.dropLastWhile", multiResolve = true),
context.symbolProvider.provideMethodSymbol("kotlin.collections.dropLastWhile"),
JKLambdaExpressionImpl(
JKFieldAccessExpressionImpl(
JKUnresolvedField(//TODO replace with `it` parameter
"it",
context.symbolProvider
)
).callOn(
context.symbolProvider.provideByFqName(
"kotlin.text.isEmpty",
multiResolve = true
)
).asStatement(),
).callOn(context.symbolProvider.provideMethodSymbol("kotlin.text.isEmpty"))
.asStatement(),
emptyList()
)
)
@@ -387,7 +378,7 @@ class BuiltinMembersConversion(private val context: NewJ2kConverterContext) : Re
else -> expression.also {
val lastArgument = arguments.arguments.last().value.copyTreeAndDetach()
.callOn(
context.symbolProvider.provideByFqName("kotlin.ranges.coerceAtLeast"),
context.symbolProvider.provideMethodSymbol("kotlin.ranges.coerceAtLeast"),
JKKtLiteralExpressionImpl("0", JKLiteralExpression.LiteralType.INT)
)
arguments.arguments = arguments.arguments.dropLast(1) + JKArgumentImpl(lastArgument)
@@ -469,5 +460,5 @@ class BuiltinMembersConversion(private val context: NewJ2kConverterContext) : Re
private fun JKExpression.castToTypedArray() =
callOn(context.symbolProvider.provideByFqName("kotlin.collections.toTypedArray", multiResolve = true))
callOn(context.symbolProvider.provideMethodSymbol("kotlin.collections.toTypedArray"))
}
@@ -237,10 +237,7 @@ class ForConversion(private val context: NewJ2kConverterContext) : RecursiveAppl
indices,
JKKtQualifierImpl.DOT,
JKJavaMethodCallExpressionImpl(
context.symbolProvider.provideByFqName(
"kotlin/collections/reversed",
multiResolve = true
),
context.symbolProvider.provideMethodSymbol("kotlin.collections.reversed"),
JKArgumentListImpl()
)
)
@@ -267,10 +264,7 @@ class ForConversion(private val context: NewJ2kConverterContext) : RecursiveAppl
private fun toIndicesCall(javaSizeCall: JKQualifiedExpression): JKQualifiedExpression? {
if (javaSizeCall.psi == null) return null
val selector = JKFieldAccessExpressionImpl(
context.symbolProvider.provideByFqName(
"kotlin/collections/indices",
multiResolve = true
)
context.symbolProvider.provideFieldSymbol("kotlin.collections.indices")
)
return JKQualifiedExpressionImpl(javaSizeCall::receiver.detached(), javaSizeCall.operator, selector)
}
@@ -5,7 +5,10 @@
package org.jetbrains.kotlin.nj2k.conversions
import org.jetbrains.kotlin.nj2k.*
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.copyTreeAndDetach
import org.jetbrains.kotlin.nj2k.isEquals
import org.jetbrains.kotlin.nj2k.parenthesizeIfBinaryExpression
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
@@ -100,7 +103,7 @@ class ImplicitCastsConversion(private val context: NewJ2kConverterContext) : Rec
copyTreeAndDetach().parenthesizeIfBinaryExpression(),
JKKtQualifierImpl.DOT,
JKKtCallExpressionImpl(
context.symbolProvider.provideByFqName("kotlin.text.toRegex", multiResolve = true),
context.symbolProvider.provideMethodSymbol("kotlin.text.toRegex"),
JKArgumentListImpl(),
JKTypeArgumentListImpl()
)
@@ -142,7 +145,7 @@ class ImplicitCastsConversion(private val context: NewJ2kConverterContext) : Rec
this.copyTreeAndDetach(),
JKKtQualifierImpl.DOT,
JKJavaMethodCallExpressionImpl(
context.symbolProvider.provideByFqName("kotlin.$initialTypeName.$conversionFunctionName"),
context.symbolProvider.provideMethodSymbol("kotlin.$initialTypeName.$conversionFunctionName"),
JKArgumentListImpl()
)
)
@@ -29,14 +29,14 @@ class JavaAnnotationsConversion(private val context: NewJ2kConverterContext) : R
private fun processAnnotation(annotation: JKAnnotation) {
if (annotation.classSymbol.fqName == "java.lang.Deprecated") {
annotation.classSymbol = context.symbolProvider.provideByFqName("kotlin.Deprecated")
annotation.classSymbol = context.symbolProvider.provideClassSymbol("kotlin.Deprecated")
if (annotation.arguments.isEmpty()) {
annotation.arguments +=
JKAnnotationParameterImpl(JKKtLiteralExpressionImpl("\"\"", JKLiteralExpression.LiteralType.STRING))
}
}
if (annotation.classSymbol.fqName == "java.lang.annotation.Target") {
annotation.classSymbol = context.symbolProvider.provideByFqName("kotlin.annotation.Target")
annotation.classSymbol = context.symbolProvider.provideClassSymbol("kotlin.annotation.Target")
val arguments = annotation.arguments.singleOrNull()?.let { parameter ->
val value = parameter.value
@@ -51,7 +51,7 @@ class JavaAnnotationsConversion(private val context: NewJ2kConverterContext) : R
value.fieldAccessFqName()
?.let { targetMappings[it] }
?.map { fqName ->
JKFieldAccessExpressionImpl(context.symbolProvider.provideByFqName(fqName))
JKFieldAccessExpressionImpl(context.symbolProvider.provideFieldSymbol(fqName))
} ?: listOf(value.copyTreeAndDetach())
}
annotation.arguments = newArguments.map { JKAnnotationParameterImpl(it) }
@@ -5,10 +5,12 @@
package org.jetbrains.kotlin.nj2k.conversions
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.impl.*
import org.jetbrains.kotlin.nj2k.tree.impl.JKAnnotationImpl
import org.jetbrains.kotlin.nj2k.tree.impl.JKJavaArrayTypeImpl
import org.jetbrains.kotlin.nj2k.tree.impl.JKTypeElementImpl
//TODO temporary
@@ -28,7 +30,7 @@ class MainFunctionConversion(private val context: NewJ2kConverterContext) : Recu
}
element.annotationList.annotations +=
JKAnnotationImpl(
context.symbolProvider.provideByFqName("kotlin.jvm.JvmStatic"),
context.symbolProvider.provideClassSymbol("kotlin.jvm.JvmStatic"),
emptyList()
)
}
@@ -49,7 +49,7 @@ class OperatorExpressionConversion(private val context: NewJ2kConverterContext)
if (javaOperator.token.psiToken == JavaTokenType.TILDE) {
val invCall =
JKKtCallExpressionImpl(
context.symbolProvider.provideByFqName("kotlin.Int.inv"),//TODO check if Long
context.symbolProvider.provideMethodSymbol("kotlin.Int.inv"),//TODO check if Long
JKArgumentListImpl()
)
JKQualifiedExpressionImpl(
@@ -72,7 +72,7 @@ class OperatorExpressionConversion(private val context: NewJ2kConverterContext)
) {
val toStringCall =
JKKtCallExpressionImpl(
context.symbolProvider.provideByFqName("kotlin.Any.toString"),
context.symbolProvider.provideMethodSymbol("kotlin.Any.toString"),
JKArgumentListImpl()
)
val qualifiedCall = JKQualifiedExpressionImpl(left, JKKtQualifierImpl.DOT, toStringCall)
@@ -21,7 +21,7 @@ class ParameterModificationInMethodCallsConversion(private val context: NewJ2kCo
val parameterType =
if (parameter.isVarArgs) {
JKClassTypeImpl(
context.symbolProvider.provideByFqName(parameter.type.type.arrayFqName()),
context.symbolProvider.provideClassSymbol(parameter.type.type.arrayFqName()),
if (parameter.type.type is JKJavaPrimitiveType) emptyList()
else listOf(
JKVarianceTypeParameterTypeImpl(
@@ -22,7 +22,7 @@ class SynchronizedStatementConversion(private val context: NewJ2kConverterContex
)
val synchronizedCall =
JKKtCallExpressionImpl(
context.symbolProvider.provideByFqName("kotlin.synchronized", true),
context.symbolProvider.provideMethodSymbol("kotlin.synchronized"),
JKArgumentListImpl(
element.lockExpression,
lambdaBody
@@ -13,7 +13,6 @@ 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.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.kotlinTypeByName
@@ -35,9 +34,7 @@ class TypeMappingConversion(val context: NewJ2kConverterContext) : RecursiveAppl
override fun applyToElement(element: JKTreeElement): JKTreeElement {
return when (element) {
is JKTypeElement -> {
val newType = element.type
.fixRawType(element)
.mapType(element)
val newType = element.type.mapType(element)
JKTypeElementImpl(newType).withNonCodeElementsFrom(element)
}
is JKJavaNewExpression -> {
@@ -79,8 +76,8 @@ class TypeMappingConversion(val context: NewJ2kConverterContext) : RecursiveAppl
}
private fun JKType.fixRawType(typeElement: JKTypeElement) =
when (typeElement.parent) {
private fun JKType.fixRawType(typeElement: JKTypeElement?) =
when (typeElement?.parent) {
is JKClassLiteralExpression -> this
is JKKtIsExpression ->
addTypeParametersToRawProjectionType(JKStarProjectionTypeImpl())
@@ -105,7 +102,7 @@ class TypeMappingConversion(val context: NewJ2kConverterContext) : RecursiveAppl
)
is JKJavaArrayType ->
JKClassTypeImpl(
context.symbolProvider.provideByFqName(type.arrayFqName()),
context.symbolProvider.provideClassSymbol(type.arrayFqName()),
if (type is JKJavaPrimitiveType) emptyList() else listOf(type.mapType(typeElement)),
nullability
)
@@ -115,14 +112,14 @@ class TypeMappingConversion(val context: NewJ2kConverterContext) : RecursiveAppl
boundType.mapType(null)
)
else -> this
}
}.fixRawType(typeElement)
private fun JKClassSymbol.mapClassSymbol(typeElement: JKTypeElement?): JKClassSymbol {
if (this is JKUniverseClassSymbol) return this
val newFqName = typeElement?.let { kotlinCollectionClassName(it) }
?: kotlinStandardType()
?: fqName
return context.symbolProvider.provideByFqName(newFqName)
return context.symbolProvider.provideClassSymbol(newFqName)
}
private fun JKClassType.mapClassType(typeElement: JKTypeElement?): JKClassType =
@@ -149,7 +146,7 @@ class TypeMappingConversion(val context: NewJ2kConverterContext) : RecursiveAppl
private fun JKJavaPrimitiveType.mapPrimitiveType(): JKClassType {
val fqName = jvmPrimitiveType.primitiveType.typeFqName
return JKClassTypeImpl(
context.symbolProvider.provideByFqName(ClassId.topLevel(fqName)),
context.symbolProvider.provideClassSymbol(fqName),
nullability = Nullability.NotNull
)
}
@@ -5,45 +5,105 @@
package org.jetbrains.kotlin.nj2k.conversions
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiPolyVariantReference
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.tree.JKTreeElement
import org.jetbrains.kotlin.nj2k.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 com.intellij.psi.impl.java.stubs.index.JavaFullClassNameIndex
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionFqnNameIndex
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelPropertyFqnNameIndex
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelTypeAliasFqNameIndex
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
import org.jetbrains.kotlin.resolve.ImportPath
internal fun resolveFqName(classId: ClassId, contextElement: JKTreeElement, context: NewJ2kConverterContext): PsiElement? {
val element = contextElement.psi ?: return null
return resolveFqName(classId, element)
}
class JKResolver(private val project: Project, module: Module, private val contextElement: PsiElement) {
private val scope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module)
fun resolveFqName(classId: ClassId, element: PsiElement): PsiElement? {
return constructImportDirectiveWithContext(classId, element)
.getChildOfType<KtDotQualifiedExpression>()
?.selectorExpression
?.let {
it.references.mapNotNull { it.resolve() }.firstOrNull()
fun resolveDeclaration(fqName: FqName): PsiElement? =
resolveFqNameOfKtClassByIndex(fqName)
?: resolveFqNameOfJavaClassByIndex(fqName)
?: resolveFqNameOfKtFunctionByIndex(fqName)
?: resolveFqNameOfKtPropertyByIndex(fqName)
?: resolveFqName(fqName)
fun resolveClass(fqName: FqName): PsiElement? =
resolveFqNameOfKtClassByIndex(fqName)
?: resolveFqNameOfJavaClassByIndex(fqName)
?: resolveFqName(fqName)
fun resolveMethod(fqName: FqName): PsiElement? =
resolveFqNameOfKtFunctionByIndex(fqName)
?: resolveFqName(fqName)
fun resolveField(fqName: FqName): PsiElement? =
resolveFqNameOfKtPropertyByIndex(fqName)
?: resolveFqName(fqName)
private fun resolveFqNameOfKtClassByIndex(fqName: FqName): KtDeclaration? {
val fqNameString = fqName.asString()
val classesPsi = KotlinFullClassNameIndex.getInstance()[fqNameString, project, scope]
val typeAliasesPsi = KotlinTopLevelTypeAliasFqNameIndex.getInstance()[fqNameString, project, scope]
return selectNearest(classesPsi, typeAliasesPsi)
}
private fun resolveFqNameOfJavaClassByIndex(fqName: FqName): PsiClass? {
val fqNameString = fqName.asString()
return JavaFullClassNameIndex.getInstance()[fqNameString.hashCode(), project, scope]
.firstOrNull {
it.qualifiedName == fqNameString
}
}
private fun resolveFqNameOfKtFunctionByIndex(fqName: FqName): KtNamedFunction? =
KotlinTopLevelFunctionFqnNameIndex.getInstance()[fqName.asString(), project, scope].firstOrNull()
private fun resolveFqNameOfKtPropertyByIndex(fqName: FqName): KtProperty? =
KotlinTopLevelPropertyFqnNameIndex.getInstance()[fqName.asString(), project, scope].firstOrNull()
private fun resolveFqName(fqName: FqName): PsiElement? =
constructImportDirectiveWithContext(fqName)
.getChildOfType<KtDotQualifiedExpression>()
?.selectorExpression
?.let {
it.references.mapNotNull { it.resolve() }.firstOrNull()
}
private fun constructImportDirectiveWithContext(fqName: FqName): KtImportDirective {
val importDirective = KtPsiFactory(contextElement).createImportDirective(ImportPath(fqName, false))
importDirective.containingKtFile.analysisContext = contextElement.containingFile
return importDirective
}
private fun selectNearest(classesPsi: Collection<KtDeclaration>, typeAliasesPsi: Collection<KtTypeAlias>): KtDeclaration? =
when {
typeAliasesPsi.isEmpty() -> classesPsi.firstOrNull()
classesPsi.isEmpty() -> typeAliasesPsi.firstOrNull()
else -> (classesPsi.asSequence() + typeAliasesPsi.asSequence()).minWith(Comparator { o1, o2 ->
scope.compare(o1.containingFile.virtualFile, o2.containingFile.virtualFile)
})
}
}
private fun constructImportDirectiveWithContext(classId: ClassId, element: PsiElement): KtImportDirective {
val importDirective = KtPsiFactory(element).createImportDirective(ImportPath(classId.asSingleFqName(), false))
importDirective.containingKtFile.analysisContext = element.containingFile
return importDirective
fun multiResolveFqName(fqName: FqName): List<PsiElement> {
return constructImportDirectiveWithContext(fqName)
.getChildOfType<KtDotQualifiedExpression>()
?.selectorExpression
?.let { selector ->
selector.references.filterIsInstance<PsiPolyVariantReference>()
.flatMap { polyVariantReference ->
polyVariantReference
.multiResolve(false)
.mapNotNull { it.element }
}
}.orEmpty()
}
}
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()
}
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.nj2k
import com.intellij.psi.PsiArrayType
import com.intellij.psi.PsiClass
import com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
@@ -22,7 +21,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
fun kotlinTypeByName(name: String, symbolProvider: JKSymbolProvider, nullability: Nullability = Nullability.Nullable): JKClassType =
JKClassTypeImpl(
symbolProvider.provideByFqName(name),
symbolProvider.provideClassSymbol(name),
emptyList(),
nullability
)
@@ -31,7 +30,7 @@ private fun JKType.classSymbol(symbolProvider: JKSymbolProvider) =
when (this) {
is JKClassType -> classReference
is JKJavaPrimitiveType ->
symbolProvider.provideByFqName(jvmPrimitiveType.primitiveType.typeFqName.asString())
symbolProvider.provideClassSymbol(jvmPrimitiveType.primitiveType.typeFqName)
else -> null
}
@@ -54,7 +53,7 @@ private fun JKKtOperatorToken.arithmeticMethodType(
val classSymbol =
if (leftType.isStringType()) symbolProvider.provideByFqName(KotlinBuiltIns.FQ_NAMES.string.toSafe())
if (leftType.isStringType()) symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.string.toSafe())
else leftType.classSymbol(symbolProvider)
return when (classSymbol) {
@@ -83,7 +82,7 @@ private fun JKKtOperatorToken.unaryExpressionMethodType(
return operandType!!
}
if (this == KtTokens.EXCL) {
return symbolProvider.provideByFqName<JKClassSymbol>(KotlinBuiltIns.FQ_NAMES._boolean).asType()
return symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES._boolean.toSafe()).asType()
}
if (this == KtTokens.MINUS || this == KtTokens.PLUS) {
return operandType!!
@@ -169,7 +168,7 @@ fun kotlinBinaryExpression(
val returnType =
when {
token is JKKtSingleValueOperatorToken && token.psiToken in booleanOperators ->
JKClassTypeImpl(symbolProvider.provideByFqName(KotlinBuiltIns.FQ_NAMES._boolean))
JKClassTypeImpl(symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES._boolean.toSafe()))
else -> {
val leftType = left.type(symbolProvider)
val rightType = right.type(symbolProvider)
@@ -178,7 +177,7 @@ fun kotlinBinaryExpression(
token.arithmeticMethodType(l, r, symbolProvider)
}
} ?: token.defaultReturnType(leftType, rightType, symbolProvider)
?: symbolProvider.provideByFqName<JKClassSymbol>(KotlinBuiltIns.FQ_NAMES.nothing).asType()
?: symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.nothing.toSafe()).asType()
}
}
return JKBinaryExpressionImpl(left, right, JKKtOperatorImpl(token, returnType))
@@ -261,7 +260,7 @@ fun rangeExpression(
to,
JKKtOperatorImpl(
JKKtWordOperatorToken(operatorName),
conversionContext.symbolProvider.provideByFqName<JKMethodSymbol>("kotlin.ranges.$operatorName").returnType!!
conversionContext.symbolProvider.provideMethodSymbol("kotlin.ranges.$operatorName").returnType!!
)
)
@@ -278,7 +277,7 @@ fun useExpression(
body: JKStatement,
symbolProvider: JKSymbolProvider
): JKExpression {
val useSymbol = symbolProvider.provideByFqName<JKMethodSymbol>("kotlin.io.use")
val useSymbol = symbolProvider.provideMethodSymbol("kotlin.io.use")
val lambdaParameter =
JKParameterImpl(JKTypeElementImpl(JKNoTypeImpl), variableIdentifier)
@@ -305,12 +304,12 @@ fun kotlinAssert(assertion: JKExpression, message: JKExpression?, symbolProvider
fun jvmAnnotation(name: String, symbolProvider: JKSymbolProvider) =
JKAnnotationImpl(
symbolProvider.provideByFqName("kotlin.jvm.$name")
symbolProvider.provideClassSymbol("kotlin.jvm.$name")
)
fun throwAnnotation(throws: List<JKType>, symbolProvider: JKSymbolProvider) =
JKAnnotationImpl(
symbolProvider.provideByFqName("kotlin.jvm.Throws"),
symbolProvider.provideClassSymbol("kotlin.jvm.Throws"),
throws.map {
JKAnnotationParameterImpl(
JKClassLiteralExpressionImpl(JKTypeElementImpl(it), JKClassLiteralExpression.LiteralType.KOTLIN_CLASS)
@@ -419,7 +418,7 @@ fun runExpression(body: JKStatement, symbolProvider: JKSymbolProvider): JKExpres
emptyList()
)
return JKKtCallExpressionImpl(
symbolProvider.provideByFqName("kotlin.run", true),
symbolProvider.provideMethodSymbol("kotlin.run"),
(listOf(lambda)).toArgumentList()
)
}
@@ -248,7 +248,7 @@ class JKBooleanLiteral(val value: Boolean) : JKLiteralExpression, JKElementBase(
fun JKLiteralExpression.LiteralType.toJkType(symbolProvider: JKSymbolProvider): JKType {
fun defaultTypeByName(name: String) =
JKClassTypeImpl(
symbolProvider.provideByFqName("kotlin.$name"), emptyList(), Nullability.NotNull
symbolProvider.provideClassSymbol("kotlin.$name"), emptyList(), Nullability.NotNull
)
return when (this) {
@@ -185,7 +185,7 @@ class JKMultiverseFunctionSymbol(override val target: KtFunction, private val sy
type?.let {
if (parameter.isVarArg) {
JKClassTypeImpl(
symbolProvider.provideByFqName(KotlinBuiltIns.FQ_NAMES.array),
symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.array.toSafe()),
listOf(it)
)
} else it
@@ -252,12 +252,13 @@ class JKUnresolvedField(override val target: String, private val symbolProvider:
get() {
val resolvedType = (target as? PsiReferenceExpressionImpl)?.type
if (resolvedType != null) return resolvedType.toJK(symbolProvider)
return JKClassTypeImpl(symbolProvider.provideByFqName("kotlin.Nothing"), emptyList())
return JKClassTypeImpl(symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.nothing.toSafe()), 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
override val name: String
get() = target.substringAfterLast('.')
}
class JKUnresolvedMethod(
@@ -274,7 +275,7 @@ class JKUnresolvedMethod(
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
get() = target.substringAfterLast('.')
}
class JKUnresolvedClassSymbol(override val target: String) : JKClassSymbol, JKUnresolvedSymbol {
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isNullable
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
@@ -57,10 +58,10 @@ fun JKExpression.type(symbolProvider: JKSymbolProvider): JKType? =
is JKClassLiteralExpression -> {
val symbol = when (literalType) {
JKClassLiteralExpression.LiteralType.KOTLIN_CLASS ->
symbolProvider.provideByFqName<JKClassSymbol>("kotlin.reflect.KClass")
symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.kClass.toSafe())
JKClassLiteralExpression.LiteralType.JAVA_CLASS,
JKClassLiteralExpression.LiteralType.JAVA_PRIMITIVE_CLASS, JKClassLiteralExpression.LiteralType.JAVA_VOID_TYPE ->
symbolProvider.provideByFqName("java.lang.Class")
symbolProvider.provideClassSymbol("java.lang.Class")
}
JKClassTypeImpl(symbol, listOf(classType.type), Nullability.NotNull)
}
@@ -76,7 +77,7 @@ fun ClassId.toKtClassType(
symbolProvider: JKSymbolProvider,
nullability: Nullability = Nullability.Default
): JKType =
JKClassTypeImpl(symbolProvider.provideByFqName(this), emptyList(), nullability)
JKClassTypeImpl(symbolProvider.provideClassSymbol(asSingleFqName()), emptyList(), nullability)
fun PsiType.toJK(symbolProvider: JKSymbolProvider, nullability: Nullability = Nullability.Default): JKType {
@@ -136,14 +137,14 @@ fun JKType.isSubtypeOf(other: JKType, symbolProvider: JKSymbolProvider): Boolean
fun KotlinType.toJK(symbolProvider: JKSymbolProvider): JKClassTypeImpl =
JKClassTypeImpl(
symbolProvider.provideByFqName(getJetTypeFqName(false)),
symbolProvider.provideClassSymbol(getJetTypeFqName(false)),
arguments.map { it.type.toJK(symbolProvider) },
if (isNullable()) Nullability.Nullable else Nullability.NotNull
)
fun KtTypeReference.toJK(symbolProvider: JKSymbolProvider): JKType? =
analyze()
analyze(BodyResolveMode.PARTIAL)
.get(BindingContext.TYPE, this)
?.toJK(symbolProvider)
@@ -247,7 +248,7 @@ fun JKJavaMethod.returnTypeNullability(context: NewJ2kConverterContext): Nullabi
fun JKType.isCollectionType(symbolProvider: JKSymbolProvider): Boolean {
if (this !is JKClassType) return false
val collectionType = JKClassTypeImpl(symbolProvider.provideByFqName("java.util.Collection"), emptyList())
val collectionType = JKClassTypeImpl(symbolProvider.provideClassSymbol("java.util.Collection"), emptyList())
return this.isSubtypeOf(collectionType, symbolProvider)
}
@@ -382,7 +383,7 @@ fun JKType.replaceJavaClassWithKotlinClassType(symbolProvider: JKSymbolProvider)
applyRecursive { type ->
if (type is JKClassType && type.classReference.fqName == "java.lang.Class") {
JKClassTypeImpl(
symbolProvider.provideByFqName(KotlinBuiltIns.FQ_NAMES.kClass),
symbolProvider.provideClassSymbol(KotlinBuiltIns.FQ_NAMES.kClass.toSafe()),
type.parameters.map { it.replaceJavaClassWithKotlinClassType(symbolProvider) },
Nullability.NotNull
)
@@ -50,7 +50,7 @@ abstract class AbstractNewJavaToKotlinConverterSingleFileTest : AbstractJavaToKo
override fun fileToKotlin(text: String, settings: ConverterSettings, project: Project): String {
val file = createJavaFile(text)
return NewJavaToKotlinConverter(project, settings, IdeaJavaToKotlinServices)
return NewJavaToKotlinConverter(project, module, settings, IdeaJavaToKotlinServices)
.filesToKotlin(listOf(file), NewJ2kPostProcessor()).results.single()
}
@@ -23,8 +23,8 @@ abstract class AbstractNullabilityAnalysisTest : KotlinLightCodeInsightFixtureTe
val text = FileUtil.loadFile(file, true)
val ktFile = myFixture.configureByText("converterTestFile.kt", text) as KtFile
NullabilityAnalysisFacade(
NewJ2kConverterContext.DUMMY,
getTypeElementNullability = { _, _ -> Nullability.UNKNOWN },
conversionContext = null,
getTypeElementNullability = { Nullability.UNKNOWN },
prepareTypeElement = ::prepareTypeElementByMakingAllTypesNullable,
debugPrint = false
)