com.lightningkite.khrysalis.analysis.safeLet.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-plugin-common Show documentation
Show all versions of kotlin-compiler-plugin-common Show documentation
Common translational tools between Typescript and Swift.
The newest version!
package com.lightningkite.khrysalis.analysis
import com.lightningkite.khrysalis.util.fqNameWithoutTypeArgs
import com.lightningkite.khrysalis.util.parentIfType
import com.lightningkite.khrysalis.util.simplerFqName
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.types.TypeUtils
fun KtExpression.isSimple(): Boolean = when (this) {
is KtNameReferenceExpression -> ([email protected] as? PropertyDescriptor)?.let {
it.delegateField == null && it.getter == null && !it.isVar && it.containingDeclaration !is ClassDescriptor
} ?: ([email protected] as? VariableDescriptor)?.let {
!it.isVar && it.containingDeclaration !is ClassDescriptor
} ?: ([email protected] is ParameterDescriptor)
is KtDotQualifiedExpression -> {
[email protected]?.type?.constructor?.declarationDescriptor?.simplerFqName == "java.util.Optional" &&
([email protected] as? KtReferenceExpression)?.resolvedReferenceTarget?.let { it as? CallableDescriptor }?.simplerFqName == "com.lightningkite.rx.kotlin"
}
is KtConstantExpression,
is KtThisExpression -> true
else -> false
}
val KtExpression.actuallyCouldBeExpression: Boolean
get() {
val exp = this
if (exp is KtStatementExpression) {
return false
}
if(exp !is KtConstantExpression && exp.resolvedExpressionTypeInfo?.type?.fqNameWithoutTypeArgs == "kotlin.Nothing") return false
var parentControlBody: KtContainerNodeForControlStructureBody? =
exp.parent as? KtContainerNodeForControlStructureBody
(exp.parent as? KtBlockExpression)?.let {
if (it.statements.lastOrNull() != exp) {
return false
}
(it.parent as? KtFunctionLiteral)?.let {
return determineMaybeExpressionLambda(it)
}
//Check if control is expression
if(it.parent is KtWhenEntry) return (it.parent!!.parent as KtExpression).actuallyCouldBeExpression
if(it.parent is KtTryExpression) return (it.parent as KtExpression).actuallyCouldBeExpression
if(it.parent is KtCatchClause) return (it.parent!!.parent as KtExpression).actuallyCouldBeExpression
parentControlBody = it.parent as? KtContainerNodeForControlStructureBody ?: return false
}
parentControlBody?.let { return determineMaybeExpressionControl(it) }
return true
}
private fun determineMaybeExpressionLambda(it: KtFunctionLiteral): Boolean {
it.resolvedExpectedReturnType?.let { expected ->
if (expected !is TypeUtils.SpecialType) {
if(expected.fqNameWithoutTypeArgs in KotlinInfo.dontReturnTypes) {
return false
}
}
}
if(it
.parentIfType()
?.let {
it.parentIfType() ?: it.parentIfType()?.parentIfType()
}
?.parentIfType()
?.let {
if((it.parent as? KtExpression)?.let {
it.isSafeLetDirect() && !it.actuallyCouldBeExpression
} == true){
return false
}
it.parentIfType()
?: it.parentIfType()
?.parentIfType()
}
?.let { it.isSafeLetChain() && !it.safeLetChainRoot().actuallyCouldBeExpression } == true
){
return false
}
return true
}
private fun determineMaybeExpressionControl(it: KtContainerNodeForControlStructureBody): Boolean {
(it.parent as? KtIfExpression)?.let {
return it.actuallyCouldBeExpression
}
(it.parent as? KtWhenExpression)?.let {
return it.actuallyCouldBeExpression
}
(it.parent as? KtTryExpression)?.let {
return it.actuallyCouldBeExpression
}
return false
}
fun KtExpression.isSafeLetDirect(): Boolean {
if (this !is KtSafeQualifiedExpression) return false
val callExpression = this.selectorExpression as? KtCallExpression ?: return false
if (callExpression.lambdaArguments.isEmpty()) return false
if ((callExpression.calleeExpression as? KtReferenceExpression)?.resolvedReferenceTarget?.fqNameSafe?.asString() != "kotlin.let") return false
return true
}
fun KtExpression.isRunDirect(): Boolean {
if (this !is KtCallExpression) return false
if (this.lambdaArguments.isEmpty()) return false
if ((this.calleeExpression as? KtReferenceExpression)?.resolvedReferenceTarget?.fqNameSafe?.asString() != "kotlin.run") return false
return true
}
fun KtBinaryExpression.isSafeLetChain(): Boolean {
if (this.operationToken != KtTokens.ELVIS) return false
if (this.left?.isSafeLetDirect() == true) return true
return (this.left as? KtBinaryExpression)?.isSafeLetChain() == true
}
fun KtBinaryExpression.safeLetChainRoot(): KtBinaryExpression {
(this.parent as? KtBinaryExpression)?.let { p ->
if (p.left == this) {
if (p.operationToken == KtTokens.ELVIS) {
return p.safeLetChainRoot()
}
}
}
return this
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy