Add Kotlin DeprecationLevel into the REPL completion

This commit is contained in:
Ilya Muradyan
2021-05-05 02:49:30 +03:00
committed by TeamCityServer
parent 6bc4e124fb
commit e9af2849ef
4 changed files with 57 additions and 7 deletions
@@ -19,7 +19,8 @@ data class SourceCodeCompletionVariant(
val text: String, val text: String,
val displayText: String, val displayText: String,
val tail: String, val tail: String,
val icon: String val icon: String,
val deprecationLevel: DeprecationLevel? = null,
) )
interface ReplAnalyzerResultKeys interface ReplAnalyzerResultKeys
@@ -127,6 +127,39 @@ class ReplCompletionAndErrorsAnalysisTest : TestCase() {
} }
} }
@Test
fun testDeprecatedCompletion() = test {
run {
doCompile
code = """
@Deprecated("deprecated")
class Clazz1
@Deprecated("deprecated", level=DeprecationLevel.ERROR)
class Clazz2
""".trimIndent()
}
run {
doComplete
code = """
@Deprecated("deprecated1", level=DeprecationLevel.WA)
class Clazz3
@Deprecated("deprecated1", level=kotlin.annotation.AnnotationRetention.SOURCE)
class Clazz4
Claz
""".trimIndent()
cursor = code.length
expect {
addCompletion("Clazz3", "Clazz3", " (Line_2_simplescript)", "class", DeprecationLevel.WARNING)
addCompletion("Clazz4", "Clazz4", " (Line_2_simplescript)", "class", DeprecationLevel.WARNING)
addCompletion("Clazz1", "Clazz1", " (Line_1_simplescript)", "class", DeprecationLevel.WARNING)
addCompletion("Clazz2", "Clazz2", " (Line_1_simplescript)", "class", DeprecationLevel.ERROR)
}
}
}
@Test @Test
fun testExtensionMethods() = test { fun testExtensionMethods() = test {
run { run {
@@ -72,8 +72,8 @@ class TestConf {
class Expected(private val run: Run) { class Expected(private val run: Run) {
val completions = ExpectedList<SourceCodeCompletionVariant>(run::doComplete) val completions = ExpectedList<SourceCodeCompletionVariant>(run::doComplete)
fun addCompletion(text: String, displayText: String, tail: String, icon: String) { fun addCompletion(text: String, displayText: String, tail: String, icon: String, deprecationLevel: DeprecationLevel? = null) {
completions.add(SourceCodeCompletionVariant(text, displayText, tail, icon)) completions.add(SourceCodeCompletionVariant(text, displayText, tail, icon, deprecationLevel))
} }
val errors = ExpectedList<ScriptDiagnostic>(run::doErrorCheck) val errors = ExpectedList<ScriptDiagnostic>(run::doErrorCheck)
@@ -17,6 +17,8 @@ import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.lexer.KtKeywordToken import org.jetbrains.kotlin.lexer.KtKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.ClassId
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.endOffset import org.jetbrains.kotlin.psi.psiUtil.endOffset
@@ -27,16 +29,20 @@ import org.jetbrains.kotlin.renderer.ClassifierNamePolicy
import org.jetbrains.kotlin.renderer.ParameterNameRenderingPolicy import org.jetbrains.kotlin.renderer.ParameterNameRenderingPolicy
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.annotations.argumentValue
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.MemberScope.Companion.ALL_NAME_FILTER import org.jetbrains.kotlin.resolve.scopes.MemberScope.Companion.ALL_NAME_FILTER
import org.jetbrains.kotlin.scripting.ide_services.compiler.completion import org.jetbrains.kotlin.scripting.ide_services.compiler.completion
import org.jetbrains.kotlin.scripting.ide_services.compiler.filterOutShadowedDescriptors import org.jetbrains.kotlin.scripting.ide_services.compiler.filterOutShadowedDescriptors
import org.jetbrains.kotlin.scripting.ide_services.compiler.nameFilter import org.jetbrains.kotlin.scripting.ide_services.compiler.nameFilter
import org.jetbrains.kotlin.scripting.resolve.classId
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.asFlexibleType import org.jetbrains.kotlin.types.asFlexibleType
import org.jetbrains.kotlin.types.isFlexible import org.jetbrains.kotlin.types.isFlexible
import java.io.File import java.io.File
import java.lang.IllegalArgumentException
import java.util.*
import kotlin.script.experimental.api.ScriptCompilationConfiguration import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.SourceCodeCompletionVariant import kotlin.script.experimental.api.SourceCodeCompletionVariant
@@ -252,14 +258,23 @@ private class KJvmReplCompleter(
.let { .let {
if (isSortNeeded) it.sortedBy { descTriple -> descTriple.third } else it if (isSortNeeded) it.sortedBy { descTriple -> descTriple.third } else it
} }
.forEach { .forEach { resultTriple ->
val descriptor = it.first val descriptor = resultTriple.first
val (rawName, presentableText, tailText, completionText) = it.second val (rawName, presentableText, tailText, completionText) = resultTriple.second
if (nameFilter(rawName, prefix)) { if (nameFilter(rawName, prefix)) {
val fullName: String = val fullName: String =
formatName( formatName(
presentableText presentableText
) )
val deprecationLevel = descriptor.annotations
.findAnnotation(FqName("kotlin.Deprecated"))
?.let { annotationDescriptor ->
val valuePair = annotationDescriptor.argumentValue("level")?.value as? Pair<*, *>
val valueClass = (valuePair?.first as? ClassId)?.takeIf { DeprecationLevel::class.classId == it }
val valueName = (valuePair?.second as? Name)?.identifier
if (valueClass == null || valueName == null) return@let DeprecationLevel.WARNING
DeprecationLevel.valueOf(valueName)
}
yield( yield(
SourceCodeCompletionVariant( SourceCodeCompletionVariant(
completionText, completionText,
@@ -267,7 +282,8 @@ private class KJvmReplCompleter(
tailText, tailText,
getIconFromDescriptor( getIconFromDescriptor(
descriptor descriptor
) ),
deprecationLevel,
) )
) )
} }