Fix CCE in constructNestedClassReferenceIdentifier J2K
#KT-17712 fixed
This commit is contained in:
@@ -123,15 +123,14 @@ class ConstructorConverter(
|
||||
val body = primaryConstructor.body
|
||||
|
||||
val parameterUsageReplacementMap = HashMap<String, String>()
|
||||
val correctedTypeConverter = converter.withSpecialContext(psiClass).typeConverter /* to correct nested class references */
|
||||
|
||||
val bodyGenerator: (CodeConverter) -> Block = if (body != null) {
|
||||
val statementsToRemove = HashSet<PsiStatement>()
|
||||
for (parameter in params) {
|
||||
val (field, initializationStatement) = findBackingFieldForConstructorParameter(parameter, primaryConstructor) ?: continue
|
||||
|
||||
val fieldType = correctedTypeConverter.convertVariableType(field)
|
||||
val parameterType = correctedTypeConverter.convertVariableType(parameter)
|
||||
val fieldType = converter.typeConverter.convertVariableType(field)
|
||||
val parameterType = converter.typeConverter.convertVariableType(parameter)
|
||||
// types can be different only in nullability
|
||||
val type = if (fieldType == parameterType) {
|
||||
fieldType
|
||||
@@ -175,27 +174,25 @@ class ConstructorConverter(
|
||||
|
||||
// we need to replace renamed parameter usages in base class constructor arguments and in default values
|
||||
|
||||
val correctedConverter = converter.withSpecialContext(psiClass) /* to correct nested class references */
|
||||
|
||||
fun CodeConverter.correct() = withSpecialExpressionConverter(ReplacingExpressionConverter(parameterUsageReplacementMap))
|
||||
|
||||
val statement = primaryConstructor.body?.statements?.firstOrNull()
|
||||
val methodCall = (statement as? PsiExpressionStatement)?.expression as? PsiMethodCallExpression
|
||||
if (methodCall != null && methodCall.isSuperConstructorCall()) {
|
||||
baseClassParams = methodCall.argumentList.expressions.map {
|
||||
correctedConverter.deferredElement { codeConverter -> codeConverter.correct().convertExpression(it) }
|
||||
converter.deferredElement { codeConverter -> codeConverter.correct().convertExpression(it) }
|
||||
}
|
||||
}
|
||||
else {
|
||||
baseClassParams = emptyList()
|
||||
}
|
||||
|
||||
val parameterList = correctedConverter.convertParameterList(
|
||||
val parameterList = converter.convertParameterList(
|
||||
primaryConstructor,
|
||||
overloadReducer,
|
||||
{ parameter, default ->
|
||||
if (!parameterToField.containsKey(parameter)) {
|
||||
correctedConverter.convertParameter(parameter, defaultValue = default)
|
||||
converter.convertParameter(parameter, defaultValue = default)
|
||||
}
|
||||
else {
|
||||
val (field, type) = parameterToField[parameter]!!
|
||||
|
||||
@@ -41,8 +41,7 @@ class Converter private constructor(
|
||||
val settings: ConverterSettings,
|
||||
val inConversionScope: (PsiElement) -> Boolean,
|
||||
val services: JavaToKotlinConverterServices,
|
||||
private val commonState: Converter.CommonState,
|
||||
private val personalState: Converter.PersonalState
|
||||
private val commonState: Converter.CommonState
|
||||
) {
|
||||
|
||||
// state which is shared between all converter's based on this one
|
||||
@@ -51,15 +50,10 @@ class Converter private constructor(
|
||||
val postUnfoldActions = ArrayList<() -> Unit>()
|
||||
}
|
||||
|
||||
// state which may differ in different converter's
|
||||
class PersonalState(val specialContext: PsiElement?)
|
||||
|
||||
val project: Project = elementToConvert.project
|
||||
val typeConverter: TypeConverter = TypeConverter(this)
|
||||
val annotationConverter: AnnotationConverter = AnnotationConverter(this)
|
||||
|
||||
val specialContext: PsiElement? = personalState.specialContext
|
||||
|
||||
val referenceSearcher: ReferenceSearcher = CachingReferenceSearcher(services.referenceSearcher)
|
||||
|
||||
val propertyDetectionCache = PropertyDetectionCache(this)
|
||||
@@ -68,15 +62,10 @@ class Converter private constructor(
|
||||
fun create(elementToConvert: PsiElement, settings: ConverterSettings, services: JavaToKotlinConverterServices,
|
||||
inConversionScope: (PsiElement) -> Boolean, usageProcessingsCollector: (UsageProcessing) -> Unit): Converter {
|
||||
return Converter(elementToConvert, settings, inConversionScope,
|
||||
services, CommonState(usageProcessingsCollector), PersonalState(null))
|
||||
services, CommonState(usageProcessingsCollector))
|
||||
}
|
||||
}
|
||||
|
||||
fun withSpecialContext(context: PsiElement): Converter = withState(PersonalState(context))
|
||||
|
||||
private fun withState(state: PersonalState): Converter
|
||||
= Converter(elementToConvert, settings, inConversionScope, services, commonState, state)
|
||||
|
||||
private fun createDefaultCodeConverter() = CodeConverter(this, DefaultExpressionConverter(), DefaultStatementConverter(), null)
|
||||
|
||||
data class IntermediateResult(
|
||||
@@ -134,14 +123,14 @@ class Converter private constructor(
|
||||
var i = 0
|
||||
while (i < commonState.deferredElements.size) {
|
||||
val deferredElement = commonState.deferredElements[i++]
|
||||
deferredElement.unfold(codeConverter.withConverter(this.withState(deferredElement.converterState)))
|
||||
deferredElement.unfold(codeConverter)
|
||||
}
|
||||
|
||||
commonState.postUnfoldActions.forEach { it() }
|
||||
}
|
||||
|
||||
fun <TResult : Element> deferredElement(generator: (CodeConverter) -> TResult): DeferredElement<TResult> {
|
||||
val element = DeferredElement(generator, personalState)
|
||||
val element = DeferredElement(generator)
|
||||
commonState.deferredElements.add(element)
|
||||
return element
|
||||
}
|
||||
@@ -686,7 +675,7 @@ class Converter private constructor(
|
||||
if (!hasExternalQualifier) {
|
||||
// references to nested classes may need correction
|
||||
if (targetClass != null) {
|
||||
val identifier = constructNestedClassReferenceIdentifier(targetClass, specialContext ?: element)
|
||||
val identifier = constructNestedClassReferenceIdentifier(targetClass, element)
|
||||
if (identifier != null) {
|
||||
return ReferenceElement(identifier, typeArgs).assignPrototype(element, CommentsAndSpacesInheritance.NO_SPACES)
|
||||
}
|
||||
@@ -701,7 +690,7 @@ class Converter private constructor(
|
||||
val outerClass = psiClass.containingClass
|
||||
if (outerClass != null
|
||||
&& !PsiTreeUtil.isAncestor(outerClass, context, true)
|
||||
&& !psiClass.isImported(context.containingFile as PsiJavaFile)) {
|
||||
&& !psiClass.isImported(elementToConvert.containingFile as PsiJavaFile)) {
|
||||
val qualifier = constructNestedClassReferenceIdentifier(outerClass, context)?.name ?: outerClass.name!!
|
||||
return Identifier.withNoPrototype(Identifier.toKotlin(qualifier) + "." + Identifier.toKotlin(psiClass.name!!))
|
||||
}
|
||||
|
||||
@@ -593,12 +593,11 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
|
||||
}
|
||||
|
||||
// add qualification for static members from base classes and also this works for enum constants in switch
|
||||
val context = converter.specialContext ?: expression
|
||||
if (target is PsiMember
|
||||
&& target.hasModifierProperty(PsiModifier.STATIC)
|
||||
&& target.containingClass != null
|
||||
&& !PsiTreeUtil.isAncestor(target.containingClass, context, true)
|
||||
&& !target.isImported(context.containingFile as PsiJavaFile)) {
|
||||
&& target.hasModifierProperty(PsiModifier.STATIC)
|
||||
&& target.containingClass != null
|
||||
&& !PsiTreeUtil.isAncestor(target.containingClass, expression, true)
|
||||
&& !target.isImported(expression.containingFile as PsiJavaFile)) {
|
||||
var member: PsiMember = target
|
||||
var code = Identifier.toKotlin(referenceName)
|
||||
while (true) {
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.j2k.ast
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.j2k.CodeBuilder
|
||||
import org.jetbrains.kotlin.j2k.CodeConverter
|
||||
import org.jetbrains.kotlin.j2k.Converter
|
||||
import org.jetbrains.kotlin.j2k.EmptyDocCommentConverter
|
||||
|
||||
fun <TElement: Element> TElement.assignPrototype(prototype: PsiElement?, inheritance: CommentsAndSpacesInheritance = CommentsAndSpacesInheritance()): TElement {
|
||||
@@ -109,8 +108,7 @@ abstract class Element {
|
||||
|
||||
// this class should never be created directly - Converter.deferredElement() should be used!
|
||||
class DeferredElement<TResult : Element>(
|
||||
private val generator: (CodeConverter) -> TResult,
|
||||
val converterState: Converter.PersonalState
|
||||
private val generator: (CodeConverter) -> TResult
|
||||
) : Element() {
|
||||
|
||||
private var result: TResult? = null
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
internal class A @JvmOverloads constructor(nested: A.Nested = A.Nested(A.Nested.FIELD)) {
|
||||
internal class A @JvmOverloads constructor(nested: Nested = Nested(Nested.FIELD)) {
|
||||
|
||||
internal class Nested(p: Int) {
|
||||
companion object {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
internal open class Base(nested: Base.Nested) {
|
||||
internal open class Base(nested: Nested) {
|
||||
|
||||
internal class Nested(p: Int) {
|
||||
companion object {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
internal class X(private val list: List<X.Y>) {
|
||||
internal class X(private val list: List<Y>) {
|
||||
|
||||
internal inner class Y
|
||||
}
|
||||
Reference in New Issue
Block a user