Fix completion order & presentation wrt to DeprecatedSinceKotlin

This commit is contained in:
Mikhail Zarechenskiy
2020-06-19 02:18:14 +03:00
parent bcaa635a4e
commit beca7fca30
6 changed files with 56 additions and 15 deletions
@@ -108,19 +108,6 @@ internal sealed class DeprecatedByAnnotation(
} }
return StandardDeprecated(deprecatedAnnotation, target, propagatesToOverrides) return StandardDeprecated(deprecatedAnnotation, target, propagatesToOverrides)
} }
private fun computeLevelForDeprecatedSinceKotlin(annotation: AnnotationDescriptor, apiVersion: ApiVersion): DeprecationLevelValue? {
val hiddenSince = annotation.getSinceVersion("hiddenSince")
if (hiddenSince != null && apiVersion >= hiddenSince) return HIDDEN
val errorSince = annotation.getSinceVersion("errorSince")
if (errorSince != null && apiVersion >= errorSince) return ERROR
val warningSince = annotation.getSinceVersion("warningSince")
if (warningSince != null && apiVersion >= warningSince) return WARNING
return null
}
} }
} }
@@ -26,6 +26,19 @@ fun Deprecation.deprecatedByAnnotationReplaceWithExpression(): String? = (this a
fun AnnotationDescriptor.getSinceVersion(name: String): ApiVersion? = fun AnnotationDescriptor.getSinceVersion(name: String): ApiVersion? =
argumentValue(name)?.safeAs<StringValue>()?.value?.takeUnless(String::isEmpty)?.let(ApiVersion.Companion::parse) argumentValue(name)?.safeAs<StringValue>()?.value?.takeUnless(String::isEmpty)?.let(ApiVersion.Companion::parse)
fun computeLevelForDeprecatedSinceKotlin(annotation: AnnotationDescriptor, apiVersion: ApiVersion): DeprecationLevelValue? {
val hiddenSince = annotation.getSinceVersion("hiddenSince")
if (hiddenSince != null && apiVersion >= hiddenSince) return HIDDEN
val errorSince = annotation.getSinceVersion("errorSince")
if (errorSince != null && apiVersion >= errorSince) return ERROR
val warningSince = annotation.getSinceVersion("warningSince")
if (warningSince != null && apiVersion >= warningSince) return WARNING
return null
}
internal fun createDeprecationDiagnostic( internal fun createDeprecationDiagnostic(
element: PsiElement, deprecation: Deprecation, languageVersionSettings: LanguageVersionSettings element: PsiElement, deprecation: Deprecation, languageVersionSettings: LanguageVersionSettings
): Diagnostic { ): Diagnostic {
@@ -9,11 +9,14 @@ import com.intellij.psi.PsiClass
import com.intellij.psi.PsiDocCommentOwner import com.intellij.psi.PsiDocCommentOwner
import com.intellij.psi.PsiNamedElement import com.intellij.psi.PsiNamedElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.idea.imports.importableFqName
import org.jetbrains.kotlin.idea.project.languageVersionSettings
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.resolve.deprecation.computeLevelForDeprecatedSinceKotlin
import org.jetbrains.kotlin.util.descriptorsEqualWithSubstitution import org.jetbrains.kotlin.util.descriptorsEqualWithSubstitution
/** /**
@@ -56,8 +59,22 @@ abstract class DeclarationLookupObjectImpl(
override val isDeprecated: Boolean override val isDeprecated: Boolean
get() { get() {
return if (descriptor != null) return if (descriptor != null)
KotlinBuiltIns.isDeprecated(descriptor) isDeprecatedAtCallSite(descriptor, psiElement?.languageVersionSettings)
else else
(psiElement as? PsiDocCommentOwner)?.isDeprecated == true (psiElement as? PsiDocCommentOwner)?.isDeprecated == true
} }
}
// This function is kind of a hack to avoid using DeprecationResolver as it's hard to preserve same resolutionFacade for descriptor
private fun isDeprecatedAtCallSite(descriptor: DeclarationDescriptor, languageVersionSettings: LanguageVersionSettings?): Boolean {
val isDeprecatedAtDeclarationSite = KotlinBuiltIns.isDeprecated(descriptor)
if (languageVersionSettings == null) return isDeprecatedAtDeclarationSite
if (!isDeprecatedAtDeclarationSite) return false
return computeLevelForDeprecatedSinceKotlin(
descriptor.original.annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.deprecatedSinceKotlin) ?: return true,
languageVersionSettings.apiVersion
) != null
} }
@@ -0,0 +1,19 @@
fun foo1() {}
@Suppress("DEPRECATED_SINCE_KOTLIN_OUTSIDE_KOTLIN_SUBPACKAGE")
@Deprecated("")
@DeprecatedSinceKotlin(warningSince = "1.0")
fun foo2() {}
@Suppress("DEPRECATED_SINCE_KOTLIN_OUTSIDE_KOTLIN_SUBPACKAGE")
@Deprecated("")
@DeprecatedSinceKotlin(warningSince = "999.999")
fun foo3() {}
fun foo4() {}
fun test() {
foo<caret>
}
// ORDER: foo1, foo3, foo4, foo2
@@ -58,6 +58,11 @@ public class BasicCompletionWeigherTestGenerated extends AbstractBasicCompletion
runTest("idea/idea-completion/testData/weighers/basic/DeprecatedJavaClass.kt"); runTest("idea/idea-completion/testData/weighers/basic/DeprecatedJavaClass.kt");
} }
@TestMetadata("DeprecatedSinceKotlinFun.kt")
public void testDeprecatedSinceKotlinFun() throws Exception {
runTest("idea/idea-completion/testData/weighers/basic/DeprecatedSinceKotlinFun.kt");
}
@TestMetadata("DslCallWithExpectedType.kt") @TestMetadata("DslCallWithExpectedType.kt")
public void testDslCallWithExpectedType() throws Exception { public void testDslCallWithExpectedType() throws Exception {
runTest("idea/idea-completion/testData/weighers/basic/DslCallWithExpectedType.kt"); runTest("idea/idea-completion/testData/weighers/basic/DslCallWithExpectedType.kt");
@@ -1,6 +1,6 @@
@Suppress("DEPRECATED_SINCE_KOTLIN_OUTSIDE_KOTLIN_SUBPACKAGE") @Suppress("DEPRECATED_SINCE_KOTLIN_OUTSIDE_KOTLIN_SUBPACKAGE")
@Deprecated("") @Deprecated("")
@DeprecatedSinceKotlin(warningSince = "1.9") @DeprecatedSinceKotlin(warningSince = "999.999")
fun f(x: Int) {} fun f(x: Int) {}
fun d(x: Int) { fun d(x: Int) {