[ULC] Better nullability annotations for light classes
This commit is contained in:
+10
-5
@@ -10,6 +10,7 @@ import com.intellij.util.IncorrectOperationException
|
|||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
||||||
import org.jetbrains.kotlin.asJava.classes.*
|
import org.jetbrains.kotlin.asJava.classes.*
|
||||||
|
import org.jetbrains.kotlin.asJava.fastCheckIsNullabilityApplied
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
@@ -76,12 +77,16 @@ abstract class KtLightModifierList<out T : KtLightElement<KtModifierListOwner, P
|
|||||||
if ((modifierListOwner is KtLightMember<*> && modifierListOwner !is KtLightFieldImpl.KtLightEnumConstant)
|
if ((modifierListOwner is KtLightMember<*> && modifierListOwner !is KtLightFieldImpl.KtLightEnumConstant)
|
||||||
|| modifierListOwner is LightParameter
|
|| modifierListOwner is LightParameter
|
||||||
) {
|
) {
|
||||||
val nullabilityAnnotation = when (modifierListOwner) {
|
|
||||||
is KtUltraLightElementWithNullabilityAnnotation<*, *> -> KtUltraLightNullabilityAnnotation(modifierListOwner, this)
|
|
||||||
else -> KtLightNullabilityAnnotation(modifierListOwner as KtLightElement<*, PsiModifierListOwner>, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
return annotationsForEntries + listOf(nullabilityAnnotation)
|
if (fastCheckIsNullabilityApplied(modifierListOwner)) {
|
||||||
|
|
||||||
|
val nullabilityAnnotation = when (modifierListOwner) {
|
||||||
|
is KtUltraLightElementWithNullabilityAnnotation<*, *> -> KtUltraLightNullabilityAnnotation(modifierListOwner, this)
|
||||||
|
else -> KtLightNullabilityAnnotation(modifierListOwner as KtLightElement<*, PsiModifierListOwner>, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
return annotationsForEntries + listOf(nullabilityAnnotation)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return annotationsForEntries
|
return annotationsForEntries
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.jetbrains.annotations.TestOnly
|
|||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
import org.jetbrains.kotlin.asJava.classes.cannotModify
|
import org.jetbrains.kotlin.asJava.classes.cannotModify
|
||||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||||
|
import org.jetbrains.kotlin.asJava.fastCheckIsNullabilityApplied
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
@@ -37,6 +38,7 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.hasSuspendModifier
|
import org.jetbrains.kotlin.psi.psiUtil.hasSuspendModifier
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.isPrivate
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils
|
import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
@@ -308,14 +310,15 @@ open class KtLightNullabilityAnnotation<D : KtLightElement<*, PsiModifierListOwn
|
|||||||
?: // it is out of our hands
|
?: // it is out of our hands
|
||||||
return getClsNullabilityAnnotation(member)?.qualifiedName
|
return getClsNullabilityAnnotation(member)?.qualifiedName
|
||||||
|
|
||||||
|
if (!fastCheckIsNullabilityApplied(member)) return null
|
||||||
|
|
||||||
// all data-class generated members are not-null
|
// all data-class generated members are not-null
|
||||||
if (annotatedElement is KtClass && annotatedElement.isData()) return NotNull::class.java.name
|
if (annotatedElement is KtClass && annotatedElement.isData()) return NotNull::class.java.name
|
||||||
|
|
||||||
// objects and companion objects are not null
|
// objects and companion objects are not null but ctor that does not annotated
|
||||||
if (annotatedElement is KtObjectDeclaration) return NotNull::class.java.name
|
if (annotatedElement is KtObjectDeclaration) {
|
||||||
|
if ((parent.parent as? PsiMethod)?.isConstructor == true) return null
|
||||||
if (annotatedElement is KtParameter) {
|
return NotNull::class.java.name
|
||||||
if (annotatedElement.containingClassOrObject?.isAnnotation() == true) return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't annotate property setters
|
// don't annotate property setters
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.intellij.psi.*
|
|||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||||
|
import org.jetbrains.kotlin.asJava.classes.KtUltraLightElementWithNullabilityAnnotation
|
||||||
import org.jetbrains.kotlin.asJava.elements.PsiElementWithOrigin
|
import org.jetbrains.kotlin.asJava.elements.PsiElementWithOrigin
|
||||||
import org.jetbrains.kotlin.asJava.elements.*
|
import org.jetbrains.kotlin.asJava.elements.*
|
||||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||||
@@ -30,9 +31,7 @@ import org.jetbrains.kotlin.load.java.propertyNameBySetMethodName
|
|||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Can be null in scripts and for elements from non-jvm modules.
|
* Can be null in scripts and for elements from non-jvm modules.
|
||||||
@@ -221,3 +220,32 @@ fun KtLightMethod.checkIsMangled(): Boolean {
|
|||||||
val originalName = propertyNameByAccessor(demangledName, this) ?: demangledName
|
val originalName = propertyNameByAccessor(demangledName, this) ?: demangledName
|
||||||
return originalName == kotlinOrigin?.name
|
return originalName == kotlinOrigin?.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun fastCheckIsNullabilityApplied(lightElement: KtLightElement<*, PsiModifierListOwner>): Boolean {
|
||||||
|
|
||||||
|
val annotatedElement = lightElement.kotlinOrigin ?: return true
|
||||||
|
|
||||||
|
// all data-class generated members are not-null
|
||||||
|
if (annotatedElement is KtClass && annotatedElement.isData()) return true
|
||||||
|
|
||||||
|
if (annotatedElement is KtParameter && lightElement !is PsiField) { //KtParameter but not it's backing field
|
||||||
|
val containingClassOrObject = annotatedElement.containingClassOrObject
|
||||||
|
if (containingClassOrObject?.isAnnotation() == true) return false
|
||||||
|
if ((containingClassOrObject as? KtClass)?.isEnum() == true) {
|
||||||
|
if (annotatedElement.parent.parent is KtPrimaryConstructor) return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val parent = annotatedElement.parent.parent
|
||||||
|
if (parent is KtModifierListOwner && parent.isPrivate()) return false
|
||||||
|
|
||||||
|
if (parent is KtPropertyAccessor) {
|
||||||
|
val propertyOfAccessor = parent.parent
|
||||||
|
if (propertyOfAccessor is KtProperty && propertyOfAccessor.isPrivate()) return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// private properties
|
||||||
|
if ((annotatedElement as? KtModifierListOwner)?.isPrivate() == true) return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user