New J2K: use KotlinExceptionWithAttachments to report tree building errors

Also, try not to throw exceptions when possible
This commit is contained in:
Ilya Kirillov
2019-09-25 17:40:48 +03:00
parent 3e2dac6586
commit 392a75e6b8
18 changed files with 93 additions and 74 deletions
@@ -206,7 +206,7 @@ open class BoundTypeCalculatorImpl(
arguments.mapIndexed { i, argument -> arguments.mapIndexed { i, argument ->
TypeParameter( TypeParameter(
argument.type.boundTypeUnenhanced( argument.type.boundTypeUnenhanced(
typeVariable?.typeParameters?.get(i)?.boundType?.label?.safeAs<TypeVariableLabel>()?.typeVariable, typeVariable?.typeParameters?.getOrNull(i)?.boundType?.label?.safeAs<TypeVariableLabel>()?.typeVariable,
contextBoundType, contextBoundType,
call, call,
isImplicitReceiver, isImplicitReceiver,
@@ -77,7 +77,7 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing
?.returnedExpression ?.returnedExpression
?.unpackedReferenceToProperty() ?.unpackedReferenceToProperty()
?.takeIf { ?.takeIf {
it.type() == this.type()!! it.type() == type() ?: return@takeIf false
} }
return RealGetter(this, target, name) return RealGetter(this, target, name)
} }
@@ -184,7 +184,7 @@ class ConvertGettersAndSettersToPropertyProcessing : ElementsBasedPostProcessing
ktSetter.filterModifiers() ktSetter.filterModifiers()
if (setter is RealSetter) { if (setter is RealSetter) {
setter.function.forAllUsages { usage -> setter.function.forAllUsages { usage ->
val callExpression = usage.getStrictParentOfType<KtCallExpression>()!! val callExpression = usage.getStrictParentOfType<KtCallExpression>() ?: return@forAllUsages
val qualifier = callExpression.getQualifiedExpressionForSelector() val qualifier = callExpression.getQualifiedExpressionForSelector()
val newValue = callExpression.valueArguments.single() val newValue = callExpression.valueArguments.single()
if (qualifier != null) { if (qualifier != null) {
@@ -85,7 +85,7 @@ val removeUselessCastDiagnosticBasedProcessing =
val removeInnecessaryNotNullAssertionDiagnosticBasedProcessing = val removeInnecessaryNotNullAssertionDiagnosticBasedProcessing =
diagnosticBasedProcessing<KtSimpleNameExpression>(Errors.UNNECESSARY_NOT_NULL_ASSERTION) { element, _ -> diagnosticBasedProcessing<KtSimpleNameExpression>(Errors.UNNECESSARY_NOT_NULL_ASSERTION) { element, _ ->
val exclExclExpr = element.parent as KtUnaryExpression val exclExclExpr = element.parent as KtUnaryExpression
val baseExpression = exclExclExpr.baseExpression!! val baseExpression = exclExclExpr.baseExpression ?: return@diagnosticBasedProcessing
val context = baseExpression.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS) val context = baseExpression.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS)
if (context.diagnostics.forElement(element).any { it.factory == Errors.UNNECESSARY_NOT_NULL_ASSERTION }) { if (context.diagnostics.forElement(element).any { it.factory == Errors.UNNECESSARY_NOT_NULL_ASSERTION }) {
exclExclExpr.replace(baseExpression) exclExclExpr.replace(baseExpression)
@@ -82,7 +82,7 @@ class RemoveRedundantNullabilityProcessing : InspectionLikeProcessingForElement<
override fun apply(element: KtProperty) { override fun apply(element: KtProperty) {
val typeElement = element.typeReference?.typeElement val typeElement = element.typeReference?.typeElement
typeElement?.replace(typeElement.cast<KtNullableType>().innerType!!) typeElement?.replace(typeElement.safeAs<KtNullableType>()?.innerType ?: return)
} }
} }
@@ -269,8 +269,8 @@ class JavaObjectEqualsToEqOperatorProcessing : InspectionLikeProcessingForElemen
element.getQualifiedExpressionForSelectorOrThis().replace( element.getQualifiedExpressionForSelectorOrThis().replace(
factory.createExpressionByPattern( factory.createExpressionByPattern(
"($0 == $1)", "($0 == $1)",
element.valueArguments[0].getArgumentExpression()!!, element.valueArguments[0].getArgumentExpression() ?: return,
element.valueArguments[1].getArgumentExpression()!! element.valueArguments[1].getArgumentExpression() ?: return
) )
) )
} }
@@ -312,7 +312,7 @@ class RemoveRedundantModalityModifierProcessing : InspectionLikeProcessingForEle
} }
override fun apply(element: KtDeclaration) { override fun apply(element: KtDeclaration) {
element.removeModifier(element.modalityModifierType()!!) element.removeModifier(element.modalityModifierType() ?: return)
} }
} }
@@ -329,7 +329,7 @@ class RemoveRedundantVisibilityModifierProcessing : InspectionLikeProcessingForE
} }
override fun apply(element: KtDeclaration) { override fun apply(element: KtDeclaration) {
element.removeModifier(element.visibilityModifierType()!!) element.removeModifier(element.visibilityModifierType() ?: return)
} }
} }
@@ -41,16 +41,17 @@ import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
import org.jetbrains.kotlin.j2k.ReferenceSearcher import org.jetbrains.kotlin.j2k.ReferenceSearcher
import org.jetbrains.kotlin.j2k.ast.Nullability import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.nj2k.symbols.* import org.jetbrains.kotlin.nj2k.symbols.*
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.JKLiteralExpression.LiteralType.* import org.jetbrains.kotlin.nj2k.tree.JKLiteralExpression.LiteralType.*
import org.jetbrains.kotlin.nj2k.types.* import org.jetbrains.kotlin.nj2k.types.*
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -249,7 +250,7 @@ class JavaToJKTreeBuilder constructor(
JavaTokenType.LONG_LITERAL -> JKLiteralExpression(text, LONG) JavaTokenType.LONG_LITERAL -> JKLiteralExpression(text, LONG)
JavaTokenType.FLOAT_LITERAL -> JKLiteralExpression(text, FLOAT) JavaTokenType.FLOAT_LITERAL -> JKLiteralExpression(text, FLOAT)
JavaTokenType.DOUBLE_LITERAL -> JKLiteralExpression(text, DOUBLE) JavaTokenType.DOUBLE_LITERAL -> JKLiteralExpression(text, DOUBLE)
else -> error("Unknown literal element type: ${this.literalElementType}") else -> throwCanNotConvertError("Unknown literal element type: $literalElementType")
}.also { }.also {
it.assignNonCodeElements(this) it.assignNonCodeElements(this)
} }
@@ -531,7 +532,7 @@ class JavaToJKTreeBuilder constructor(
fun PsiTypeCastExpression.toJK(): JKExpression { fun PsiTypeCastExpression.toJK(): JKExpression {
return JKTypeCastExpression( return JKTypeCastExpression(
operand?.toJK() ?: throwCanNotConvertError(), operand?.toJK() ?: throwCanNotConvertError(),
castType?.type?.toJK()?.asTypeElement() ?: throwCanNotConvertError() (castType?.type?.toJK() ?: JKNoType).asTypeElement()
).also { ).also {
it.assignNonCodeElements(this) it.assignNonCodeElements(this)
} }
@@ -647,10 +648,12 @@ class JavaToJKTreeBuilder constructor(
with(expressionTreeMapper) { argumentList?.toJK() ?: JKArgumentList() }, with(expressionTreeMapper) { argumentList?.toJK() ?: JKArgumentList() },
initializingClass?.createClassBody() ?: JKClassBody(), initializingClass?.createClassBody() ?: JKClassBody(),
JKTypeElement( JKTypeElement(
JKClassType( containingClass?.let { klass ->
symbolProvider.provideDirectSymbol(containingClass ?: throwCanNotConvertError()) as JKClassSymbol, JKClassType(
emptyList() symbolProvider.provideDirectSymbol(klass) as JKClassSymbol,
) emptyList()
)
} ?: JKNoType
) )
).also { ).also {
symbolProvider.provideUniverseSymbol(this, it) symbolProvider.provideUniverseSymbol(this, it)
@@ -701,15 +704,18 @@ class JavaToJKTreeBuilder constructor(
} }
fun <T : PsiModifierListOwner> T.annotationList(docCommentOwner: PsiDocCommentOwner?): JKAnnotationList { fun <T : PsiModifierListOwner> T.annotationList(docCommentOwner: PsiDocCommentOwner?): JKAnnotationList {
val plainAnnotations = annotations.map { it.cast<PsiAnnotation>().toJK() } val deprecatedAnnotation = docCommentOwner?.docComment?.deprecatedAnnotation()
val deprecatedAnnotation = docCommentOwner?.docComment?.deprecatedAnnotation() ?: return JKAnnotationList(plainAnnotations) val plainAnnotations = annotations.mapNotNull { annotation ->
return JKAnnotationList( when {
plainAnnotations.mapNotNull { annotation -> annotation !is PsiAnnotation -> null
if (annotation.classSymbol.fqName == "java.lang.Deprecated") null else annotation annotation.qualifiedName == DEPRECATED_ANNOTAION_FQ_NAME && deprecatedAnnotation != null -> null
} + deprecatedAnnotation else -> annotation.toJK()
) }
}
return JKAnnotationList(plainAnnotations + listOfNotNull(deprecatedAnnotation))
} }
fun PsiAnnotation.toJK(): JKAnnotation = fun PsiAnnotation.toJK(): JKAnnotation =
JKAnnotation( JKAnnotation(
symbolProvider.provideSymbolForReference<JKSymbol>( symbolProvider.provideSymbolForReference<JKSymbol>(
@@ -755,9 +761,10 @@ class JavaToJKTreeBuilder constructor(
fun PsiAnnotationMethod.toJK(): JKJavaAnnotationMethod = fun PsiAnnotationMethod.toJK(): JKJavaAnnotationMethod =
JKJavaAnnotationMethod( JKJavaAnnotationMethod(
returnType?.toJK()?.asTypeElement() JKTypeElement(
?: JKTypeElement(JKJavaVoidType).takeIf { isConstructor } returnType?.toJK()
?: throwCanNotConvertError("type of PsiAnnotationMethod can not be retrieved"), ?: JKJavaVoidType.takeIf { isConstructor }
?: JKNoType),
nameIdentifier.toJK(), nameIdentifier.toJK(),
defaultValue?.toJK() ?: JKStubExpression(), defaultValue?.toJK() ?: JKStubExpression(),
otherModifiers(), otherModifiers(),
@@ -772,9 +779,10 @@ class JavaToJKTreeBuilder constructor(
fun PsiMethod.toJK(): JKMethod { fun PsiMethod.toJK(): JKMethod {
return JKMethodImpl( return JKMethodImpl(
returnType?.toJK()?.asTypeElement() JKTypeElement(
?: JKTypeElement(JKJavaVoidType).takeIf { isConstructor } returnType?.toJK()
?: throwCanNotConvertError("type of PsiAnnotationMethod can not be retrieved"), ?: JKJavaVoidType.takeIf { isConstructor }
?: JKNoType),
nameIdentifier.toJK(), nameIdentifier.toJK(),
parameterList.parameters.map { it.toJK() }, parameterList.parameters.map { it.toJK() },
body?.toJK() ?: JKBodyStub, body?.toJK() ?: JKBodyStub,
@@ -845,11 +853,11 @@ class JavaToJKTreeBuilder constructor(
is PsiExpressionStatement -> JKExpressionStatement(with(expressionTreeMapper) { expression.toJK() }) is PsiExpressionStatement -> JKExpressionStatement(with(expressionTreeMapper) { expression.toJK() })
is PsiReturnStatement -> JKReturnStatement(with(expressionTreeMapper) { returnValue.toJK() }) is PsiReturnStatement -> JKReturnStatement(with(expressionTreeMapper) { returnValue.toJK() })
is PsiDeclarationStatement -> is PsiDeclarationStatement ->
JKDeclarationStatement(declaredElements.map { JKDeclarationStatement(declaredElements.mapNotNull {
when (it) { when (it) {
is PsiClass -> it.toJK() is PsiClass -> it.toJK()
is PsiLocalVariable -> it.toJK() is PsiLocalVariable -> it.toJK()
else -> it.throwCanNotConvertError() else -> null
} }
}) })
is PsiAssertStatement -> is PsiAssertStatement ->
@@ -993,7 +1001,7 @@ class JavaToJKTreeBuilder constructor(
this is PsiWhiteSpace -> JKSpaceElement(text) this is PsiWhiteSpace -> JKSpaceElement(text)
text == ";" -> null text == ";" -> null
text == "" -> null text == "" -> null
else -> error("Token should be either token or whitespace") else -> null
} ?: return null } ?: return null
tokenCache[this] = token tokenCache[this] = token
return token return token
@@ -1054,8 +1062,13 @@ class JavaToJKTreeBuilder constructor(
also { it.assignNonCodeElements(psi) } also { it.assignNonCodeElements(psi) }
private fun PsiElement.throwCanNotConvertError(message: String? = null): Nothing { private fun PsiElement.throwCanNotConvertError(message: String? = null): Nothing {
error("Cannot convert the following Java element ${this::class} with text `$text`" + message?.let { " due to `$it`" }.orEmpty()) throw KotlinExceptionWithAttachments("Cannot convert the following Java element ${this::class}" + message?.let { " due to `$it`" })
.withAttachment("elementText", text)
.withAttachment("file", containingFile?.text)
} }
companion object {
private const val DEPRECATED_ANNOTAION_FQ_NAME = "java.lang.Deprecated"
}
} }
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.nj2k.conversions package org.jetbrains.kotlin.nj2k.conversions
import com.intellij.psi.PsiClass
import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext import org.jetbrains.kotlin.nj2k.NewJ2kConverterContext
import org.jetbrains.kotlin.nj2k.declarationList import org.jetbrains.kotlin.nj2k.declarationList
import org.jetbrains.kotlin.nj2k.getCompanion import org.jetbrains.kotlin.nj2k.getCompanion
@@ -70,6 +71,8 @@ class ClassToObjectPromotionConversion(context: NewJ2kConverterContext) : Recurs
} }
} }
private fun JKClass.hasInheritors() = private fun JKClass.hasInheritors(): Boolean {
context.converter.converterServices.oldServices.referenceSearcher.hasInheritors(psi()!!) val psi = psi<PsiClass>() ?: return false
return context.converter.converterServices.oldServices.referenceSearcher.hasInheritors(psi)
}
} }
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.nj2k.conversions package org.jetbrains.kotlin.nj2k.conversions
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.nj2k.* import org.jetbrains.kotlin.nj2k.*
import org.jetbrains.kotlin.nj2k.symbols.JKUniverseMethodSymbol import org.jetbrains.kotlin.nj2k.symbols.JKUniverseMethodSymbol
import org.jetbrains.kotlin.nj2k.tree.* import org.jetbrains.kotlin.nj2k.tree.*
@@ -22,7 +23,7 @@ class DefaultArgumentsConversion(context: NewJ2kConverterContext) : RecursiveApp
|| hasOtherModifier(OtherModifier.OVERRIDE) || hasOtherModifier(OtherModifier.OVERRIDE)
|| hasOtherModifier(OtherModifier.NATIVE) || hasOtherModifier(OtherModifier.NATIVE)
|| hasOtherModifier(OtherModifier.SYNCHRONIZED) || hasOtherModifier(OtherModifier.SYNCHRONIZED)
|| context.converter.converterServices.oldServices.referenceSearcher.hasOverrides(psi()!!) || psi<PsiMethod>()?.let { context.converter.converterServices.oldServices.referenceSearcher.hasOverrides(it) } == true
|| annotationList.annotations.isNotEmpty() || annotationList.annotations.isNotEmpty()
|| canBeGetterOrSetter() || canBeGetterOrSetter()
@@ -28,14 +28,15 @@ class EnumFieldAccessConversion(context: NewJ2kConverterContext) : RecursiveAppl
) )
} }
private fun JKFieldSymbol.enumClassSymbol(): JKClassSymbol? = private fun JKFieldSymbol.enumClassSymbol(): JKClassSymbol? {
when { return when {
this is JKMultiverseFieldSymbol && target is PsiEnumConstant -> this is JKMultiverseFieldSymbol && target is PsiEnumConstant ->
symbolProvider.provideDirectSymbol(target.containingClass!!) as JKClassSymbol symbolProvider.provideDirectSymbol(target.containingClass ?: return null) as? JKClassSymbol
this is JKMultiverseKtEnumEntrySymbol -> this is JKMultiverseKtEnumEntrySymbol ->
symbolProvider.provideDirectSymbol(target.containingClass()!!) as JKClassSymbol symbolProvider.provideDirectSymbol(target.containingClass() ?: return null) as? JKClassSymbol
this is JKUniverseFieldSymbol && target is JKEnumConstant -> this is JKUniverseFieldSymbol && target is JKEnumConstant ->
symbolProvider.provideUniverseSymbol(target.parentOfType<JKClass>()!!) symbolProvider.provideUniverseSymbol(target.parentOfType<JKClass>() ?: return null)
else -> null else -> null
} }
}
} }
@@ -30,8 +30,8 @@ class ImplicitCastsConversion(context: NewJ2kConverterContext) : RecursiveApplic
private fun convertBinaryExpression(binaryExpression: JKBinaryExpression): JKExpression { private fun convertBinaryExpression(binaryExpression: JKBinaryExpression): JKExpression {
fun JKBinaryExpression.convertBinaryOperationWithChar(): JKBinaryExpression { fun JKBinaryExpression.convertBinaryOperationWithChar(): JKBinaryExpression {
val leftType = left.calculateType(typeFactory).asPrimitiveType() ?: return this val leftType = left.calculateType(typeFactory)?.asPrimitiveType() ?: return this
val rightType = right.calculateType(typeFactory).asPrimitiveType() ?: return this val rightType = right.calculateType(typeFactory)?.asPrimitiveType() ?: return this
val leftOperandCastedCasted by lazy(LazyThreadSafetyMode.NONE) { val leftOperandCastedCasted by lazy(LazyThreadSafetyMode.NONE) {
JKBinaryExpression( JKBinaryExpression(
@@ -97,7 +97,7 @@ class ImplicitCastsConversion(context: NewJ2kConverterContext) : RecursiveApplic
private fun JKExpression.castStringToRegex(toType: JKType): JKExpression? { private fun JKExpression.castStringToRegex(toType: JKType): JKExpression? {
if (toType.safeAs<JKClassType>()?.classReference?.fqName != "java.util.regex.Pattern") return null if (toType.safeAs<JKClassType>()?.classReference?.fqName != "java.util.regex.Pattern") return null
val expressionType = calculateType(typeFactory) val expressionType = calculateType(typeFactory) ?: return null
if (!expressionType.isStringType()) return null if (!expressionType.isStringType()) return null
return JKQualifiedExpression( return JKQualifiedExpression(
copyTreeAndDetach().parenthesizeIfBinaryExpression(), copyTreeAndDetach().parenthesizeIfBinaryExpression(),
@@ -117,7 +117,7 @@ class ImplicitCastsConversion(context: NewJ2kConverterContext) : RecursiveApplic
val casted = expression.castToAsPrimitiveTypes(toType, strict) ?: return null val casted = expression.castToAsPrimitiveTypes(toType, strict) ?: return null
return JKPrefixExpression(casted, operator) return JKPrefixExpression(casted, operator)
} }
val expressionTypeAsPrimitive = calculateType(typeFactory).asPrimitiveType() ?: return null val expressionTypeAsPrimitive = calculateType(typeFactory)?.asPrimitiveType() ?: return null
val toTypeAsPrimitive = toType.asPrimitiveType() ?: return null val toTypeAsPrimitive = toType.asPrimitiveType() ?: return null
if (toTypeAsPrimitive == expressionTypeAsPrimitive) return null if (toTypeAsPrimitive == expressionTypeAsPrimitive) return null
@@ -67,7 +67,7 @@ class ImplicitInitializerConversion(context: NewJ2kConverterContext) : Recursive
.toMap() .toMap()
.toMutableMap() .toMutableMap()
val constructorsWithInitializers = findUsages(parentOfType<JKClass>()!!, context).mapNotNull { usage -> val constructorsWithInitializers = findUsages(containingClass, context).mapNotNull { usage ->
val parent = usage.parent val parent = usage.parent
val assignmentStatement = val assignmentStatement =
when { when {
@@ -75,8 +75,7 @@ class MethodReferenceToLambdaConversion(context: NewJ2kConverterContext) : Recur
JKArgumentList(arguments) JKArgumentList(arguments)
) )
is JKClassSymbol -> JKNewExpression(symbol, JKArgumentList(), JKTypeArgumentList()) is JKClassSymbol -> JKNewExpression(symbol, JKArgumentList(), JKTypeArgumentList())
is JKUnresolvedSymbol -> return recurse(element) else -> return recurse(element)
else -> error("Symbol should be either method symbol or class symbol, but it is ${symbol::class}")
} }
val qualifier = when { val qualifier = when {
receiverParameter != null -> receiverParameter != null ->
@@ -94,8 +93,7 @@ class MethodReferenceToLambdaConversion(context: NewJ2kConverterContext) : Recur
when (symbol) { when (symbol) {
is JKMethodSymbol -> symbol.returnType ?: JKNoType is JKMethodSymbol -> symbol.returnType ?: JKNoType
is JKClassSymbol -> JKClassType(symbol) is JKClassSymbol -> JKClassType(symbol)
is JKUnresolvedSymbol -> return recurse(element) else -> return recurse(element)
else -> error("Symbol should be either method symbol or class symbol, but it is ${symbol::class}")
} }
) )
) )
@@ -15,8 +15,8 @@ class AnyWithStringConcatenationConversion(context: NewJ2kConverterContext) : Re
override fun applyToElement(element: JKTreeElement): JKTreeElement { override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKBinaryExpression) return recurse(element) if (element !is JKBinaryExpression) return recurse(element)
if (element.operator.token == JKOperatorToken.PLUS if (element.operator.token == JKOperatorToken.PLUS
&& element.right.calculateType(typeFactory).isStringType() && element.right.calculateType(typeFactory)?.isStringType() == true
&& !element.left.calculateType(typeFactory).isStringType() && element.left.calculateType(typeFactory)?.isStringType() == false
) { ) {
return recurse( return recurse(
JKBinaryExpression( JKBinaryExpression(
@@ -115,7 +115,7 @@ class SwitchStatementConversion(context: NewJ2kConverterContext) : RecursiveAppl
this is JKIfElseStatement || this is JKIfElseStatement ||
this is JKJavaSwitchStatement || this is JKJavaSwitchStatement ||
this is JKKtWhenStatement -> this is JKKtWhenStatement ->
this.psi!!.canCompleteNormally() psi?.canCompleteNormally() == true
else -> true else -> true
} }
@@ -46,11 +46,13 @@ class JKMultiverseKtEnumEntrySymbol(
override val typeFactory: JKTypeFactory override val typeFactory: JKTypeFactory
) : JKFieldSymbol(), JKMultiverseKtSymbol<KtEnumEntry> { ) : JKFieldSymbol(), JKMultiverseKtSymbol<KtEnumEntry> {
override val fieldType: JKType? override val fieldType: JKType?
get() = JKClassType( get() = target.containingClass()?.let { klass ->
symbolProvider.provideDirectSymbol(target.containingClass()!!) as JKClassSymbol, JKClassType(
emptyList(), symbolProvider.provideDirectSymbol(klass) as? JKClassSymbol ?: return@let null,
Nullability.NotNull emptyList(),
) Nullability.NotNull
)
}
} }
class JKUnresolvedField( class JKUnresolvedField(
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.nj2k.types.*
abstract class JKExpression : JKAnnotationMemberValue(), PsiOwner by PsiOwnerImpl() { abstract class JKExpression : JKAnnotationMemberValue(), PsiOwner by PsiOwnerImpl() {
// we don't need exact type here (eg with substituted type parameters) // we don't need exact type here (eg with substituted type parameters)
abstract fun calculateType(typeFactory: JKTypeFactory): JKType abstract fun calculateType(typeFactory: JKTypeFactory): JKType?
} }
abstract class JKOperatorExpression : JKExpression() { abstract class JKOperatorExpression : JKExpression() {
@@ -92,7 +92,7 @@ class JKLiteralExpression(
} }
class JKStubExpression : JKExpression() { class JKStubExpression : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = JKNoType override fun calculateType(typeFactory: JKTypeFactory): JKType? = null
override fun accept(visitor: JKVisitor) = visitor.visitStubExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitStubExpression(this)
} }
@@ -118,7 +118,7 @@ class JKIfElseExpression(
var thenBranch by child(thenBranch) var thenBranch by child(thenBranch)
var elseBranch by child(elseBranch) var elseBranch by child(elseBranch)
override fun calculateType(typeFactory: JKTypeFactory): JKType = type override fun calculateType(typeFactory: JKTypeFactory): JKType? = type
override fun accept(visitor: JKVisitor) = visitor.visitIfElseExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitIfElseExpression(this)
} }
@@ -133,7 +133,7 @@ class JKLambdaExpression(
var functionalType by child(functionalType) var functionalType by child(functionalType)
val returnType by child(returnType) val returnType by child(returnType)
override fun calculateType(typeFactory: JKTypeFactory): JKType = JKNoType override fun calculateType(typeFactory: JKTypeFactory): JKType? = null
override fun accept(visitor: JKVisitor) = visitor.visitLambdaExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitLambdaExpression(this)
} }
@@ -141,7 +141,7 @@ class JKLambdaExpression(
abstract class JKCallExpression : JKExpression(), JKTypeArgumentListOwner { abstract class JKCallExpression : JKExpression(), JKTypeArgumentListOwner {
abstract val identifier: JKMethodSymbol abstract val identifier: JKMethodSymbol
abstract var arguments: JKArgumentList abstract var arguments: JKArgumentList
override fun calculateType(typeFactory: JKTypeFactory): JKType = identifier.returnType ?: JKNoType override fun calculateType(typeFactory: JKTypeFactory): JKType? = identifier.returnType
} }
class JKDelegationConstructorCall( class JKDelegationConstructorCall(
@@ -181,18 +181,18 @@ class JKNewExpression(
class JKFieldAccessExpression(var identifier: JKFieldSymbol) : JKExpression() { class JKFieldAccessExpression(var identifier: JKFieldSymbol) : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = identifier.fieldType ?: JKNoType override fun calculateType(typeFactory: JKTypeFactory) = identifier.fieldType
override fun accept(visitor: JKVisitor) = visitor.visitFieldAccessExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitFieldAccessExpression(this)
} }
class JKPackageAccessExpression(var identifier: JKPackageSymbol) : JKExpression() { class JKPackageAccessExpression(var identifier: JKPackageSymbol) : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = JKNoType override fun calculateType(typeFactory: JKTypeFactory): JKType? = null
override fun accept(visitor: JKVisitor) = visitor.visitPackageAccessExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitPackageAccessExpression(this)
} }
class JKClassAccessExpression(var identifier: JKClassSymbol) : JKExpression() { class JKClassAccessExpression(var identifier: JKClassSymbol) : JKExpression() {
override fun calculateType(typeFactory: JKTypeFactory) = JKNoType override fun calculateType(typeFactory: JKTypeFactory): JKType? = null
override fun accept(visitor: JKVisitor) = visitor.visitClassAccessExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitClassAccessExpression(this)
} }
@@ -204,7 +204,7 @@ class JKMethodReferenceExpression(
) : JKExpression() { ) : JKExpression() {
val qualifier by child(qualifier) val qualifier by child(qualifier)
val functionalType by child(functionalType) val functionalType by child(functionalType)
override fun calculateType(typeFactory: JKTypeFactory): JKType = JKNoType override fun calculateType(typeFactory: JKTypeFactory): JKType? = null
override fun accept(visitor: JKVisitor) = visitor.visitMethodReferenceExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitMethodReferenceExpression(this)
} }
@@ -221,7 +221,7 @@ class JKClassLiteralExpression(
var literalType: ClassLiteralType var literalType: ClassLiteralType
) : JKExpression() { ) : JKExpression() {
val classType: JKTypeElement by child(classType) val classType: JKTypeElement by child(classType)
override fun calculateType(typeFactory: JKTypeFactory): JKType = when (literalType) { override fun calculateType(typeFactory: JKTypeFactory): JKType? = when (literalType) {
ClassLiteralType.KOTLIN_CLASS -> typeFactory.types.kotlinClass ClassLiteralType.KOTLIN_CLASS -> typeFactory.types.kotlinClass
else -> typeFactory.types.javaKlass else -> typeFactory.types.javaKlass
} }
@@ -289,7 +289,7 @@ class JKKtAnnotationArrayInitializerExpression(initializers: List<JKAnnotationMe
constructor(vararg initializers: JKAnnotationMemberValue) : this(initializers.toList()) constructor(vararg initializers: JKAnnotationMemberValue) : this(initializers.toList())
val initializers: List<JKAnnotationMemberValue> by children(initializers) val initializers: List<JKAnnotationMemberValue> by children(initializers)
override fun calculateType(typeFactory: JKTypeFactory) = JKNoType override fun calculateType(typeFactory: JKTypeFactory): JKType? = null
override fun accept(visitor: JKVisitor) = visitor.visitKtAnnotationArrayInitializerExpression(this) override fun accept(visitor: JKVisitor) = visitor.visitKtAnnotationArrayInitializerExpression(this)
} }
@@ -43,7 +43,7 @@ enum class OtherModifier(override val text: String) : Modifier {
VOLATILE("volatile") VOLATILE("volatile")
} }
abstract class JKModifierElement : JKTreeElement() sealed class JKModifierElement : JKTreeElement()
interface JKOtherModifiersOwner : JKModifiersListOwner { interface JKOtherModifiersOwner : JKModifiersListOwner {
@@ -131,7 +131,6 @@ val JKModifierElement.modifier: Modifier
is JKModalityModifierElement -> modality is JKModalityModifierElement -> modality
is JKVisibilityModifierElement -> visibility is JKVisibilityModifierElement -> visibility
is JKOtherModifierElement -> otherModifier is JKOtherModifierElement -> otherModifier
else -> error("")
} }
@@ -107,7 +107,9 @@ class JKTypeFactory(val symbolProvider: JKSymbolProvider) {
} }
is PsiCapturedWildcardType -> is PsiCapturedWildcardType ->
JKCapturedType(fromPsiType(type.wildcard) as JKWildCardType) JKCapturedType(fromPsiType(type.wildcard) as JKWildCardType)
else -> throw Exception("Invalid PSI ${this::class.java}") is PsiIntersectionType -> // TODO what to do with intersection types? old j2k just took the first conjunct
fromPsiType(type.representative)
else -> throw Exception("Invalid PSI ${type::class.java}")
} }
private fun createKotlinType(type: KotlinType): JKType { private fun createKotlinType(type: KotlinType): JKType {
@@ -78,7 +78,7 @@ fun JKType.applyRecursive(transform: (JKType) -> JKType?): JKType =
is JKJavaDisjunctionType -> is JKJavaDisjunctionType ->
JKJavaDisjunctionType(disjunctions.map { it.applyRecursive(transform) }, nullability) JKJavaDisjunctionType(disjunctions.map { it.applyRecursive(transform) }, nullability)
is JKStarProjectionType -> this is JKStarProjectionType -> this
else -> TODO(this::class.toString()) else -> this
} }
inline fun <reified T : JKType> T.updateNullability(newNullability: Nullability): T = inline fun <reified T : JKType> T.updateNullability(newNullability: Nullability): T =
@@ -92,7 +92,7 @@ inline fun <reified T : JKType> T.updateNullability(newNullability: Nullability)
is JKJavaArrayType -> JKJavaArrayType(type, newNullability) is JKJavaArrayType -> JKJavaArrayType(type, newNullability)
is JKContextType -> JKContextType is JKContextType -> JKContextType
is JKJavaDisjunctionType -> this is JKJavaDisjunctionType -> this
else -> TODO(this::class.toString()) else -> this
} as T } as T
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")