New J2K: add element info storage, pass info about types & functions via it
This commit is contained in:
committed by
Ilya Kirillov
parent
39b09b39ff
commit
98651f3484
+82
-37
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.nj2k.nullabilityAnalysis
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
@@ -12,26 +13,46 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isNullExpression
|
||||
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
||||
import org.jetbrains.kotlin.nj2k.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.asAssignment
|
||||
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getTargetFunction
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||
import org.jetbrains.kotlin.resolve.calls.components.isVararg
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.firstOverridden
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
|
||||
internal class LabelToFunctionTypeVariableMapper(analysisContext: AnalysisContext) {
|
||||
private val labelToFunction = analysisContext.declarationToTypeVariable.mapNotNull { (declaration, _) ->
|
||||
if (declaration !is KtNamedFunction) return@mapNotNull null
|
||||
val label = declaration.nameIdentifier?.getLabel() ?: return@mapNotNull null
|
||||
label to declaration
|
||||
}.toMap()
|
||||
|
||||
fun functionByLabel(label: JKElementInfoLabel): KtNamedFunction? =
|
||||
labelToFunction[label]
|
||||
|
||||
}
|
||||
|
||||
internal class ConstraintsCollector(
|
||||
private val analysisContext: AnalysisContext,
|
||||
private val converterContext: NewJ2kConverterContext,
|
||||
printConstraints: Boolean
|
||||
) {
|
||||
private val boundTypeStorage = BoundTypeStorage(analysisContext, printConstraints)
|
||||
private val constraintBuilder = ConstraintBuilder(boundTypeStorage)
|
||||
private val labelToFunctionTypeVariableMapper = LabelToFunctionTypeVariableMapper(analysisContext)
|
||||
|
||||
private val PsiElement.elementInfo: List<JKElementInfo>?
|
||||
get() = getLabel()?.let { label ->
|
||||
converterContext.elementsInfoStorage.getInfoForLabel(label)
|
||||
}
|
||||
|
||||
private inline val KtExpression.boundType
|
||||
get() = boundTypeStorage.boundTypeFor(this)
|
||||
@@ -161,47 +182,71 @@ internal class ConstraintsCollector(
|
||||
}
|
||||
|
||||
|
||||
private fun collectSuperDeclarationConstraintsForFunction(function: KtNamedFunction) = with(constraintBuilder) {
|
||||
val descriptor = function.resolveToDescriptorIfAny() ?: return
|
||||
val superDeclarationDescriptor = descriptor.firstOverridden { true }
|
||||
?.takeIf { it != descriptor }
|
||||
?.safeAs<FunctionDescriptor>()
|
||||
?: return
|
||||
|
||||
val containingSuperClassBoundType =
|
||||
superDeclarationDescriptor.containingDeclaration.safeAs<ClassDescriptor>()?.let { klass ->
|
||||
GenericBoundType(
|
||||
DescriptorClassReference(klass),
|
||||
emptyList(),//TODO,
|
||||
isNull = false
|
||||
)
|
||||
private fun SuperFunctionInfo.superFunctionBoundType(
|
||||
originalFunctionDescriptor: FunctionDescriptor
|
||||
): BoundType? =
|
||||
when (this) {
|
||||
is ExternalSuperFunctionInfo -> {
|
||||
val containingSuperClassBoundType =
|
||||
descriptor.containingDeclaration.safeAs<ClassDescriptor>()?.let { klass ->
|
||||
GenericBoundType(
|
||||
DescriptorClassReference(klass),
|
||||
emptyList(),//TODO,
|
||||
isNull = false
|
||||
)
|
||||
}
|
||||
originalFunctionDescriptor.returnType?.let { type ->
|
||||
boundTypeStorage.boundTypeForType(type, containingSuperClassBoundType, emptyMap()/*TODO*/)
|
||||
}
|
||||
}
|
||||
is InternalSuperFunctionInfo -> {
|
||||
labelToFunctionTypeVariableMapper.functionByLabel(label)?.let { function ->
|
||||
analysisContext.declarationToTypeVariable[function]?.let { TypeVariableBoundType(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val superFunctionPsi = superDeclarationDescriptor.findPsi() as? KtNamedFunction
|
||||
private fun SuperFunctionInfo.superFunctionParameterBoundType(parameterIndex: Int): BoundType? {
|
||||
return when (this) {
|
||||
is ExternalSuperFunctionInfo -> {
|
||||
val containingSuperClassBoundType =
|
||||
descriptor.containingDeclaration.safeAs<ClassDescriptor>()?.let { klass ->
|
||||
GenericBoundType(
|
||||
DescriptorClassReference(klass),
|
||||
emptyList(),//TODO,
|
||||
isNull = false
|
||||
)
|
||||
}
|
||||
val parameter = descriptor.valueParameters.getOrNull(parameterIndex) ?: return null
|
||||
boundTypeStorage.boundTypeForType(parameter.type, containingSuperClassBoundType, emptyMap()/*TODO*/)
|
||||
}
|
||||
is InternalSuperFunctionInfo -> {
|
||||
val function = labelToFunctionTypeVariableMapper.functionByLabel(label) ?: return null
|
||||
val parameter = function.valueParameters.getOrNull(parameterIndex) ?: return null
|
||||
analysisContext.declarationToTypeVariable[parameter]?.let { TypeVariableBoundType(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val superFunctionBoundType =
|
||||
superFunctionPsi?.let { analysisContext.declarationToTypeVariable[it] }?.let {
|
||||
TypeVariableBoundType(it)
|
||||
} ?: descriptor.returnType?.let { type ->
|
||||
boundTypeStorage.boundTypeForType(type, containingSuperClassBoundType, emptyMap()/*TODO*/)
|
||||
} ?: return
|
||||
|
||||
analysisContext.declarationToTypeVariable[function]?.addEqualsNullabilityConstraint(
|
||||
superFunctionBoundType,
|
||||
ConstraintCameFrom.SUPER_DECLARATION
|
||||
)
|
||||
private fun collectSuperDeclarationConstraintsForFunction(function: KtNamedFunction) = with(constraintBuilder) {
|
||||
val (descriptor, superDeclarationDescriptors) =
|
||||
function.nameIdentifier?.elementInfo?.firstIsInstanceOrNull<FunctionInfo>() ?: return@with
|
||||
|
||||
for (parameterIndex in function.valueParameters.indices) {
|
||||
val parameterTypeVariable =
|
||||
function.valueParameters[parameterIndex].let { analysisContext.declarationToTypeVariable[it] } ?: return
|
||||
for (superDeclarationInfo in superDeclarationDescriptors) {
|
||||
val superFunctionBoundType = superDeclarationInfo.superFunctionBoundType(descriptor) ?: continue
|
||||
|
||||
val superParameterBoundType = superFunctionPsi?.valueParameters?.get(parameterIndex)
|
||||
?.let { analysisContext.declarationToTypeVariable[it] }
|
||||
?.let { TypeVariableBoundType(it) }
|
||||
?: superDeclarationDescriptor.valueParameters.getOrNull(parameterIndex)
|
||||
?.let { boundTypeStorage.boundTypeForType(it.type, containingSuperClassBoundType, emptyMap()/*TODO*/) }
|
||||
?: continue
|
||||
parameterTypeVariable.addEqualsNullabilityConstraint(superParameterBoundType, ConstraintCameFrom.SUPER_DECLARATION)
|
||||
analysisContext.declarationToTypeVariable[function]?.addEqualsNullabilityConstraint(
|
||||
superFunctionBoundType,
|
||||
ConstraintCameFrom.SUPER_DECLARATION
|
||||
)
|
||||
|
||||
for (parameterIndex in function.valueParameters.indices) {
|
||||
val parameterTypeVariable =
|
||||
function.valueParameters[parameterIndex].let { analysisContext.declarationToTypeVariable[it] } ?: return
|
||||
val superParameterBoundType = superDeclarationInfo.superFunctionParameterBoundType(parameterIndex) ?: return
|
||||
parameterTypeVariable.addEqualsNullabilityConstraint(superParameterBoundType, ConstraintCameFrom.SUPER_DECLARATION)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,18 @@ import com.intellij.openapi.editor.RangeMarker
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||
import org.jetbrains.kotlin.nj2k.JKElementInfoLabel
|
||||
import org.jetbrains.kotlin.nj2k.asLabel
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
internal class ContextCreator(private val getNullability: (KtTypeElement) -> Nullability) {
|
||||
internal class ContextCreator(
|
||||
private val conversionContext: NewJ2kConverterContext,
|
||||
private val getNullability: (KtTypeElement, NewJ2kConverterContext) -> Nullability
|
||||
) {
|
||||
|
||||
private fun KtCallableDeclaration.typeElement(): KtTypeElement? =
|
||||
typeReference?.typeElement
|
||||
@@ -62,7 +68,7 @@ internal class ContextCreator(private val getNullability: (KtTypeElement) -> Nul
|
||||
}
|
||||
|
||||
private fun KtTypeElement.asTypeVariable(): TypeVariable {
|
||||
val nullability = getNullability(this)
|
||||
val nullability = getNullability(this, conversionContext)
|
||||
val classReference: ClassReference = classReference()
|
||||
val typeParameters: List<TypeVariableTypeParameter> =
|
||||
typeArgumentsAsTypes.mapIndexed { index, typeRef ->
|
||||
@@ -79,38 +85,40 @@ internal class ContextCreator(private val getNullability: (KtTypeElement) -> Nul
|
||||
}
|
||||
|
||||
|
||||
fun nullabilityByUndefinedNullabilityComment(typeElement: KtTypeElement): Nullability {
|
||||
val undefinedNullabilityComment =
|
||||
typeElement.parent?.safeAs<KtTypeReference>()?.getUndefinedNullabilityComment()?.also { it.delete() }
|
||||
fun nullabilityByUndefinedNullabilityComment(typeElement: KtTypeElement, context: NewJ2kConverterContext): Nullability {
|
||||
val hasUndefinedNullabilityLabel =
|
||||
typeElement.parent?.safeAs<KtTypeReference>()?.hasUndefinedNullabilityLabel(context) ?: false
|
||||
return when {
|
||||
undefinedNullabilityComment != null -> Nullability.UNKNOWN
|
||||
hasUndefinedNullabilityLabel -> Nullability.UNKNOWN
|
||||
typeElement is KtNullableType -> Nullability.NULLABLE
|
||||
else -> Nullability.NOT_NULL
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun KtElement.getUndefinedNullabilityComment(): PsiComment? =
|
||||
prevSibling?.safeAs<PsiComment>()?.takeIf { it.text == UNDEFINED_NULLABILITY_COMMENT }
|
||||
?: parent?.safeAs<KtTypeProjection>()?.getUndefinedNullabilityComment()
|
||||
fun PsiElement.getLabel(): JKElementInfoLabel? =
|
||||
prevSibling?.safeAs<PsiComment>()?.text?.asLabel()
|
||||
?: parent?.safeAs<KtTypeProjection>()?.getLabel()
|
||||
|
||||
private fun KtTypeReference.hasUndefinedNullabilityLabel(context: NewJ2kConverterContext) =
|
||||
getLabel()?.let { label ->
|
||||
context.elementsInfoStorage.getInfoForLabel(label).orEmpty().contains(org.jetbrains.kotlin.nj2k.UnknownNullability)
|
||||
} ?: false
|
||||
|
||||
fun prepareTypeElementByMakingAllTypesNullableConsideringNullabilityComment(typeElement: KtTypeElement) {
|
||||
val hasUndefinedNullabilityComment =
|
||||
typeElement.parent?.safeAs<KtTypeReference>()?.getUndefinedNullabilityComment() != null
|
||||
if (hasUndefinedNullabilityComment) {
|
||||
fun prepareTypeElementByMakingAllTypesNullableConsideringNullabilityComment(typeElement: KtTypeElement, context: NewJ2kConverterContext) {
|
||||
val hasUndefinedNullabilityLabel =
|
||||
typeElement.parent?.safeAs<KtTypeReference>()?.hasUndefinedNullabilityLabel(context) ?: false
|
||||
|
||||
if (hasUndefinedNullabilityLabel) {
|
||||
typeElement.changeNullability(toNullable = true)
|
||||
}
|
||||
}
|
||||
|
||||
fun preapareTypeElementByMakingAllTypesNullable(typeElement: KtTypeElement) {
|
||||
fun prepareTypeElementByMakingAllTypesNullable(typeElement: KtTypeElement, conversionContext: NewJ2kConverterContext) {
|
||||
typeElement.changeNullability(toNullable = true)
|
||||
}
|
||||
|
||||
|
||||
internal const val UNDEFINED_NULLABILITY_COMMENT = "/*UNDEFINED*/"
|
||||
|
||||
|
||||
internal data class AnalysisContext(
|
||||
val typeVariableOwners: List<TypeVariableOwner>,
|
||||
val typeElementToTypeVariable: Map<KtTypeElement, TypeVariable>,
|
||||
|
||||
+14
-8
@@ -12,6 +12,8 @@ import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import com.intellij.psi.util.parentOfType
|
||||
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
|
||||
import org.jetbrains.kotlin.nj2k.asLabel
|
||||
import org.jetbrains.kotlin.nj2k.postProcessing.resolve
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
|
||||
@@ -73,22 +75,23 @@ internal fun KtTypeElement.classReference(): ClassReference {
|
||||
}
|
||||
|
||||
class NullabilityAnalysisFacade(
|
||||
private val getTypeElementNullability: (KtTypeElement) -> Nullability,
|
||||
private val prepareTypeElement: (KtTypeElement) -> Unit,
|
||||
private val conversionContext: NewJ2kConverterContext,
|
||||
private val getTypeElementNullability: (KtTypeElement, NewJ2kConverterContext) -> Nullability,
|
||||
private val prepareTypeElement: (KtTypeElement, NewJ2kConverterContext) -> Unit,
|
||||
private val debugPrint: Boolean
|
||||
) {
|
||||
fun fixNullability(analysisScope: AnalysisScope) {
|
||||
CommandProcessor.getInstance().runUndoTransparentAction {
|
||||
runWriteAction {
|
||||
analysisScope.prepareTypeElements(prepareTypeElement)
|
||||
val context = ContextCreator(getTypeElementNullability).createContext(analysisScope)
|
||||
analysisScope.prepareTypeElements(prepareTypeElement, conversionContext)
|
||||
val context = ContextCreator(conversionContext, getTypeElementNullability).createContext(analysisScope)
|
||||
if (debugPrint) {
|
||||
with(Printer(context)) {
|
||||
analysisScope.forEach { it.addTypeVariablesNames() }
|
||||
}
|
||||
}
|
||||
|
||||
val constraints = ConstraintsCollector(context, debugPrint).collectConstraints(analysisScope)
|
||||
val constraints = ConstraintsCollector(context, conversionContext, debugPrint).collectConstraints(analysisScope)
|
||||
Solver(context, debugPrint).solveConstraints(constraints)
|
||||
context.fixTypeVariablesNullability()
|
||||
analysisScope.clearUndefinedLabels()
|
||||
@@ -97,12 +100,15 @@ class NullabilityAnalysisFacade(
|
||||
}
|
||||
}
|
||||
|
||||
private fun AnalysisScope.prepareTypeElements(prepareTypeElement: (KtTypeElement) -> Unit) {
|
||||
private fun AnalysisScope.prepareTypeElements(
|
||||
prepareTypeElement: (KtTypeElement, NewJ2kConverterContext) -> Unit,
|
||||
conversionContext: NewJ2kConverterContext
|
||||
) {
|
||||
val typeElements = flatMap { it.collectDescendantsOfType<KtTypeReference>() }
|
||||
typeElements.forEach { typeReference ->
|
||||
val typeElement = typeReference.typeElement ?: return@forEach
|
||||
if (typeElement.parentOfType<KtSuperTypeCallEntry>() == null) {
|
||||
prepareTypeElement(typeElement)
|
||||
prepareTypeElement(typeElement, conversionContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,7 +123,7 @@ private fun AnalysisScope.clearUndefinedLabels() {
|
||||
}
|
||||
|
||||
override fun visitComment(comment: PsiComment) {
|
||||
if (comment.text == UNDEFINED_NULLABILITY_COMMENT) {
|
||||
if (comment.text.asLabel() != null) {
|
||||
comments += comment
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
|
||||
|
||||
interface JKElementInfo
|
||||
|
||||
sealed class SuperFunctionInfo
|
||||
data class ExternalSuperFunctionInfo(val descriptor: FunctionDescriptor) : SuperFunctionInfo()
|
||||
data class InternalSuperFunctionInfo(val label: JKElementInfoLabel) : SuperFunctionInfo()
|
||||
|
||||
data class FunctionInfo(val originalDescriptor: FunctionDescriptor, val superFunctions: List<SuperFunctionInfo>) : JKElementInfo
|
||||
|
||||
object UnknownNullability : JKElementInfo
|
||||
|
||||
inline class JKElementInfoLabel(val label: String) {
|
||||
inline fun render(): String = "/*@@$label@@*/"
|
||||
|
||||
companion object {
|
||||
val LABEL_REGEX = """/\*@@(\w+)@@\*/""".toRegex()
|
||||
}
|
||||
}
|
||||
|
||||
fun String.asLabel(): JKElementInfoLabel? =
|
||||
JKElementInfoLabel.LABEL_REGEX.matchEntire(this)?.groupValues?.getOrNull(1)?.let { JKElementInfoLabel(it) }
|
||||
|
||||
class JKElementInfoStorage {
|
||||
private val labelToInfo = mutableMapOf<JKElementInfoLabel, List<JKElementInfo>>()
|
||||
private val elementToLabel = mutableMapOf<Any, JKElementInfoLabel>()
|
||||
|
||||
fun getOrCreateInfoForElement(element: Any): JKElementInfoLabel =
|
||||
elementToLabel.getOrPut(element) { JKElementInfoLabel(createRandomString()) }
|
||||
|
||||
fun getOrCreateInfoForLabel(label: JKElementInfoLabel): List<JKElementInfo> =
|
||||
labelToInfo.getOrPut(label) { emptyList() }
|
||||
|
||||
fun getInfoForLabel(label: JKElementInfoLabel): List<JKElementInfo>? =
|
||||
labelToInfo[label]
|
||||
|
||||
|
||||
fun addEntry(element: Any, info: JKElementInfo) {
|
||||
val label = elementToLabel.getOrPut(element) { JKElementInfoLabel(createRandomString()) }
|
||||
labelToInfo[label] = labelToInfo[label].orEmpty() + info
|
||||
elementToLabel[element] = label
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val charPool = ('a'..'z').toList()
|
||||
private const val generatedStringLength = 6
|
||||
|
||||
private fun createRandomString(): String {
|
||||
return (1..generatedStringLength)
|
||||
.map { kotlin.random.Random.nextInt(0, charPool.size) }
|
||||
.map(charPool::get)
|
||||
.joinToString("")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,8 @@ import org.jetbrains.kotlin.nj2k.tree.visitors.JKVisitorWithCommentsPrinting
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class NewCodeBuilder {
|
||||
|
||||
class NewCodeBuilder(context: NewJ2kConverterContext) {
|
||||
private val elementInfoStorage = context.elementsInfoStorage
|
||||
val builder = StringBuilder()
|
||||
val printer = Printer(builder)
|
||||
|
||||
@@ -399,6 +399,10 @@ class NewCodeBuilder {
|
||||
renderModifiersList(ktFunction)
|
||||
printer.printWithNoIndent(" fun ")
|
||||
ktFunction.typeParameterList.accept(this)
|
||||
|
||||
elementInfoStorage.getOrCreateInfoForElement(ktFunction)?.also {
|
||||
printer.printWithNoIndent(it.render())
|
||||
}
|
||||
ktFunction.name.accept(this)
|
||||
renderTokenElement(ktFunction.leftParen)
|
||||
renderList(ktFunction.parameters) {
|
||||
@@ -652,8 +656,8 @@ class NewCodeBuilder {
|
||||
|
||||
private fun renderType(type: JKType, owner: JKTreeElement?) {
|
||||
if (type is JKNoTypeImpl) return
|
||||
if (type.nullability == Nullability.Default) {
|
||||
printer.print("/*UNDEFINED*/")
|
||||
elementInfoStorage.getOrCreateInfoForElement(type)?.also {
|
||||
printer.print(it.render())
|
||||
}
|
||||
when (type) {
|
||||
is JKClassType -> {
|
||||
|
||||
@@ -15,7 +15,7 @@ data class NewJ2kConverterContext(
|
||||
val converter: NewJavaToKotlinConverter,
|
||||
val inConversionContext: (PsiElement) -> Boolean,
|
||||
val importStorage: ImportStorage,
|
||||
val elementsInfoStorage: ElementInfoStorage
|
||||
val elementsInfoStorage: JKElementInfoStorage
|
||||
) : ConverterContext {
|
||||
val project: Project get() = converter.project
|
||||
val typeFlavorCalculator = TypeFlavorCalculator(object : TypeFlavorConverterFacade {
|
||||
@@ -40,7 +40,7 @@ data class NewJ2kConverterContext(
|
||||
),
|
||||
{ false },
|
||||
ImportStorage(),
|
||||
ElementInfoStorage()
|
||||
JKElementInfoStorage()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -101,13 +101,14 @@ class NewJavaToKotlinConverter(
|
||||
symbolProvider,
|
||||
this,
|
||||
{ it.containingFile in inputElements },
|
||||
importStorage
|
||||
importStorage,
|
||||
JKElementInfoStorage()
|
||||
)
|
||||
|
||||
ConversionsRunner.doApply(asts.mapNotNull { it.second }, context)
|
||||
val results = asts.map { (element, ast) ->
|
||||
if (ast == null) return@map null
|
||||
val code = NewCodeBuilder().run { printCodeOut(ast) }
|
||||
val code = NewCodeBuilder(context).run { printCodeOut(ast) }
|
||||
val parseContext = when (element) {
|
||||
is PsiStatement, is PsiExpression -> ParseContext.CODE_BLOCK
|
||||
else -> ParseContext.TOP_LEVEL
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.PsiMethod
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.j2k.ast.Nullability
|
||||
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
||||
import org.jetbrains.kotlin.nj2k.*
|
||||
import org.jetbrains.kotlin.nj2k.tree.*
|
||||
import org.jetbrains.kotlin.nj2k.tree.impl.JKUniverseMethodSymbol
|
||||
import org.jetbrains.kotlin.nj2k.tree.impl.psi
|
||||
|
||||
class AddElementsInfoConversion(private val context: NewJ2kConverterContext) : RecursiveApplicableConversionBase() {
|
||||
override fun applyToElement(element: JKTreeElement): JKTreeElement {
|
||||
when (element) {
|
||||
is JKTypeElement -> addInfoForTypeElement(element)
|
||||
is JKKtFunction -> addInfoForFunction(element)
|
||||
}
|
||||
|
||||
return recurse(element)
|
||||
}
|
||||
|
||||
private fun addInfoForTypeElement(typeElement: JKTypeElement) {
|
||||
typeElement.type.forAllInnerTypes { type ->
|
||||
if (type.nullability == Nullability.Default) {
|
||||
context.elementsInfoStorage.addEntry(type, UnknownNullability)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addInfoForFunction(function: JKKtFunction) {
|
||||
val psiMethod = function.psi<PsiMethod>() ?: return
|
||||
val descriptor = psiMethod.getJavaMethodDescriptor() ?: return
|
||||
val superDescriptorsInfo =
|
||||
descriptor.overriddenDescriptors.map { superDescriptor ->
|
||||
val psi = superDescriptor.findPsi() ?: return@map ExternalSuperFunctionInfo(descriptor)
|
||||
when (val symbol = context.symbolProvider.symbolsByPsi[psi]) {
|
||||
is JKUniverseMethodSymbol ->
|
||||
InternalSuperFunctionInfo(
|
||||
context.elementsInfoStorage.getOrCreateInfoForElement(symbol.target)
|
||||
)
|
||||
else -> ExternalSuperFunctionInfo(descriptor)
|
||||
}
|
||||
}
|
||||
context.elementsInfoStorage.addEntry(function, FunctionInfo(descriptor, superDescriptorsInfo))
|
||||
}
|
||||
|
||||
private fun JKType.forAllInnerTypes(action: (JKType) -> Unit) {
|
||||
action(this)
|
||||
if (this is JKParametrizedType) {
|
||||
parameters.forEach { it.forAllInnerTypes(action) }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user