FIR IDE: implement super qualifier completion

This commit is contained in:
Ilya Kirillov
2021-05-19 16:05:47 +02:00
committed by TeamCityServer
parent 7d351ca6b1
commit 0a6243fc67
39 changed files with 639 additions and 27 deletions
@@ -1,3 +1,4 @@
// FIR_COMPARISON
open class Base
open class A : Base
@@ -1,3 +1,4 @@
// FIR_COMPARISON
open class A
interface I
@@ -1,3 +1,4 @@
// FIR_COMPARISON
open class AA
interface AI
+33
View File
@@ -0,0 +1,33 @@
// FIR_COMPARISON
fun some() {
if (true) {
} else {
}
<caret>
}
// EXIST: do
// EXIST: class
// EXIST: false
// EXIST: for
// EXIST: fun
// EXIST: if
// EXIST: interface
// EXIST: null
// EXIST: object
// EXIST: return
// EXIST: throw
// EXIST: true
// EXIST: try
// EXIST: typealias
// EXIST: val
// EXIST: var
// EXIST: when
// EXIST: while
// NOTHING_ELSE
-1
View File
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FIR_COMPARISON
fun some() {
@@ -0,0 +1,33 @@
// FIR_COMPARISON
fun foo() {
try {
}
catch(e: Exception) {
}
<caret>
}
// EXIST: catch
// EXIST: finally
// EXIST: class
// EXIST: do
// EXIST: false
// EXIST: for
// EXIST: fun
// EXIST: if
// EXIST: null
// EXIST: object
// EXIST: return
// EXIST: throw
// EXIST: interface
// EXIST: true
// EXIST: try
// EXIST: val
// EXIST: var
// EXIST: when
// EXIST: while
// EXIST: as
// EXIST: typealias
// NOTHING_ELSE
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FIR_COMPARISON
fun foo() {
try {
@@ -0,0 +1,30 @@
// FIR_COMPARISON
fun foo() {
try {
}
finally {
}
<caret>
}
// EXIST: class
// EXIST: do
// EXIST: false
// EXIST: for
// EXIST: fun
// EXIST: if
// EXIST: null
// EXIST: object
// EXIST: return
// EXIST: throw
// EXIST: interface
// EXIST: true
// EXIST: try
// EXIST: val
// EXIST: var
// EXIST: when
// EXIST: while
// EXIST: typealias
// NOTHING_ELSE
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FIR_COMPARISON
fun foo() {
try {
+29
View File
@@ -0,0 +1,29 @@
// FIR_COMPARISON
fun foo(p: Int) {
if (p > 0) {
}
<caret>
}
// EXIST: else
// EXIST: class
// EXIST: do
// EXIST: false
// EXIST: for
// EXIST: fun
// EXIST: if
// EXIST: null
// EXIST: object
// EXIST: return
// EXIST: throw
// EXIST: interface
// EXIST: true
// EXIST: try
// EXIST: val
// EXIST: var
// EXIST: when
// EXIST: while
// EXIST: typealias
// EXIST: as
// NOTHING_ELSE
-1
View File
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FIR_COMPARISON
fun foo(p: Int) {
if (p > 0) {
+28
View File
@@ -0,0 +1,28 @@
// FIR_COMPARISON
fun foo(p: Int) {
if (p > 0)
foo()
<caret>
}
// EXIST: else
// EXIST: class
// EXIST: do
// EXIST: false
// EXIST: for
// EXIST: fun
// EXIST: if
// EXIST: null
// EXIST: object
// EXIST: return
// EXIST: throw
// EXIST: interface
// EXIST: true
// EXIST: try
// EXIST: val
// EXIST: var
// EXIST: when
// EXIST: while
// EXIST: typealias
// EXIST: as
// NOTHING_ELSE
-1
View File
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FIR_COMPARISON
fun foo(p: Int) {
if (p > 0)
@@ -0,0 +1,59 @@
// FIR_COMPARISON
// COMPILER_ARGUMENTS: -XXLanguage:+SealedInterfaces -XXLanguage:+MultiPlatformProjects
fun foo() {
bar()
}
fun bar() {
foo()
}
var a : Int
<caret>
// EXIST: abstract
// EXIST: by
// EXIST: class
// EXIST: class GlobalPropertyAccessors
// EXIST: enum class
// EXIST: enum class GlobalPropertyAccessors
// EXIST: final
// EXIST: fun
// EXIST: { itemText: "get", tailText: null }
// EXIST: { itemText: "get", tailText: "() = ..." }
// EXIST: { itemText: "get", tailText: "() {...}" }
// EXIST: internal
// EXIST: object
// EXIST: object GlobalPropertyAccessors
// EXIST: open
// EXIST: private
// EXIST: public
// EXIST: { itemText: "set", tailText: null }
// EXIST: { itemText: "set", tailText: "(value) = ..." }
// EXIST: { itemText: "set", tailText: "(value) {...}" }
// EXIST: interface
// EXIST: interface GlobalPropertyAccessors
// EXIST: val
// EXIST: var
// EXIST: operator
// EXIST: infix
// EXIST: sealed class
// EXIST: sealed class GlobalPropertyAccessors
// EXIST: sealed interface GlobalPropertyAccessors
// EXIST: sealed interface
// EXIST: data class
// EXIST: { "lookupString":"data class", "itemText":"data class", "tailText":" GlobalPropertyAccessors(...)", "attributes":"bold" }
// EXIST: inline
// EXIST: value
// EXIST: tailrec
// EXIST: external
// EXIST: annotation class
// EXIST: annotation class GlobalPropertyAccessors
// EXIST: const val
// EXIST: suspend fun
// EXIST: typealias
// EXIST: expect
// EXIST: actual
// EXIST: lateinit var
// NOTHING_ELSE
@@ -0,0 +1,33 @@
// FIR_COMPARISON
fun foo(p: Int) {
if (p > 0)
try {
}
catch (e: Exception) {
}
<caret>
}
// EXIST: catch
// EXIST: finally
// EXIST: else
// EXIST: class
// EXIST: do
// EXIST: false
// EXIST: for
// EXIST: fun
// EXIST: if
// EXIST: null
// EXIST: object
// EXIST: return
// EXIST: throw
// EXIST: interface
// EXIST: true
// EXIST: try
// EXIST: val
// EXIST: var
// EXIST: when
// EXIST: while
// EXIST: typealias
// EXIST: as
// NOTHING_ELSE
-1
View File
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FIR_COMPARISON
fun foo(p: Int) {
if (p > 0)
@@ -0,0 +1,22 @@
// FIR_COMPARISON
fun foo(p: Int) {
x()
y()
val edge = a.b(<caret>)
z()
}
// EXIST: do
// EXIST: false
// EXIST: for
// EXIST: fun
// EXIST: if
// EXIST: null
// EXIST: object
// EXIST: return
// EXIST: throw
// EXIST: true
// EXIST: try
// EXIST: when
// EXIST: while
// NOTHING_ELSE
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FIR_COMPARISON
fun foo(p: Int) {
x()
@@ -0,0 +1,24 @@
// FIR_COMPARISON
fun foo() {
<caret>
}
// EXIST: class
// EXIST: do
// EXIST: false
// EXIST: for
// EXIST: fun
// EXIST: if
// EXIST: null
// EXIST: object
// EXIST: return
// EXIST: throw
// EXIST: interface
// EXIST: true
// EXIST: try
// EXIST: val
// EXIST: var
// EXIST: when
// EXIST: while
// EXIST: typealias
// NOTHING_ELSE
-1
View File
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FIR_COMPARISON
fun foo() {
<caret>
+32
View File
@@ -0,0 +1,32 @@
// FIR_COMPARISON
fun some() {
if (true) {
} else {
<caret>
}
}
// EXIST: do
// EXIST: class
// EXIST: false
// EXIST: for
// EXIST: fun
// EXIST: if
// EXIST: interface
// EXIST: null
// EXIST: object
// EXIST: return
// EXIST: throw
// EXIST: true
// EXIST: try
// EXIST: typealias
// EXIST: val
// EXIST: var
// EXIST: when
// EXIST: while
// NOTHING_ELSE
-1
View File
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FIR_COMPARISON
fun some() {
@@ -0,0 +1,16 @@
// FIR_COMPARISON
fun foo() = <caret>
// EXIST: do
// EXIST: false
// EXIST: for
// EXIST: fun
// EXIST: if
// EXIST: null
// EXIST: object
// EXIST: throw
// EXIST: true
// EXIST: try
// EXIST: when
// EXIST: while
// NOTHING_ELSE
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FIR_COMPARISON
fun foo() = <caret>
@@ -0,0 +1,17 @@
// FIR_COMPARISON
val prop: Int
get() = <caret>
// EXIST: do
// EXIST: false
// EXIST: for
// EXIST: fun
// EXIST: if
// EXIST: null
// EXIST: object
// EXIST: throw
// EXIST: true
// EXIST: try
// EXIST: when
// EXIST: while
// NOTHING_ELSE
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FIR_COMPARISON
val prop: Int
get() = <caret>
+32
View File
@@ -0,0 +1,32 @@
// FIR_COMPARISON
fun some() {
if (true) {
<caret>
} else {
}
}
// EXIST: do
// EXIST: class
// EXIST: false
// EXIST: for
// EXIST: fun
// EXIST: if
// EXIST: interface
// EXIST: null
// EXIST: object
// EXIST: return
// EXIST: throw
// EXIST: true
// EXIST: try
// EXIST: typealias
// EXIST: val
// EXIST: var
// EXIST: when
// EXIST: while
// NOTHING_ELSE
-1
View File
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FIR_COMPARISON
fun some() {
@@ -0,0 +1,17 @@
// FIR_COMPARISON
fun foo(p: Int = <caret>)
// EXIST: do
// EXIST: false
// EXIST: for
// EXIST: fun
// EXIST: if
// EXIST: null
// EXIST: object
// EXIST: return
// EXIST: throw
// EXIST: true
// EXIST: try
// EXIST: when
// EXIST: while
// NOTHING_ELSE
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FIR_COMPARISON
fun foo(p: Int = <caret>)
@@ -0,0 +1,16 @@
// FIR_COMPARISON
var a : Int = <caret>
// EXIST: do
// EXIST: false
// EXIST: for
// EXIST: fun
// EXIST: if
// EXIST: null
// EXIST: object
// EXIST: throw
// EXIST: true
// EXIST: try
// EXIST: when
// EXIST: while
// NOTHING_ELSE
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FIR_COMPARISON
var a : Int = <caret>
@@ -78,6 +78,7 @@ private object KotlinFirCompletionProvider : CompletionProvider<CompletionParame
complete(callableContributor, positionContext)
complete(classifierContributor, positionContext)
}
is FirTypeNameReferencePositionContext -> {
complete(keywordContributor, positionContext)
complete(packageCompletionContributor, positionContext)
@@ -90,6 +91,10 @@ private object KotlinFirCompletionProvider : CompletionProvider<CompletionParame
complete(annotationsContributor, positionContext)
}
is FirSuperTypeCallNameReferencePositionContext -> {
complete(FirSuperEntryContributor(basicContext), positionContext)
}
is FirUnknownPositionContext -> {
complete(keywordContributor, positionContext)
}
@@ -232,7 +232,7 @@ private object ClassifierInsertionHandler : InsertHandler<LookupElement> {
context.document.replaceString(context.startOffset, context.tailOffset, fqName.render())
context.commitDocument()
shortenReferences(targetFile, TextRange(context.startOffset, context.tailOffset))
shortenReferencesForFirCompletion(targetFile, TextRange(context.startOffset, context.tailOffset))
}
}
}
@@ -338,7 +338,7 @@ private object FunctionInsertionHandler : QuotedNamesAwareInsertionHandler() {
addArguments(context, element, lookupObject)
context.commitDocument()
shortenReferences(targetFile, TextRange(context.startOffset, context.tailOffset))
shortenReferencesForFirCompletion(targetFile, TextRange(context.startOffset, context.tailOffset))
} else {
addArguments(context, element, lookupObject)
context.commitDocument()
@@ -368,7 +368,7 @@ private object VariableInsertionHandler : InsertHandler<LookupElement> {
)
context.commitDocument()
shortenReferences(targetFile, TextRange(context.startOffset, context.tailOffset))
shortenReferencesForFirCompletion(targetFile, TextRange(context.startOffset, context.tailOffset))
}
is CallableImportStrategy.DoNothing -> {}
@@ -435,7 +435,7 @@ private fun CharSequence.indexOfSkippingSpace(c: Char, startIndex: Int): Int? {
return null
}
private fun shortenReferences(targetFile: KtFile, textRange: TextRange) {
internal fun shortenReferencesForFirCompletion(targetFile: KtFile, textRange: TextRange) {
val shortenings = withAllowedResolve {
analyse(targetFile) {
collectPossibleReferenceShortenings(targetFile, textRange)
@@ -39,6 +39,14 @@ internal class FirAnnotationTypeNameReferencePositionContext(
val annotationEntry: KtAnnotationEntry,
) : FirNameReferencePositionContext()
internal class FirSuperTypeCallNameReferencePositionContext(
override val position: PsiElement,
override val reference: KtSimpleNameReference,
override val nameExpression: KtSimpleNameExpression,
override val explicitReceiver: KtExpression?,
val superExpression: KtSuperExpression,
) : FirNameReferencePositionContext()
internal class FirExpressionNameReferencePositionContext(
override val position: PsiElement,
@@ -78,15 +86,23 @@ internal object FirPositionCompletionContextDetector {
nameExpression: KtSimpleNameExpression,
explicitReceiver: KtExpression?
): FirNameReferencePositionContext {
val annotationEntry = userType.annotationEntry()
?: return FirTypeNameReferencePositionContext(position, reference, nameExpression, explicitReceiver)
return FirAnnotationTypeNameReferencePositionContext(position, reference, nameExpression, explicitReceiver, annotationEntry)
}
private fun KtUserType.annotationEntry(): KtAnnotationEntry? {
val typeReference = (parent as? KtTypeReference)?.takeIf { it.typeElement == this }
val constructorCall = (typeReference?.parent as? KtConstructorCalleeExpression)?.takeIf { it.typeReference == typeReference }
return (constructorCall?.parent as? KtAnnotationEntry)?.takeIf { it.calleeExpression == constructorCall }
val typeReference = (userType.parent as? KtTypeReference)?.takeIf { it.typeElement == userType }
return when (val typeReferenceOwner = typeReference?.parent) {
is KtConstructorCalleeExpression -> {
val constructorCall = typeReferenceOwner.takeIf { it.typeReference == typeReference }
val annotationEntry = (constructorCall?.parent as? KtAnnotationEntry)?.takeIf { it.calleeExpression == constructorCall }
annotationEntry?.let {
FirAnnotationTypeNameReferencePositionContext(position, reference, nameExpression, explicitReceiver, it)
}
}
is KtSuperExpression -> {
val superTypeCallEntry = typeReferenceOwner.takeIf { it.superTypeQualifier == typeReference }
superTypeCallEntry?.let {
FirSuperTypeCallNameReferencePositionContext(position, reference, nameExpression, explicitReceiver, it)
}
}
else -> null
} ?: FirTypeNameReferencePositionContext(position, reference, nameExpression, explicitReceiver)
}
inline fun analyseInContext(
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.idea.completion.context.FirRawPositionCompletionCont
import org.jetbrains.kotlin.idea.completion.context.FirUnknownPositionContext
import org.jetbrains.kotlin.idea.completion.contributors.keywords.OverrideKeywordHandler
import org.jetbrains.kotlin.idea.completion.contributors.keywords.ReturnKeywordHandler
import org.jetbrains.kotlin.idea.completion.contributors.keywords.SuperKeywordHandler
import org.jetbrains.kotlin.idea.completion.contributors.keywords.ThisKeywordHandler
import org.jetbrains.kotlin.idea.completion.keywords.CompletionKeywordHandlerProvider
import org.jetbrains.kotlin.idea.completion.keywords.CompletionKeywordHandlers
@@ -76,5 +77,6 @@ private class ResolveDependentCompletionKeywordHandlerProvider(
ReturnKeywordHandler,
OverrideKeywordHandler(basicContext),
ThisKeywordHandler(basicContext),
SuperKeywordHandler,
)
}
@@ -0,0 +1,42 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.completion.contributors
import com.intellij.codeInsight.lookup.LookupElementBuilder
import org.jetbrains.kotlin.idea.completion.context.FirBasicCompletionContext
import org.jetbrains.kotlin.idea.completion.context.FirSuperTypeCallNameReferenceRawPositionContext
import org.jetbrains.kotlin.idea.completion.contributors.helpers.FirSuperEntriesProvider.getSuperClassesAvailableForSuperCall
import org.jetbrains.kotlin.idea.completion.contributors.helpers.SuperCallLookupObject
import org.jetbrains.kotlin.idea.completion.contributors.helpers.SuperCallInsertionHandler
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
internal class FirSuperEntryContributor(
basicContext: FirBasicCompletionContext,
) : FirContextCompletionContributorBase<FirSuperTypeCallNameReferenceRawPositionContext>(basicContext) {
override fun KtAnalysisSession.complete(positionContext: FirSuperTypeCallNameReferenceRawPositionContext) {
getSuperClassesAvailableForSuperCall(positionContext.nameExpression).forEach { superType ->
val tailText = superType.classIdIfNonLocal?.asString()?.let { "($it)" }
LookupElementBuilder.create(SuperLookupObject(superType.name, superType.classIdIfNonLocal), superType.name.asString())
.withTailText(tailText)
.withInsertHandler(SuperCallInsertionHandler)
.let { result.addElement(it) }
}
}
}
private class SuperLookupObject(val className: Name, val classId: ClassId?) : SuperCallLookupObject {
override val replaceTo: String
get() = when {
classId != null -> "${classId.asSingleFqName().asString()}>"
else -> "${className.asString()}>"
}
override val shortenReferencesInReplaced: Boolean
get() = classId != null
}
@@ -0,0 +1,75 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.completion.contributors.helpers
import com.intellij.codeInsight.completion.CodeCompletionHandlerBase
import com.intellij.codeInsight.completion.CompletionType
import com.intellij.codeInsight.completion.InsertHandler
import com.intellij.codeInsight.completion.InsertionContext
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.completion.shortenReferencesForFirCompletion
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.types.KtClassType
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
internal object FirSuperEntriesProvider {
fun KtAnalysisSession.getSuperClassesAvailableForSuperCall(context: PsiElement): List<KtNamedClassOrObjectSymbol> {
val containingClass = context.getStrictParentOfType<KtClassOrObject>() ?: return emptyList()
val containingClassSymbol = containingClass.getClassOrObjectSymbol()
return containingClassSymbol.superTypes.mapNotNull { superType ->
val classType = superType.type as? KtClassType ?: return@mapNotNull null
classType.classSymbol as? KtNamedClassOrObjectSymbol
}
}
}
internal object SuperCallInsertionHandler : InsertHandler<LookupElement> {
override fun handleInsert(context: InsertionContext, item: LookupElement) {
val lookupObject = item.`object` as SuperCallLookupObject
replaceWithClassIdAndShorten(lookupObject, context)
addDot(context)
invokeCompletion(context)
}
private fun replaceWithClassIdAndShorten(
lookupObject: SuperCallLookupObject,
context: InsertionContext
) {
val replaceTo = lookupObject.replaceTo ?: return
context.document.replaceString(context.startOffset, context.tailOffset, replaceTo)
context.commitDocument()
if (lookupObject.shortenReferencesInReplaced) {
val targetFile = context.file as KtFile
shortenReferencesForFirCompletion(targetFile, TextRange(context.startOffset, context.tailOffset))
}
}
private fun invokeCompletion(context: InsertionContext) {
ApplicationManager.getApplication().invokeLater {
CodeCompletionHandlerBase(CompletionType.BASIC, true, false, true)
.invokeCompletion(context.project, context.editor)
}
}
private fun addDot(context: InsertionContext) {
context.document.insertString(context.tailOffset, ".")
context.commitDocument()
context.editor.caretModel.moveToOffset(context.tailOffset)
}
}
internal interface SuperCallLookupObject {
val replaceTo: String?
val shortenReferencesInReplaced: Boolean
}
@@ -0,0 +1,62 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.completion.contributors.keywords
import com.intellij.codeInsight.completion.*
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.completion.KeywordLookupObject
import org.jetbrains.kotlin.idea.completion.contributors.helpers.FirSuperEntriesProvider.getSuperClassesAvailableForSuperCall
import org.jetbrains.kotlin.idea.completion.contributors.helpers.SuperCallLookupObject
import org.jetbrains.kotlin.idea.completion.contributors.helpers.SuperCallInsertionHandler
import org.jetbrains.kotlin.idea.completion.createKeywordElement
import org.jetbrains.kotlin.idea.completion.keywords.CompletionKeywordHandler
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtExpression
internal object SuperKeywordHandler : CompletionKeywordHandler<KtAnalysisSession>(KtTokens.SUPER_KEYWORD) {
@OptIn(ExperimentalStdlibApi::class)
override fun KtAnalysisSession.createLookups(
parameters: CompletionParameters,
expression: KtExpression?,
lookup: LookupElement,
project: Project
): Collection<LookupElement> {
val superClasses = getSuperClassesAvailableForSuperCall(parameters.position)
if (superClasses.isEmpty()) {
return emptyList()
}
if (expression == null) {
// for completion in secondary constructor delegation call
return listOf(lookup)
}
return when {
superClasses.size <= 1 -> listOf(lookup)
else -> buildList {
add(lookup)
superClasses.mapTo(this) { symbol ->
createKeywordElement("super", "<${symbol.name}>", SuperKeywordLookupObject(symbol.name, symbol.classIdIfNonLocal))
.withInsertHandler(SuperCallInsertionHandler)
}
}
}
}
}
private class SuperKeywordLookupObject(val className: Name, val classId: ClassId?) : KeywordLookupObject(), SuperCallLookupObject {
override val replaceTo: String?
get() = classId?.let { "super<${it.asSingleFqName().asString()}>" }
override val shortenReferencesInReplaced: Boolean
get() = classId != null
}