[Analysis API] remove old renderer code
This commit is contained in:
+1
-1
@@ -56,7 +56,7 @@ internal class KtFe10DescConstructorSymbol(
|
||||
|
||||
val callableId = descriptor.callableIdIfNotLocal
|
||||
if (callableId != null) {
|
||||
val signature = descriptor.getSymbolPointerSignature(analysisContext)
|
||||
val signature = descriptor.getSymbolPointerSignature()
|
||||
return KtFe10DescFunctionLikeSymbolPointer(callableId, signature)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ internal class KtFe10DescFunctionSymbol private constructor(
|
||||
|
||||
val callableId = descriptor.callableIdIfNotLocal
|
||||
if (callableId != null) {
|
||||
val signature = descriptor.getSymbolPointerSignature(analysisContext)
|
||||
val signature = descriptor.getSymbolPointerSignature()
|
||||
return KtFe10DescFunctionLikeSymbolPointer(callableId, signature)
|
||||
}
|
||||
|
||||
|
||||
+3
-9
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.analysis.api.*
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.*
|
||||
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
|
||||
import org.jetbrains.kotlin.analysis.api.base.KtContextReceiver
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisContext
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.KtFe10FileSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.KtFe10PackageSymbol
|
||||
@@ -21,14 +20,12 @@ import org.jetbrains.kotlin.analysis.api.descriptors.symbols.psiBased.KtFe10PsiD
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.psiBased.KtFe10PsiDefaultSetterParameterSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.psiBased.base.KtFe10PsiSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.types.*
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.utils.KtFe10Renderer
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.KtContextReceiverImpl
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.*
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolKind
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.unexpectedElementError
|
||||
import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
@@ -43,6 +40,7 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtCallElement
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.CapturedType
|
||||
import org.jetbrains.kotlin.resolve.constants.*
|
||||
@@ -537,13 +535,9 @@ internal fun ClassDescriptor.getSupertypesWithAny(): Collection<KotlinType> {
|
||||
return if (hasClassSupertype) supertypes else listOf(builtIns.anyType) + supertypes
|
||||
}
|
||||
|
||||
internal fun DeclarationDescriptor.render(analysisContext: Fe10AnalysisContext, options: KtDeclarationRendererOptions): String {
|
||||
val renderer = KtFe10Renderer(analysisContext, options)
|
||||
return prettyPrint { renderer.render(this@render, this) }.trim()
|
||||
}
|
||||
|
||||
internal fun CallableMemberDescriptor.getSymbolPointerSignature(analysisContext: Fe10AnalysisContext): String {
|
||||
return render(analysisContext, KtDeclarationRendererOptions.DEFAULT)
|
||||
internal fun CallableMemberDescriptor.getSymbolPointerSignature(): String {
|
||||
return DescriptorRenderer.FQ_NAMES_IN_TYPES.render(this)
|
||||
}
|
||||
|
||||
internal fun createKtInitializerValue(
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ class KtFe10DescFunctionLikeSymbolPointer<T : KtFunctionLikeSymbol>(
|
||||
return memberScope
|
||||
.getContributedDescriptors(DescriptorKindFilter.CALLABLES) { it == callableId.callableName }
|
||||
.filterIsInstance<CallableMemberDescriptor>()
|
||||
.firstOrNull { it.getSymbolPointerSignature(analysisContext) == signature }
|
||||
.firstOrNull { it.getSymbolPointerSignature() == signature }
|
||||
?.toKtCallableSymbol(analysisContext) as? T
|
||||
}
|
||||
}
|
||||
+3
-4
@@ -5,13 +5,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.descriptors.types.base
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeOwner
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotated
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtTypeRendererOptions
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisContext
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.annotations.KtFe10AnnotationsList
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.utils.KtFe10TypeRenderer
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.utils.KtFe10DebugTypeRenderer
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeOwner
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
|
||||
import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint
|
||||
@@ -33,6 +32,6 @@ interface KtFe10Type : KtLifetimeOwner, KtAnnotated {
|
||||
}
|
||||
|
||||
internal fun KotlinType.asStringForDebugging(): String {
|
||||
val renderer = KtFe10TypeRenderer(KtTypeRendererOptions.DEFAULT, isDebugText = true)
|
||||
val renderer = KtFe10DebugTypeRenderer()
|
||||
return prettyPrint { renderer.render(this@asStringForDebugging, this) }
|
||||
}
|
||||
+24
-51
@@ -6,14 +6,12 @@
|
||||
package org.jetbrains.kotlin.analysis.api.descriptors.utils
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.*
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtTypeRendererOptions
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.classId
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.getKtNamedAnnotationArguments
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.maybeLocalClassId
|
||||
import org.jetbrains.kotlin.analysis.utils.printer.PrettyPrinter
|
||||
import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint
|
||||
import org.jetbrains.kotlin.builtins.*
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
|
||||
import org.jetbrains.kotlin.descriptors.PossiblyInnerType
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
@@ -32,7 +30,7 @@ import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor
|
||||
import org.jetbrains.kotlin.types.error.ErrorType
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
|
||||
internal class KtFe10TypeRenderer(private val options: KtTypeRendererOptions, private val isDebugText: Boolean = false) {
|
||||
internal class KtFe10DebugTypeRenderer {
|
||||
private companion object {
|
||||
const val ERROR_TYPE_TEXT = "ERROR_TYPE"
|
||||
}
|
||||
@@ -41,18 +39,8 @@ internal class KtFe10TypeRenderer(private val options: KtTypeRendererOptions, pr
|
||||
consumer.renderType(type)
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderType(type: KotlinType) {
|
||||
if (isDebugText) {
|
||||
renderTypeAnnotationsDebug(type)
|
||||
} else {
|
||||
renderFe10Annotations(
|
||||
type.annotations,
|
||||
isSingleLineAnnotations = true,
|
||||
renderAnnotationWithShortNames = options.shortQualifiedNames
|
||||
) { classId ->
|
||||
classId != StandardClassIds.Annotations.ExtensionFunctionType
|
||||
}
|
||||
}
|
||||
private fun PrettyPrinter.renderType(type: KotlinType) {
|
||||
renderTypeAnnotationsDebug(type)
|
||||
when (val unwrappedType = type.unwrap()) {
|
||||
is DynamicType -> append("dynamic")
|
||||
is FlexibleType -> renderFlexibleType(unwrappedType)
|
||||
@@ -67,9 +55,7 @@ internal class KtFe10TypeRenderer(private val options: KtTypeRendererOptions, pr
|
||||
is IntersectionTypeConstructor -> renderIntersectionType(typeConstructor)
|
||||
else -> {
|
||||
val descriptor = unwrappedType.constructor.declarationDescriptor
|
||||
if (!isDebugText && options.renderFunctionType && descriptor is FunctionClassDescriptor) {
|
||||
renderFunctionType(unwrappedType)
|
||||
} else if (descriptor is TypeParameterDescriptor) {
|
||||
if (descriptor is TypeParameterDescriptor) {
|
||||
renderTypeParameterType(descriptor)
|
||||
} else if (descriptor is ClassifierDescriptorWithTypeParameters) {
|
||||
renderOrdinaryType(unwrappedType)
|
||||
@@ -86,19 +72,19 @@ internal class KtFe10TypeRenderer(private val options: KtTypeRendererOptions, pr
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderTypeAnnotationsDebug(type: KotlinType) {
|
||||
private fun PrettyPrinter.renderTypeAnnotationsDebug(type: KotlinType) {
|
||||
val annotations = type.annotations
|
||||
.filter { it.annotationClass?.classId != StandardClassIds.Annotations.ExtensionFunctionType }
|
||||
|
||||
printCollectionIfNotEmpty(annotations, separator = " ", postfix = " ") { renderTypeAnnotationDebug(it) }
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderTypeAnnotationDebug(annotation: AnnotationDescriptor) {
|
||||
private fun PrettyPrinter.renderTypeAnnotationDebug(annotation: AnnotationDescriptor) {
|
||||
val namedValues = annotation.getKtNamedAnnotationArguments()
|
||||
renderAnnotationDebug(annotation.annotationClass?.classId, namedValues)
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderAnnotationDebug(classId: ClassId?, namedValues: List<KtNamedAnnotationValue>) {
|
||||
private fun PrettyPrinter.renderAnnotationDebug(classId: ClassId?, namedValues: List<KtNamedAnnotationValue>) {
|
||||
append("@")
|
||||
|
||||
if (classId != null) {
|
||||
@@ -116,7 +102,7 @@ internal class KtFe10TypeRenderer(private val options: KtTypeRendererOptions, pr
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderConstantValueDebug(value: KtAnnotationValue) {
|
||||
private fun PrettyPrinter.renderConstantValueDebug(value: KtAnnotationValue) {
|
||||
when (value) {
|
||||
is KtAnnotationApplicationValue -> renderAnnotationDebug(value.annotationValue.classId, value.annotationValue.arguments)
|
||||
is KtArrayAnnotationValue ->
|
||||
@@ -128,46 +114,44 @@ internal class KtFe10TypeRenderer(private val options: KtTypeRendererOptions, pr
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderFlexibleType(type: FlexibleType) {
|
||||
private fun PrettyPrinter.renderFlexibleType(type: FlexibleType) {
|
||||
val lowerBoundText = prettyPrint { renderType(type.lowerBound) }
|
||||
val upperBoundText = prettyPrint { renderType(type.upperBound) }
|
||||
append(DescriptorRenderer.COMPACT.renderFlexibleType(lowerBoundText, upperBoundText, type.builtIns))
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderDefinitelyNotNullType(type: DefinitelyNotNullType) {
|
||||
private fun PrettyPrinter.renderDefinitelyNotNullType(type: DefinitelyNotNullType) {
|
||||
renderType(type.original)
|
||||
append(" & Any")
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderErrorType() {
|
||||
private fun PrettyPrinter.renderErrorType() {
|
||||
append(ERROR_TYPE_TEXT)
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderCapturedType(type: CapturedType) {
|
||||
private fun PrettyPrinter.renderCapturedType(type: CapturedType) {
|
||||
append("CapturedType(")
|
||||
renderTypeProjection(type.typeProjection)
|
||||
append(")")
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderCapturedType(type: NewCapturedType) {
|
||||
private fun PrettyPrinter.renderCapturedType(type: NewCapturedType) {
|
||||
append("CapturedType(")
|
||||
renderTypeProjection(type.constructor.projection)
|
||||
append(")")
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderTypeVariableType(typeConstructor: NewTypeVariableConstructor) {
|
||||
private fun PrettyPrinter.renderTypeVariableType(typeConstructor: NewTypeVariableConstructor) {
|
||||
val name = typeConstructor.originalTypeParameter?.name ?: SpecialNames.NO_NAME_PROVIDED
|
||||
append("TypeVariable(").append(name.asString()).append(")")
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderIntersectionType(typeConstructor: IntersectionTypeConstructor) {
|
||||
if (isDebugText) {
|
||||
append("it")
|
||||
}
|
||||
private fun PrettyPrinter.renderIntersectionType(typeConstructor: IntersectionTypeConstructor) {
|
||||
append("it")
|
||||
printCollection(typeConstructor.supertypes, separator = " & ", prefix = "(", postfix = ")") { renderType(it) }
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderFunctionType(type: SimpleType) {
|
||||
private fun PrettyPrinter.renderFunctionType(type: SimpleType) {
|
||||
if (type.isSuspendFunctionType || type.isKSuspendFunctionType) {
|
||||
append("suspend ")
|
||||
}
|
||||
@@ -193,41 +177,30 @@ internal class KtFe10TypeRenderer(private val options: KtTypeRendererOptions, pr
|
||||
renderType(returnType)
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderTypeParameterType(descriptor: TypeParameterDescriptor) {
|
||||
private fun PrettyPrinter.renderTypeParameterType(descriptor: TypeParameterDescriptor) {
|
||||
append(descriptor.name.render())
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderOrdinaryType(type: SimpleType) {
|
||||
private fun PrettyPrinter.renderOrdinaryType(type: SimpleType) {
|
||||
val nestedType = KtFe10JvmTypeMapperContext.getNestedType(type)
|
||||
renderTypeSegment(nestedType.root, isRoot = true)
|
||||
renderTypeSegment(nestedType.root)
|
||||
printCollectionIfNotEmpty(nestedType.nested, separator = ".", prefix = ".", postfix = "") { renderTypeSegment(it) }
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderTypeSegment(typeSegment: PossiblyInnerType, isRoot: Boolean = false) {
|
||||
private fun PrettyPrinter.renderTypeSegment(typeSegment: PossiblyInnerType) {
|
||||
val classifier = typeSegment.classifierDescriptor
|
||||
|
||||
if (isDebugText) {
|
||||
append(classifier.maybeLocalClassId.asString())
|
||||
} else if (isRoot) {
|
||||
val classId = classifier.maybeLocalClassId
|
||||
if (!options.shortQualifiedNames && !classId.packageFqName.isRoot) {
|
||||
renderFqName(classId.packageFqName)
|
||||
append('.')
|
||||
}
|
||||
renderFqName(classId.relativeClassName)
|
||||
} else {
|
||||
append(classifier.name.render())
|
||||
}
|
||||
append(classifier.maybeLocalClassId.asString())
|
||||
|
||||
val arguments = typeSegment.arguments
|
||||
printCollectionIfNotEmpty(arguments, separator = ", ", prefix = "<", postfix = ">") { renderTypeProjection(it) }
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderFqName(fqName: FqName) {
|
||||
private fun PrettyPrinter.renderFqName(fqName: FqName) {
|
||||
printCollection(fqName.pathSegments(), separator = ".") { append(it.render()) }
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderTypeProjection(projection: TypeProjection) {
|
||||
private fun PrettyPrinter.renderTypeProjection(projection: TypeProjection) {
|
||||
if (projection.isStarProjection) {
|
||||
append("*")
|
||||
} else {
|
||||
-575
@@ -1,575 +0,0 @@
|
||||
/*
|
||||
* 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.analysis.api.descriptors.utils
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions
|
||||
import org.jetbrains.kotlin.analysis.api.components.RendererModifier
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisContext
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.classId
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.isExplicitOverride
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.ktModality
|
||||
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.ktVisibility
|
||||
import org.jetbrains.kotlin.analysis.utils.printer.PrettyPrinter
|
||||
import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.renderer.render
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
|
||||
import org.jetbrains.kotlin.resolve.calls.components.isVararg
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeApproximator
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNullableAny
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
|
||||
|
||||
internal typealias KtFe10RendererConsumer = PrettyPrinter
|
||||
|
||||
internal class KtFe10Renderer(
|
||||
private val analysisContext: Fe10AnalysisContext,
|
||||
private val options: KtDeclarationRendererOptions,
|
||||
isDebugText: Boolean = false
|
||||
) {
|
||||
private companion object {
|
||||
val IGNORED_VISIBILITIES: Set<Visibility> = setOf(
|
||||
Visibilities.Local,
|
||||
Visibilities.PrivateToThis,
|
||||
Visibilities.InvisibleFake,
|
||||
Visibilities.Inherited,
|
||||
Visibilities.Unknown,
|
||||
Visibilities.DEFAULT_VISIBILITY
|
||||
)
|
||||
|
||||
val IGNORED_SUPERTYPES: Set<ClassId> = setOf(
|
||||
StandardClassIds.Enum,
|
||||
StandardClassIds.Annotation
|
||||
)
|
||||
}
|
||||
|
||||
private val typeRenderer = KtFe10TypeRenderer(options.typeRendererOptions, isDebugText)
|
||||
|
||||
private val typeApproximator = TypeApproximator(
|
||||
analysisContext.builtIns,
|
||||
analysisContext.resolveSession.languageVersionSettings
|
||||
)
|
||||
|
||||
fun render(descriptor: DeclarationDescriptor, consumer: KtFe10RendererConsumer) {
|
||||
consumer.renderDeclaration(descriptor)
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderType(type: KotlinType, shouldApproximate: Boolean = false) {
|
||||
if (shouldApproximate) {
|
||||
val approximatedType = typeApproximator.approximateToSuperType(type.unwrap(), PublicApproximatorConfiguration(localTypes = true))
|
||||
?: type.takeIf { it.constructor.declarationDescriptor?.name != SpecialNames.NO_NAME_PROVIDED }
|
||||
?: analysisContext.builtIns.anyType
|
||||
|
||||
renderType(approximatedType, shouldApproximate = false)
|
||||
return
|
||||
}
|
||||
|
||||
typeRenderer.render(type, this)
|
||||
}
|
||||
|
||||
private fun needsParenthesis(type: KotlinType): Boolean {
|
||||
if (!type.annotations.isEmpty()) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (options.typeRendererOptions.renderFunctionType && type.isFunctionType) {
|
||||
return true
|
||||
}
|
||||
|
||||
val descriptor = type.constructor.declarationDescriptor
|
||||
if (descriptor is FunctionClassDescriptor && descriptor.functionKind.isSuspendType) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderDeclaration(descriptor: DeclarationDescriptor) {
|
||||
when (descriptor) {
|
||||
is ClassifierDescriptor -> renderClassifier(descriptor)
|
||||
is CallableDescriptor -> renderCallable(descriptor)
|
||||
else -> error("Unexpected descriptor kind: $descriptor")
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderClassifier(descriptor: ClassifierDescriptor) {
|
||||
when (descriptor) {
|
||||
is TypeAliasDescriptor -> renderTypeAlias(descriptor)
|
||||
is TypeParameterDescriptor -> renderTypeParameter(descriptor)
|
||||
is ClassDescriptor -> {
|
||||
if (descriptor.kind == ClassKind.ENUM_ENTRY) {
|
||||
renderEnumEntry(descriptor)
|
||||
} else {
|
||||
renderClass(descriptor)
|
||||
}
|
||||
}
|
||||
else -> error("Unexpected descriptor kind: $descriptor")
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderTypeAlias(descriptor: TypeAliasDescriptor) {
|
||||
if (options.renderDeclarationHeader) {
|
||||
renderAnnotations(descriptor)
|
||||
renderModifiers(descriptor)
|
||||
append("typealias ")
|
||||
}
|
||||
renderName(descriptor)
|
||||
renderTypeParameters(descriptor.declaredTypeParameters)
|
||||
append(" = ")
|
||||
renderType(descriptor.expandedType)
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderTypeParameters(typeParameters: List<TypeParameterDescriptor>) {
|
||||
if (typeParameters.isNotEmpty()) append('<')
|
||||
printCollection(typeParameters, separator = ", ") { renderTypeParameter(it) }
|
||||
if (typeParameters.isNotEmpty()) append('>')
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderTypeParameter(descriptor: TypeParameterDescriptor) {
|
||||
renderModifier("reified", descriptor.isReified)
|
||||
|
||||
val variance = descriptor.variance.label
|
||||
renderModifier(variance, variance.isNotEmpty())
|
||||
|
||||
renderAnnotations(descriptor)
|
||||
renderName(descriptor)
|
||||
|
||||
val upperBounds = descriptor.upperBounds.filterNot { it.isNullableAny() }
|
||||
if (upperBounds.isNotEmpty()) {
|
||||
append(" : ")
|
||||
renderType(upperBounds.first())
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderClass(descriptor: ClassDescriptor) {
|
||||
if (options.renderDeclarationHeader) {
|
||||
renderAnnotations(descriptor)
|
||||
renderModifiers(descriptor)
|
||||
|
||||
|
||||
if (DescriptorUtils.isAnonymousObject(descriptor)) {
|
||||
append("object")
|
||||
} else {
|
||||
val classKeyword = when (descriptor.kind) {
|
||||
ClassKind.CLASS -> "class"
|
||||
ClassKind.INTERFACE -> "interface"
|
||||
ClassKind.ENUM_CLASS -> "enum class"
|
||||
ClassKind.ENUM_ENTRY -> error("enum entries should not be rendered via renderClass")
|
||||
ClassKind.ANNOTATION_CLASS -> "annotation class"
|
||||
ClassKind.OBJECT -> "object"
|
||||
}
|
||||
append(classKeyword)
|
||||
}
|
||||
}
|
||||
|
||||
val shouldRenderName = !descriptor.name.isSpecial
|
||||
&& (!descriptor.isCompanionObject || descriptor.name != SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT)
|
||||
|
||||
if (shouldRenderName) {
|
||||
append(' ')
|
||||
renderName(descriptor)
|
||||
}
|
||||
|
||||
renderTypeParameters(descriptor.declaredTypeParameters)
|
||||
renderSupertypes(descriptor)
|
||||
|
||||
renderWhereSuffix(descriptor.declaredTypeParameters)
|
||||
|
||||
if (options.renderClassMembers) {
|
||||
val (enumEntries, otherDeclarations) = descriptor.unsubstitutedMemberScope.getContributedDescriptors()
|
||||
.filter { shouldRenderNestedDeclaration(descriptor, it) }
|
||||
.partition { it is ClassDescriptor && it.kind == ClassKind.ENUM_ENTRY }
|
||||
|
||||
val constructors = descriptor.constructors
|
||||
.filter { shouldRenderNestedDeclaration(descriptor, it) }
|
||||
|
||||
if (enumEntries.isNotEmpty() || otherDeclarations.isNotEmpty() || constructors.isNotEmpty()) {
|
||||
append(' ')
|
||||
withIndentInBraces {
|
||||
printCollection(sortDeclarations(enumEntries), separator = ",\n") {
|
||||
renderEnumEntry(it as ClassDescriptor)
|
||||
}
|
||||
|
||||
if (enumEntries.isNotEmpty() && (constructors.isNotEmpty() || otherDeclarations.isNotEmpty())) {
|
||||
appendLine(";\n")
|
||||
}
|
||||
|
||||
printCollection(sortDeclarations(constructors + otherDeclarations), separator = "\n\n") {
|
||||
renderDeclaration(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun shouldRenderNestedDeclaration(owner: ClassDescriptor, declaration: DeclarationDescriptor): Boolean {
|
||||
if (declaration is CallableMemberDescriptor && declaration.kind != CallableMemberDescriptor.Kind.DECLARATION) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (
|
||||
declaration is ConstructorDescriptor && !DescriptorUtils.isAnonymousObject(declaration.constructedClass)
|
||||
&& declaration.isPrimary && declaration.valueParameters.isEmpty() && declaration.annotations.isEmpty()
|
||||
) {
|
||||
if (declaration.visibility == DescriptorVisibilities.DEFAULT_VISIBILITY) {
|
||||
return false
|
||||
} else if (owner.kind == ClassKind.OBJECT || owner.kind == ClassKind.ENUM_CLASS) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if (declaration is FunctionDescriptor && owner.kind == ClassKind.ENUM_CLASS) {
|
||||
if (declaration.name.asString() == "valueOf" && KotlinBuiltIns.isString(declaration.valueParameters.singleOrNull()?.type)) {
|
||||
return false
|
||||
} else if (declaration.name.asString() == "values" && declaration.valueParameters.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun <T : DeclarationDescriptor> sortDeclarations(declarations: List<T>): List<T> {
|
||||
if (!options.sortNestedDeclarations) {
|
||||
return declarations
|
||||
}
|
||||
|
||||
fun getDeclarationKind(declaration: DeclarationDescriptor): Int = when (declaration) {
|
||||
is ConstructorDescriptor -> if (declaration.isPrimary) 1 else 2
|
||||
is PropertyDescriptor -> 3
|
||||
is FunctionDescriptor -> 4
|
||||
else -> 5
|
||||
}
|
||||
|
||||
return declarations.sortedWith(Comparator { left, right ->
|
||||
val kindResult = getDeclarationKind(left) - getDeclarationKind(right)
|
||||
if (kindResult != 0) {
|
||||
return@Comparator kindResult
|
||||
}
|
||||
|
||||
val nameResult = left.name.asString().compareTo(right.name.asString())
|
||||
if (nameResult != 0) {
|
||||
return@Comparator nameResult
|
||||
}
|
||||
|
||||
val leftString = prettyPrint { renderDeclaration(left) }
|
||||
val rightString = prettyPrint { renderDeclaration(right) }
|
||||
return@Comparator leftString.compareTo(rightString)
|
||||
})
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderSupertypes(descriptor: ClassDescriptor) {
|
||||
val allowedSuperClasses = (listOfNotNull(descriptor.getSuperClassNotAny()) + descriptor.getSuperInterfaces())
|
||||
.filterTo(HashSet()) { it.classId !in IGNORED_SUPERTYPES }
|
||||
|
||||
val supertypes = descriptor.typeConstructor.supertypes.filter { it.constructor.declarationDescriptor in allowedSuperClasses }
|
||||
printCollectionIfNotEmpty(supertypes, separator = ", ", prefix = " : ") { renderType(it) }
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderCallable(descriptor: CallableDescriptor) {
|
||||
when (descriptor) {
|
||||
is SyntheticFieldDescriptor -> renderSyntheticFieldDescriptor()
|
||||
is PropertyGetterDescriptor -> renderPropertyAccessor(descriptor)
|
||||
is PropertySetterDescriptor -> renderPropertyAccessor(descriptor)
|
||||
is PropertyDescriptor -> renderProperty(descriptor)
|
||||
is ConstructorDescriptor -> renderConstructor(descriptor)
|
||||
is FunctionDescriptor -> renderFunction(descriptor)
|
||||
is ValueParameterDescriptor -> renderValueParameter(descriptor)
|
||||
is LocalVariableDescriptor -> renderLocalVariable(descriptor)
|
||||
else -> error("Unexpected descriptor kind: $descriptor")
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderSyntheticFieldDescriptor() {
|
||||
append("field")
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderPropertyAccessor(descriptor: PropertyAccessorDescriptor) {
|
||||
if (options.renderDeclarationHeader) {
|
||||
renderAnnotations(descriptor)
|
||||
renderModifiers(descriptor)
|
||||
}
|
||||
|
||||
when (descriptor) {
|
||||
is PropertyGetterDescriptor -> {
|
||||
append("get()")
|
||||
}
|
||||
is PropertySetterDescriptor -> {
|
||||
append("set(")
|
||||
val valueParameter = descriptor.valueParameters.singleOrNull()
|
||||
if (valueParameter != null) {
|
||||
val name = valueParameter.name.takeIf { !it.isSpecial } ?: Name.identifier("value")
|
||||
renderValueParameter(valueParameter, name)
|
||||
}
|
||||
append(")")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderEnumEntry(descriptor: ClassDescriptor) {
|
||||
assert(descriptor.kind == ClassKind.ENUM_ENTRY)
|
||||
renderName(descriptor)
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderLocalVariable(descriptor: LocalVariableDescriptor) {
|
||||
if (options.renderDeclarationHeader) {
|
||||
renderAnnotations(descriptor)
|
||||
append(if (descriptor.isVar) "var" else "val").append(' ')
|
||||
}
|
||||
|
||||
renderName(descriptor)
|
||||
append(": ")
|
||||
renderType(descriptor.type, shouldApproximate = options.approximateTypes)
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderProperty(descriptor: PropertyDescriptor) {
|
||||
if (options.renderDeclarationHeader) {
|
||||
renderAnnotations(descriptor)
|
||||
renderModifiers(descriptor)
|
||||
append(if (descriptor.isVar) "var" else "val").append(' ')
|
||||
renderTypeParameters(descriptor.typeParameters)
|
||||
if (descriptor.typeParameters.isNotEmpty()) {
|
||||
append(' ')
|
||||
}
|
||||
}
|
||||
|
||||
renderReceiver(descriptor)
|
||||
renderName(descriptor)
|
||||
append(": ")
|
||||
renderType(descriptor.type, shouldApproximate = options.approximateTypes)
|
||||
renderWhereSuffix(descriptor.typeParameters)
|
||||
|
||||
if (options.renderClassMembers) {
|
||||
fun shouldRenderAccessor(accessor: PropertyAccessorDescriptor): Boolean {
|
||||
return !accessor.annotations.isEmpty()
|
||||
|| accessor.visibility != descriptor.visibility
|
||||
}
|
||||
|
||||
val getter = descriptor.getter
|
||||
val setter = descriptor.setter
|
||||
|
||||
val shouldRenderAccessors = (getter != null && shouldRenderAccessor(getter)) || (setter != null && shouldRenderAccessor(setter))
|
||||
if (shouldRenderAccessors) {
|
||||
withIndent {
|
||||
if (getter != null) {
|
||||
appendLine()
|
||||
renderPropertyAccessor(getter)
|
||||
}
|
||||
if (setter != null) {
|
||||
appendLine()
|
||||
renderPropertyAccessor(setter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderReceiver(descriptor: CallableDescriptor) {
|
||||
val extensionReceiver = descriptor.extensionReceiverParameter ?: return
|
||||
val needsParentheses = !extensionReceiver.annotations.isEmpty() || needsParenthesis(extensionReceiver.type)
|
||||
if (needsParentheses) {
|
||||
append('(')
|
||||
}
|
||||
renderType(extensionReceiver.type)
|
||||
if (needsParentheses) {
|
||||
append(')')
|
||||
}
|
||||
append('.')
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderConstructor(descriptor: ConstructorDescriptor) {
|
||||
if (options.renderDeclarationHeader) {
|
||||
renderAnnotations(descriptor)
|
||||
}
|
||||
append("constructor")
|
||||
renderValueParameters(descriptor.valueParameters)
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderFunction(descriptor: FunctionDescriptor) {
|
||||
if (options.renderDeclarationHeader) {
|
||||
renderAnnotations(descriptor)
|
||||
renderModifiers(descriptor)
|
||||
append("fun ")
|
||||
renderTypeParameters(descriptor.typeParameters)
|
||||
if (descriptor.typeParameters.isNotEmpty()) {
|
||||
append(" ")
|
||||
}
|
||||
}
|
||||
|
||||
renderReceiver(descriptor)
|
||||
renderName(descriptor)
|
||||
renderValueParameters(descriptor.valueParameters)
|
||||
|
||||
val returnType = descriptor.returnType
|
||||
if (returnType != null && !returnType.isUnit()) {
|
||||
append(": ")
|
||||
renderType(returnType, shouldApproximate = options.approximateTypes)
|
||||
}
|
||||
|
||||
renderWhereSuffix(descriptor.typeParameters)
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderWhereSuffix(descriptors: List<TypeParameterDescriptor>) {
|
||||
val upperBoundStrings = ArrayList<String>(0)
|
||||
|
||||
for (typeParameter in descriptors) {
|
||||
typeParameter.upperBounds
|
||||
.drop(1) // first parameter is rendered by renderTypeParameter
|
||||
.mapTo(upperBoundStrings) { typeParameter.name.render() + " : " + prettyPrint { renderType(it) } }
|
||||
}
|
||||
|
||||
if (upperBoundStrings.isNotEmpty()) {
|
||||
append(" where ")
|
||||
upperBoundStrings.joinTo(this, ", ")
|
||||
append(' ')
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderValueParameters(valueParameters: List<ValueParameterDescriptor>) {
|
||||
printCollection(valueParameters, separator = ", ", prefix = "(", postfix = ")") { renderValueParameter(it) }
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderValueParameter(descriptor: ValueParameterDescriptor, name: Name = descriptor.name) {
|
||||
if (options.renderDeclarationHeader) {
|
||||
renderAnnotations(descriptor)
|
||||
}
|
||||
|
||||
renderModifiers(descriptor)
|
||||
append(name.render())
|
||||
append(": ")
|
||||
renderType(descriptor.varargElementType ?: descriptor.type)
|
||||
|
||||
if (options.renderDefaultParameterValue && descriptor.hasDefaultValue()) {
|
||||
append(" = ...")
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderName(descriptor: DeclarationDescriptor) {
|
||||
append(descriptor.name.render())
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderAnnotations(declaration: Annotated, predicate: (ClassId) -> Boolean = { true }) {
|
||||
if (RendererModifier.ANNOTATIONS !in options.modifiers) {
|
||||
return
|
||||
}
|
||||
val isSingleLineAnnotations = declaration is ValueParameterDescriptor || declaration is TypeParameterDescriptor
|
||||
renderFe10Annotations(
|
||||
declaration.annotations,
|
||||
isSingleLineAnnotations,
|
||||
renderAnnotationWithShortNames = options.typeRendererOptions.shortQualifiedNames,
|
||||
predicate
|
||||
)
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderModifiers(descriptor: DeclarationDescriptor) {
|
||||
if (descriptor is MemberDescriptor) {
|
||||
renderVisibility(descriptor)
|
||||
}
|
||||
|
||||
if (descriptor is PropertyDescriptor) {
|
||||
renderModifier("const", descriptor.isConst, RendererModifier.CONST)
|
||||
renderModifier("lateinit", descriptor.isLateInit, RendererModifier.LATEINIT)
|
||||
}
|
||||
|
||||
if (descriptor is ValueParameterDescriptor) {
|
||||
renderModifier("crossinline", descriptor.isCrossinline)
|
||||
renderModifier("noinline", descriptor.isNoinline)
|
||||
}
|
||||
|
||||
if (descriptor is MemberDescriptor) {
|
||||
renderModifier("external", descriptor.isExternal)
|
||||
renderModifier("expect", descriptor.isExpect, RendererModifier.EXPECT)
|
||||
renderModifier("actual", descriptor.isActual, RendererModifier.ACTUAL)
|
||||
renderModality(descriptor)
|
||||
}
|
||||
|
||||
if (descriptor is CallableMemberDescriptor) {
|
||||
renderModifier("override", descriptor !is DeserializedDescriptor && descriptor.isExplicitOverride, RendererModifier.OVERRIDE)
|
||||
}
|
||||
|
||||
if (descriptor is ValueParameterDescriptor) {
|
||||
renderModifier("vararg", descriptor.isVararg)
|
||||
}
|
||||
|
||||
if (descriptor is FunctionDescriptor) {
|
||||
renderModifier("tailrec", descriptor.isTailrec)
|
||||
renderModifier("suspend", descriptor.isSuspend)
|
||||
renderModifier("inline", descriptor.isInline, RendererModifier.INLINE)
|
||||
renderModifier("infix", descriptor.isInfix)
|
||||
renderModifier("operator", descriptor.isOperator, RendererModifier.OPERATOR)
|
||||
}
|
||||
|
||||
if (descriptor is ClassDescriptor) {
|
||||
renderModifier("inner", descriptor.isInner, RendererModifier.INNER)
|
||||
renderModifier("data", descriptor.isData, RendererModifier.DATA)
|
||||
renderModifier("inline", descriptor.isInline, RendererModifier.INNER)
|
||||
renderModifier("fun", descriptor.isFun, RendererModifier.FUN)
|
||||
renderModifier("companion", descriptor.isCompanionObject)
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderVisibility(descriptor: DeclarationDescriptorWithVisibility) {
|
||||
val visibility = descriptor.ktVisibility
|
||||
renderModifier(visibility.internalDisplayName, visibility !in IGNORED_VISIBILITIES, RendererModifier.VISIBILITY)
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderModality(descriptor: MemberDescriptor) {
|
||||
if (descriptor is PropertyAccessorDescriptor || (descriptor is CallableMemberDescriptor && descriptor.isExplicitOverride)) {
|
||||
return
|
||||
}
|
||||
|
||||
val modality = descriptor.ktModality
|
||||
|
||||
renderModifier(
|
||||
modality.name.toLowerCaseAsciiOnly(),
|
||||
modality != getDefaultModality(descriptor),
|
||||
RendererModifier.MODALITY
|
||||
)
|
||||
}
|
||||
|
||||
private fun getDefaultModality(descriptor: MemberDescriptor): Modality {
|
||||
when (descriptor) {
|
||||
is ClassDescriptor -> return if (descriptor.kind == ClassKind.INTERFACE) Modality.ABSTRACT else Modality.FINAL
|
||||
is CallableMemberDescriptor -> {
|
||||
val containingDeclaration = descriptor.containingDeclaration
|
||||
if (containingDeclaration !is ClassDescriptor) {
|
||||
return Modality.FINAL
|
||||
}
|
||||
if (descriptor.isExplicitOverride && containingDeclaration.ktModality != Modality.FINAL) {
|
||||
return Modality.OPEN
|
||||
} else if (containingDeclaration.kind == ClassKind.INTERFACE && descriptor.visibility != DescriptorVisibilities.PRIVATE) {
|
||||
return if (descriptor.ktModality == Modality.ABSTRACT || descriptor.kind == CallableMemberDescriptor.Kind.DELEGATION)
|
||||
Modality.ABSTRACT
|
||||
else
|
||||
Modality.OPEN
|
||||
}
|
||||
|
||||
return Modality.FINAL
|
||||
}
|
||||
else -> return Modality.FINAL
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtFe10RendererConsumer.renderModifier(text: String, state: Boolean, modifier: RendererModifier? = null) {
|
||||
if (state && (modifier == null || modifier in options.modifiers)) {
|
||||
append(text).append(' ')
|
||||
}
|
||||
}
|
||||
}
|
||||
-375
@@ -1,375 +0,0 @@
|
||||
/*
|
||||
* 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.analysis.api.fir.renderer
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtTypeRendererOptions
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.tryCollectDesignation
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||
import org.jetbrains.kotlin.fir.containingClassForLocal
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeCannotInferParameterType
|
||||
import org.jetbrains.kotlin.fir.renderWithType
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedError
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.LookupTagInternals
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.renderer.render
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.applyIf
|
||||
|
||||
internal class ConeTypeIdeRenderer(
|
||||
private val session: FirSession,
|
||||
private val options: KtTypeRendererOptions,
|
||||
) {
|
||||
companion object {
|
||||
const val ERROR_TYPE_TEXT = "ERROR_TYPE"
|
||||
}
|
||||
|
||||
private fun StringBuilder.appendError(message: String? = null) {
|
||||
append(ERROR_TYPE_TEXT)
|
||||
if (message != null) append(" <$message>")
|
||||
}
|
||||
|
||||
private fun StringBuilder.renderAnnotationList(type: ConeKotlinType) {
|
||||
if (options.renderTypeAnnotations) {
|
||||
renderAnnotations(this@ConeTypeIdeRenderer, type.customAnnotations, session, isSingleLineAnnotations = true)
|
||||
}
|
||||
}
|
||||
|
||||
fun renderType(type: ConeTypeProjection): String = buildString {
|
||||
when (type) {
|
||||
is ConeErrorType -> {
|
||||
renderErrorType(type)
|
||||
}
|
||||
is ConeClassLikeType -> {
|
||||
if (options.renderFunctionType && shouldRenderAsPrettyFunctionType(type)) {
|
||||
renderAnnotationList(type)
|
||||
renderFunctionType(type)
|
||||
} else {
|
||||
renderAnnotationList(type)
|
||||
renderTypeConstructorAndArguments(type)
|
||||
}
|
||||
}
|
||||
is ConeTypeParameterType -> {
|
||||
renderAnnotationList(type)
|
||||
append(type.lookupTag.name.asString())
|
||||
renderNullability(type.type)
|
||||
}
|
||||
is ConeIntersectionType -> {
|
||||
renderAnnotationList(type)
|
||||
type.intersectedTypes.joinTo(this, "&", prefix = "(", postfix = ")") {
|
||||
renderType(it)
|
||||
}
|
||||
renderNullability(type.type)
|
||||
}
|
||||
is ConeDynamicType -> {
|
||||
append("dynamic")
|
||||
}
|
||||
is ConeFlexibleType -> {
|
||||
renderFlexibleType(type)
|
||||
}
|
||||
is ConeCapturedType -> {
|
||||
renderAnnotationList(type)
|
||||
append(type.renderReadableWithFqNames())
|
||||
renderNullability(type.type)
|
||||
}
|
||||
is ConeDefinitelyNotNullType -> {
|
||||
renderAnnotationList(type)
|
||||
append(renderType(type.original))
|
||||
append("!!")
|
||||
}
|
||||
else -> appendError("Unexpected cone type ${type::class.qualifiedName}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun StringBuilder.renderFlexibleType(type: ConeFlexibleType) {
|
||||
renderAnnotationList(type)
|
||||
append(renderFlexibleType(renderType(type.lowerBound), renderType(type.upperBound)))
|
||||
}
|
||||
|
||||
private fun StringBuilder.renderErrorType(type: ConeErrorType) {
|
||||
val diagnostic = type.diagnostic
|
||||
if (options.renderUnresolvedTypeAsResolved) {
|
||||
when (diagnostic) {
|
||||
is ConeUnresolvedError -> {
|
||||
val qualifierRendered = diagnostic.qualifier.let { FqName(it).render() }
|
||||
append(qualifierRendered)
|
||||
}
|
||||
|
||||
is ConeCannotInferParameterType -> {
|
||||
append(diagnostic.typeParameter.name.render())
|
||||
}
|
||||
|
||||
else -> {
|
||||
appendError(diagnostic.reason)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
appendError(diagnostic.reason)
|
||||
}
|
||||
}
|
||||
|
||||
private fun StringBuilder.renderNullability(type: ConeKotlinType) {
|
||||
if (type.nullability == ConeNullability.NULLABLE) {
|
||||
append("?")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun shouldRenderAsPrettyFunctionType(type: ConeKotlinType): Boolean {
|
||||
return type.type.isBuiltinFunctionalType(session) && type.typeArguments.none { it.kind == ProjectionKind.STAR }
|
||||
}
|
||||
|
||||
private fun differsOnlyInNullability(lower: String, upper: String) =
|
||||
lower == upper.replace("?", "") || upper.endsWith("?") && ("$lower?") == upper || "($lower)?" == upper
|
||||
|
||||
|
||||
private fun renderFlexibleType(lowerRendered: String, upperRendered: String): String {
|
||||
if (differsOnlyInNullability(lowerRendered, upperRendered)) {
|
||||
if (upperRendered.startsWith("(")) {
|
||||
// the case of complex type, e.g. (() -> Unit)?
|
||||
return "($lowerRendered)!"
|
||||
}
|
||||
return "$lowerRendered!"
|
||||
}
|
||||
|
||||
val kotlinCollectionsPrefix = "kotlin.collections."
|
||||
val mutablePrefix = "Mutable"
|
||||
// java.util.List<Foo> -> (Mutable)List<Foo!>!
|
||||
val simpleCollection = replacePrefixes(
|
||||
lowerRendered,
|
||||
kotlinCollectionsPrefix + mutablePrefix,
|
||||
upperRendered,
|
||||
kotlinCollectionsPrefix,
|
||||
"$kotlinCollectionsPrefix($mutablePrefix)"
|
||||
)
|
||||
if (simpleCollection != null) return simpleCollection
|
||||
// java.util.Map.Entry<Foo, Bar> -> (Mutable)Map.(Mutable)Entry<Foo!, Bar!>!
|
||||
val mutableEntry = replacePrefixes(
|
||||
lowerRendered,
|
||||
kotlinCollectionsPrefix + "MutableMap.MutableEntry",
|
||||
upperRendered,
|
||||
kotlinCollectionsPrefix + "Map.Entry",
|
||||
"$kotlinCollectionsPrefix(Mutable)Map.(Mutable)Entry"
|
||||
)
|
||||
if (mutableEntry != null) return mutableEntry
|
||||
|
||||
val kotlinPrefix = "kotlin."
|
||||
// Foo[] -> Array<(out) Foo!>!
|
||||
val array = replacePrefixes(
|
||||
lowerRendered,
|
||||
kotlinPrefix + "Array<",
|
||||
upperRendered,
|
||||
kotlinPrefix + "Array<out ",
|
||||
kotlinPrefix + "Array<(out) "
|
||||
)
|
||||
if (array != null) return array
|
||||
|
||||
return "($lowerRendered..$upperRendered)"
|
||||
}
|
||||
|
||||
private fun replacePrefixes(
|
||||
lowerRendered: String,
|
||||
lowerPrefix: String,
|
||||
upperRendered: String,
|
||||
upperPrefix: String,
|
||||
foldedPrefix: String
|
||||
): String? {
|
||||
if (lowerRendered.startsWith(lowerPrefix) && upperRendered.startsWith(upperPrefix)) {
|
||||
val lowerWithoutPrefix = lowerRendered.substring(lowerPrefix.length)
|
||||
val upperWithoutPrefix = upperRendered.substring(upperPrefix.length)
|
||||
val flexibleCollectionName = foldedPrefix + lowerWithoutPrefix
|
||||
|
||||
if (lowerWithoutPrefix == upperWithoutPrefix) return flexibleCollectionName
|
||||
|
||||
if (differsOnlyInNullability(lowerWithoutPrefix, upperWithoutPrefix)) {
|
||||
return "$flexibleCollectionName!"
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun FirRegularClass.collectForLocal(): List<FirClassLikeDeclaration> {
|
||||
require(isLocal)
|
||||
var containingClassLookUp = containingClassForLocal()
|
||||
val designation = mutableListOf<FirClassLikeDeclaration>(this)
|
||||
@OptIn(LookupTagInternals::class)
|
||||
while (containingClassLookUp != null && containingClassLookUp.classId.isLocal) {
|
||||
val currentClass = containingClassLookUp.toFirRegularClass(moduleData.session) ?: break
|
||||
designation.add(currentClass)
|
||||
containingClassLookUp = currentClass.containingClassForLocal()
|
||||
}
|
||||
return designation
|
||||
}
|
||||
|
||||
private fun collectDesignationPathForLocal(declaration: FirDeclaration): List<FirDeclaration>? {
|
||||
@OptIn(LookupTagInternals::class)
|
||||
val containingClass = when (declaration) {
|
||||
is FirCallableDeclaration -> declaration.containingClassLookupTag()?.toFirRegularClass(declaration.moduleData.session)
|
||||
is FirAnonymousObject -> return listOf(declaration)
|
||||
is FirClassLikeDeclaration -> declaration.let {
|
||||
if (!declaration.isLocal) return null
|
||||
(it as? FirRegularClass)?.containingClassForLocal()?.toFirRegularClass(declaration.moduleData.session)
|
||||
}
|
||||
else -> error("Invalid declaration ${declaration.renderWithType()}")
|
||||
} ?: return listOf(declaration)
|
||||
|
||||
return if (containingClass.isLocal) {
|
||||
containingClass.collectForLocal().reversed()
|
||||
} else null
|
||||
}
|
||||
|
||||
private fun StringBuilder.renderTypeConstructorAndArguments(type: ConeClassLikeType) {
|
||||
fun renderTypeArguments(typeArguments: Array<out ConeTypeProjection>, range: IntRange) {
|
||||
if (range.any()) {
|
||||
typeArguments.slice(range).joinTo(this, ", ", prefix = "<", postfix = ">") {
|
||||
renderTypeProjection(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val classSymbolToRender = type.lookupTag.toSymbol(session)
|
||||
// To be able to render unresolved types like java.io.Serializable
|
||||
val classId = classSymbolToRender?.classId ?: type.lookupTag.classId
|
||||
|
||||
if (!options.shortQualifiedNames && !classId.isLocal) {
|
||||
val packageName = classId.packageFqName.asString()
|
||||
if (packageName.isNotEmpty()) {
|
||||
append(packageName).append(".")
|
||||
}
|
||||
}
|
||||
|
||||
if (classSymbolToRender !is FirRegularClassSymbol) {
|
||||
append(classId.shortClassName)
|
||||
if (type.typeArguments.any()) {
|
||||
type.typeArguments.joinTo(this, ", ", prefix = "<", postfix = ">") {
|
||||
renderTypeProjection(it)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
val designation = classSymbolToRender.fir.let {
|
||||
val nonLocalDesignation = it.tryCollectDesignation()
|
||||
nonLocalDesignation?.toSequence(includeTarget = true)?.toList()
|
||||
?: collectDesignationPathForLocal(it)
|
||||
?: emptyList()
|
||||
}
|
||||
|
||||
var typeParametersLeft = type.typeArguments.count()
|
||||
fun needToRenderTypeParameters(index: Int): Boolean {
|
||||
if (typeParametersLeft <= 0) return false
|
||||
return index == designation.lastIndex ||
|
||||
(designation[index] as? FirRegularClass)?.isInner == true ||
|
||||
(designation[index + 1] as? FirRegularClass)?.isInner == true
|
||||
}
|
||||
|
||||
val classParentFqName = classId.relativeClassName.parent()
|
||||
if (!classParentFqName.isRoot && designation.size == 1) {
|
||||
// This code is added for a case we can't build designation (e.g. nested Java class),
|
||||
// but still wish to render full class name
|
||||
append(classParentFqName)
|
||||
append(".")
|
||||
}
|
||||
|
||||
designation.filterIsInstance<FirRegularClass>().forEachIndexed { index, currentClass ->
|
||||
if (index != 0) append(".")
|
||||
append(currentClass.name)
|
||||
|
||||
if (needToRenderTypeParameters(index)) {
|
||||
val typeParametersCount = currentClass.typeParameters.count { it is FirTypeParameter }
|
||||
val begin = typeParametersLeft - typeParametersCount
|
||||
val end = typeParametersLeft
|
||||
check(begin >= 0)
|
||||
typeParametersLeft -= typeParametersCount
|
||||
renderTypeArguments(type.typeArguments, begin until end)
|
||||
}
|
||||
}
|
||||
|
||||
renderNullability(type)
|
||||
}
|
||||
|
||||
private fun renderTypeProjection(typeProjection: ConeTypeProjection): String {
|
||||
val type = typeProjection.type?.let(::renderType) ?: "???"
|
||||
return when (typeProjection.kind) {
|
||||
ProjectionKind.STAR -> "*"
|
||||
ProjectionKind.IN -> "in $type"
|
||||
ProjectionKind.OUT -> "out $type"
|
||||
ProjectionKind.INVARIANT -> type
|
||||
}
|
||||
}
|
||||
|
||||
private fun StringBuilder.renderFunctionType(type: ConeClassLikeType) {
|
||||
val lengthBefore = length
|
||||
val hasAnnotations = length != lengthBefore
|
||||
|
||||
val isSuspend = type.isSuspendFunctionType(session)
|
||||
val isNullable = type.isMarkedNullable
|
||||
|
||||
val receiverType = type.receiverType(session)
|
||||
|
||||
val needParenthesis = isNullable || (hasAnnotations && receiverType != null)
|
||||
if (needParenthesis) {
|
||||
if (isSuspend) {
|
||||
insert(lengthBefore, '(')
|
||||
} else {
|
||||
if (hasAnnotations) {
|
||||
check(last() == ' ')
|
||||
if (get(lastIndex - 1) != ')') {
|
||||
// last annotation rendered without parenthesis - need to add them otherwise parsing will be incorrect
|
||||
insert(lastIndex, "()")
|
||||
}
|
||||
}
|
||||
|
||||
append("(")
|
||||
}
|
||||
}
|
||||
|
||||
if (isSuspend) {
|
||||
append("suspend")
|
||||
append(" ")
|
||||
}
|
||||
|
||||
if (receiverType != null) {
|
||||
val surroundReceiver = shouldRenderAsPrettyFunctionType(receiverType) &&
|
||||
!receiverType.isMarkedNullable ||
|
||||
receiverType.isSuspendFunctionType(session)
|
||||
if (surroundReceiver) {
|
||||
append("(")
|
||||
}
|
||||
append(renderType(receiverType))
|
||||
if (surroundReceiver) {
|
||||
append(")")
|
||||
}
|
||||
append(".")
|
||||
}
|
||||
|
||||
append("(")
|
||||
|
||||
val notNullParametersType = type
|
||||
.valueParameterTypesIncludingReceiver(session)
|
||||
.applyIf(receiverType != null) { drop(1) }
|
||||
|
||||
notNullParametersType.forEachIndexed { index, typeProjection ->
|
||||
if (index != 0) append(", ")
|
||||
append(renderTypeProjection(typeProjection))
|
||||
}
|
||||
|
||||
append(") -> ")
|
||||
|
||||
val returnType = type.returnType(session)
|
||||
append(renderType(returnType))
|
||||
|
||||
if (needParenthesis) append(")")
|
||||
|
||||
renderNullability(type)
|
||||
}
|
||||
}
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* 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.analysis.api.fir.renderer
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.annotations.mapAnnotationParameters
|
||||
import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirCompileTimeConstantEvaluator
|
||||
import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirAnnotationValueConverter
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtUnsupportedAnnotationValue
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.renderAsSourceCode
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtConstantEvaluationMode
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import kotlin.text.Appendable
|
||||
|
||||
internal fun Appendable.renderAnnotations(
|
||||
coneTypeIdeRenderer: ConeTypeIdeRenderer,
|
||||
annotations: List<FirAnnotation>,
|
||||
session: FirSession,
|
||||
isSingleLineAnnotations: Boolean,
|
||||
) {
|
||||
val separator = if (isSingleLineAnnotations) " " else "\n"
|
||||
for (annotation in annotations) {
|
||||
if (!annotation.isParameterName()) {
|
||||
append(renderAnnotation(annotation, coneTypeIdeRenderer, session))
|
||||
append(separator)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun FirAnnotation.isParameterName(): Boolean {
|
||||
return toAnnotationClassId()?.asSingleFqName() == StandardNames.FqNames.parameterName
|
||||
}
|
||||
|
||||
private fun renderAnnotation(annotation: FirAnnotation, coneTypeIdeRenderer: ConeTypeIdeRenderer, session: FirSession): String {
|
||||
return buildString {
|
||||
append('@')
|
||||
val resolvedTypeRef = annotation.typeRef as? FirResolvedTypeRef
|
||||
check(resolvedTypeRef != null)
|
||||
append(coneTypeIdeRenderer.renderType(resolvedTypeRef.type))
|
||||
|
||||
val arguments = renderAndSortAnnotationArguments(annotation, session)
|
||||
if (arguments.isNotEmpty()) {
|
||||
arguments.joinTo(this, ", ", "(", ")")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderAndSortAnnotationArguments(descriptor: FirAnnotation, session: FirSession): List<String> {
|
||||
val argumentList = mapAnnotationParameters(descriptor, session).entries.map { (name, value) ->
|
||||
"$name = ${renderConstant(value, session)}"
|
||||
}
|
||||
return argumentList.sorted()
|
||||
}
|
||||
|
||||
private fun renderConstant(value: FirExpression, useSiteSession: FirSession): String {
|
||||
val evaluated = FirCompileTimeConstantEvaluator.evaluate(value, KtConstantEvaluationMode.CONSTANT_EXPRESSION_EVALUATION)
|
||||
val constantValue = FirAnnotationValueConverter.toConstantValue(evaluated ?: value, useSiteSession)
|
||||
?: KtUnsupportedAnnotationValue
|
||||
|
||||
return constantValue.renderAsSourceCode()
|
||||
}
|
||||
-371
@@ -1,371 +0,0 @@
|
||||
/*
|
||||
* 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.analysis.api.fir.renderer
|
||||
|
||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions
|
||||
import org.jetbrains.kotlin.analysis.utils.printer.PrettyPrinter
|
||||
import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.PsiSourceNavigator.getRawName
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.hasBody
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||
import org.jetbrains.kotlin.fir.extensions.generatedMembers
|
||||
import org.jetbrains.kotlin.fir.extensions.generatedNestedClassifiers
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.renderer.render
|
||||
|
||||
internal class FirIdeRenderer private constructor(
|
||||
options: KtDeclarationRendererOptions,
|
||||
session: FirSession,
|
||||
) : FirIdeRendererBase(options, session) {
|
||||
fun PrettyPrinter.renderMemberDeclaration(declaration: FirDeclaration) {
|
||||
when (declaration) {
|
||||
is FirAnonymousObject -> renderAnonymousObject(declaration)
|
||||
is FirRegularClass -> renderRegularClass(declaration)
|
||||
is FirTypeAlias -> renderTypeAlias(declaration)
|
||||
is FirConstructor -> renderConstructor(declaration)
|
||||
is FirPropertyAccessor -> renderPropertyAccessor(declaration)
|
||||
is FirSimpleFunction -> renderSimpleFunction(declaration)
|
||||
is FirBackingField -> renderBackingField()
|
||||
is FirEnumEntry -> renderEnumEntry(declaration)
|
||||
is FirProperty -> renderPropertyOrField(declaration)
|
||||
is FirValueParameter -> renderValueParameter(declaration)
|
||||
is FirField -> renderPropertyOrField(declaration)
|
||||
is FirErrorFunction -> error("FirErrorFunction should not be rendered")
|
||||
is FirErrorProperty -> error("FirErrorProperty should not be rendered")
|
||||
is FirAnonymousInitializer -> error("FirAnonymousInitializer should not be rendered")
|
||||
is FirFile -> error("FirFile should not be rendered")
|
||||
is FirTypeParameter -> renderTypeParameter(declaration)
|
||||
is FirAnonymousFunction -> TODO()
|
||||
}
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderBackingField() {
|
||||
append("field")
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderPropertyOrField(variable: FirVariable) {
|
||||
check(variable is FirProperty || variable is FirField) {
|
||||
"Required either FirProperty or FirField but was ${variable::class.simpleName}"
|
||||
}
|
||||
renderAnnotationsAndModifiers(variable)
|
||||
renderValVarPrefix(variable)
|
||||
renderTypeParameters(variable)
|
||||
renderReceiver(variable)
|
||||
renderName(variable)
|
||||
append(": ")
|
||||
renderType(variable.returnTypeRef, approximate = options.approximateTypes)
|
||||
|
||||
renderWhereSuffix(variable)
|
||||
|
||||
fun FirPropertyAccessor?.needToRender() = this != null && (annotations.isNotEmpty() || visibility != variable.visibility)
|
||||
val needToRenderAccessors = options.renderClassMembers &&
|
||||
(variable.getter.needToRender() || (variable.isVar && variable.setter.needToRender()))
|
||||
|
||||
if (needToRenderAccessors) {
|
||||
withIndent {
|
||||
variable.getter?.let { getter ->
|
||||
if (getter.needToRender()) {
|
||||
appendLine()
|
||||
renderPropertyAccessor(getter)
|
||||
}
|
||||
}
|
||||
variable.setter?.let { setter ->
|
||||
if (setter.needToRender()) {
|
||||
appendLine()
|
||||
renderPropertyAccessor(setter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderPropertyAccessor(propertyAccessor: FirPropertyAccessor) {
|
||||
renderAnnotationsAndModifiers(propertyAccessor)
|
||||
append(if (propertyAccessor.isGetter) "get" else "set")
|
||||
if (propertyAccessor.isSetter) {
|
||||
append("(")
|
||||
val valueParameter = propertyAccessor.valueParameters.first()
|
||||
renderAnnotations(valueParameter)
|
||||
append("value: ")
|
||||
renderType(valueParameter.returnTypeRef)
|
||||
append(")")
|
||||
} else {
|
||||
append("()")
|
||||
}
|
||||
renderFunctionBody(propertyAccessor)
|
||||
}
|
||||
|
||||
@Suppress("unused", "UNUSED_PARAMETER")
|
||||
private fun PrettyPrinter.renderFunctionBody(function: FirFunction) {
|
||||
// TODO implement with some settings
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderSimpleFunction(simpleFunction: FirSimpleFunction) {
|
||||
renderAnnotationsAndModifiers(simpleFunction)
|
||||
append("fun ")
|
||||
renderTypeParameters(simpleFunction)
|
||||
renderReceiver(simpleFunction)
|
||||
renderName(simpleFunction)
|
||||
renderValueParameters(simpleFunction)
|
||||
|
||||
val returnType = simpleFunction.returnTypeRef
|
||||
if (options.renderUnitReturnType || !returnType.isUnit) {
|
||||
append(": ")
|
||||
renderType(returnType, approximate = options.approximateTypes)
|
||||
append(' ')
|
||||
}
|
||||
|
||||
renderWhereSuffix(simpleFunction)
|
||||
renderFunctionBody(simpleFunction)
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderAnonymousObject(anonymousObject: FirAnonymousObject) {
|
||||
renderAnnotationsAndModifiers(anonymousObject)
|
||||
append("object ")
|
||||
renderSuperTypes(anonymousObject)
|
||||
renderClassBody(anonymousObject)
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderClassBody(firClass: FirClass) {
|
||||
if (!options.renderClassMembers) return
|
||||
if (firClass.declarations.isEmpty()) return
|
||||
|
||||
val allDeclarations = buildList {
|
||||
firClass.declarations.filterNotTo(this) { member ->
|
||||
member.isDefaultPrimaryConstructor()
|
||||
|| member.isDefaultEnumEntryMember(firClass)
|
||||
|| member is FirConstructor && firClass.classKind == ClassKind.OBJECT
|
||||
}
|
||||
addAll(firClass.generatedNestedClassifiers(useSiteSession))
|
||||
addAll(firClass.generatedMembers(useSiteSession))
|
||||
}.filterIsInstance<FirMemberDeclaration>()
|
||||
if (allDeclarations.isEmpty()) return
|
||||
|
||||
val (enumEntries, nonEnumEntries) = allDeclarations.partition { it is FirEnumEntry }
|
||||
withIndentInBraces {
|
||||
printCollection(sortDeclarations(enumEntries), separator = ",\n") { declaration ->
|
||||
renderMemberDeclaration(declaration)
|
||||
}
|
||||
|
||||
if (enumEntries.isNotEmpty() && nonEnumEntries.isNotEmpty()) {
|
||||
appendLine(";\n")
|
||||
}
|
||||
|
||||
printCollection(sortDeclarations(nonEnumEntries), separator = "\n\n") { declaration ->
|
||||
renderMemberDeclaration(declaration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderConstructor(constructor: FirConstructor) {
|
||||
renderAnnotationsAndModifiers(constructor)
|
||||
append("constructor")
|
||||
renderValueParameters(constructor)
|
||||
renderFunctionBody(constructor)
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderRegularClass(regularClass: FirRegularClass) {
|
||||
renderAnnotationsAndModifiers(regularClass)
|
||||
renderClassifierKind(regularClass)
|
||||
renderClassName(regularClass)
|
||||
renderTypeParameters(regularClass)
|
||||
printCharIfNotThere(' ')
|
||||
renderSuperTypes(regularClass)
|
||||
renderWhereSuffix(regularClass)
|
||||
renderClassBody(regularClass)
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderClassName(regularClass: FirRegularClass) {
|
||||
if (!regularClass.isCompanion) {
|
||||
renderName(regularClass)
|
||||
} else {
|
||||
if (regularClass.name != SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT) {
|
||||
append(regularClass.name.render())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderTypeAlias(typeAlias: FirTypeAlias) {
|
||||
renderAnnotationsAndModifiers(typeAlias)
|
||||
append("typealias ")
|
||||
renderName(typeAlias)
|
||||
renderTypeParameters(typeAlias)
|
||||
printCharIfNotThere(' ')
|
||||
append("= ")
|
||||
renderType(typeAlias.expandedTypeRef)
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderEnumEntry(enumEntry: FirEnumEntry) {
|
||||
renderName(enumEntry)
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderTypeParameter(typeParameter: FirTypeParameter) {
|
||||
renderIf(typeParameter.isReified, "reified")
|
||||
val variance = typeParameter.variance.label
|
||||
renderIf(variance.isNotEmpty(), variance)
|
||||
renderAnnotations(typeParameter)
|
||||
renderName(typeParameter)
|
||||
|
||||
val upperBoundsCount = typeParameter.bounds.size
|
||||
if (upperBoundsCount >= 1) {
|
||||
val upperBound = typeParameter.bounds.first()
|
||||
if (!upperBound.isNullableAny) {
|
||||
append(" : ")
|
||||
renderType(upperBound)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderTypeParameters(declaration: FirMemberDeclaration) {
|
||||
val typeParameters = declaration.typeParameters.filterIsInstance<FirTypeParameter>()
|
||||
if (typeParameters.isNotEmpty()) {
|
||||
append("<")
|
||||
printCollection(typeParameters) {
|
||||
renderTypeParameter(it)
|
||||
}
|
||||
append("> ")
|
||||
}
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderReceiver(firCallableDeclaration: FirCallableDeclaration) {
|
||||
val receiverType = firCallableDeclaration.receiverTypeRef
|
||||
if (receiverType != null) {
|
||||
if (options.renderDeclarationHeader) {
|
||||
renderAnnotations(firCallableDeclaration)
|
||||
}
|
||||
|
||||
val needBrackets =
|
||||
typeIdeRenderer.shouldRenderAsPrettyFunctionType(receiverType.coneType) && receiverType.isMarkedNullable == true
|
||||
|
||||
if (needBrackets) append('(')
|
||||
renderType(receiverType)
|
||||
if (needBrackets) append(')')
|
||||
append(".")
|
||||
}
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderWhereSuffix(declaration: FirTypeParameterRefsOwner) {
|
||||
val upperBoundStrings = ArrayList<String>(0)
|
||||
|
||||
for (typeParameter in declaration.typeParameters) {
|
||||
if (typeParameter !is FirTypeParameter) continue
|
||||
typeParameter.symbol.resolvedBounds
|
||||
.drop(1) // first parameter is rendered by renderTypeParameter
|
||||
.mapTo(upperBoundStrings) { typeParameter.name.render() + " : " + renderTypeToString(it.coneType) }
|
||||
}
|
||||
|
||||
if (upperBoundStrings.isNotEmpty()) {
|
||||
append("where ")
|
||||
upperBoundStrings.joinTo(this, ", ")
|
||||
append(' ')
|
||||
}
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderValueParameters(function: FirFunction) {
|
||||
printCollection(function.valueParameters, prefix = "(", postfix = ")") {
|
||||
renderValueParameter(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderValueParameter(valueParameter: FirValueParameter) {
|
||||
if (options.renderDeclarationHeader) {
|
||||
renderAnnotations(valueParameter)
|
||||
}
|
||||
renderIf(valueParameter.isCrossinline, "crossinline")
|
||||
renderIf(valueParameter.isNoinline, "noinline")
|
||||
renderVariable(valueParameter)
|
||||
|
||||
if (options.renderDefaultParameterValue) {
|
||||
val withDefaultValue = valueParameter.defaultValue != null //TODO check if default value is inherited
|
||||
if (withDefaultValue) {
|
||||
append(" = ...")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderValVarPrefix(variable: FirVariable, isInPrimaryConstructor: Boolean = false) {
|
||||
if (!isInPrimaryConstructor || variable !is FirValueParameter) {
|
||||
append(if (variable.isVar) "var" else "val")
|
||||
append(' ')
|
||||
}
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderVariable(variable: FirVariable) {
|
||||
val typeToRender = variable.returnTypeRef.coneType
|
||||
val isVarArg = (variable as? FirValueParameter)?.isVararg ?: false
|
||||
renderIf(isVarArg, "vararg")
|
||||
renderName(variable)
|
||||
append(": ")
|
||||
if (isVarArg) {
|
||||
renderType(typeToRender.arrayElementType() ?: typeToRender)
|
||||
} else {
|
||||
renderType(typeToRender)
|
||||
}
|
||||
}
|
||||
|
||||
fun sortDeclarations(declarations: List<FirMemberDeclaration>): List<FirMemberDeclaration> {
|
||||
if (!options.sortNestedDeclarations) return declarations
|
||||
|
||||
fun getDeclarationKind(declaration: FirDeclaration): Int = when (declaration) {
|
||||
is FirEnumEntry -> 0
|
||||
is FirConstructor -> if (declaration.isPrimary) 1 else 2
|
||||
is FirProperty -> 3
|
||||
is FirFunction -> 4
|
||||
else -> 5
|
||||
}
|
||||
|
||||
return declarations.sortedWith(Comparator { left, right ->
|
||||
val kindResult = getDeclarationKind(left) - getDeclarationKind(right)
|
||||
if (kindResult != 0) {
|
||||
return@Comparator kindResult
|
||||
}
|
||||
|
||||
val nameResult = (left.getRawName() ?: "").compareTo(right.getRawName() ?: "")
|
||||
if (nameResult != 0) {
|
||||
return@Comparator nameResult
|
||||
}
|
||||
|
||||
val leftString = prettyPrint { renderMemberDeclaration(left) }
|
||||
val rightString = prettyPrint { renderMemberDeclaration(right) }
|
||||
return@Comparator leftString.compareTo(rightString)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
fun render(
|
||||
firDeclaration: FirDeclaration,
|
||||
options: KtDeclarationRendererOptions,
|
||||
session: FirSession
|
||||
): String {
|
||||
val renderer = FirIdeRenderer(options, session)
|
||||
return prettyPrint {
|
||||
with(renderer) { renderMemberDeclaration(firDeclaration) }
|
||||
}.trim { it.isWhitespace() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirDeclaration.isDefaultEnumEntryMember(firClass: FirClass): Boolean {
|
||||
if (firClass.classKind != ClassKind.ENUM_CLASS) return false
|
||||
if (this is FirConstructor) return isPrimary && valueParameters.isEmpty()
|
||||
return source?.kind == KtFakeSourceElementKind.EnumGeneratedDeclaration
|
||||
}
|
||||
|
||||
private fun FirDeclaration.isDefaultPrimaryConstructor() =
|
||||
this is FirConstructor &&
|
||||
isPrimary &&
|
||||
valueParameters.isEmpty() &&
|
||||
!hasBody &&
|
||||
visibility == Visibilities.DEFAULT_VISIBILITY
|
||||
-179
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
* 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.analysis.api.fir.renderer
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions
|
||||
import org.jetbrains.kotlin.analysis.api.components.RendererModifier
|
||||
import org.jetbrains.kotlin.analysis.api.fir.types.PublicTypeApproximator
|
||||
import org.jetbrains.kotlin.analysis.utils.printer.PrettyPrinter
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.classKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
|
||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.renderer.render
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.applyIf
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
|
||||
|
||||
internal abstract class FirIdeRendererBase(
|
||||
protected val options: KtDeclarationRendererOptions,
|
||||
protected val useSiteSession: FirSession,
|
||||
) {
|
||||
protected val typeIdeRenderer: ConeTypeIdeRenderer = ConeTypeIdeRenderer(useSiteSession, options.typeRendererOptions)
|
||||
|
||||
protected fun PrettyPrinter.renderAnnotations(declaration: FirDeclaration) {
|
||||
if (RendererModifier.ANNOTATIONS in options.modifiers) {
|
||||
val isSingleLineAnnotations = declaration is FirValueParameter || declaration is FirTypeParameter
|
||||
renderAnnotations(typeIdeRenderer, declaration.annotations, useSiteSession, isSingleLineAnnotations)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun renderTypeToString(type: ConeTypeProjection): String {
|
||||
return typeIdeRenderer.renderType(type)
|
||||
}
|
||||
|
||||
protected fun PrettyPrinter.renderType(type: ConeTypeProjection) {
|
||||
append(renderTypeToString(type))
|
||||
}
|
||||
|
||||
protected fun PrettyPrinter.renderType(firRef: FirTypeRef, approximate: Boolean = false) {
|
||||
val coneType = firRef.coneType
|
||||
val approximatedIfNeeded = approximate.ifTrue {
|
||||
PublicTypeApproximator.approximateTypeToPublicDenotable(coneType, useSiteSession, approximateLocalTypes = true)
|
||||
} ?: coneType
|
||||
renderType(approximatedIfNeeded)
|
||||
}
|
||||
|
||||
protected fun PrettyPrinter.renderName(declaration: FirDeclaration) {
|
||||
if (declaration is FirAnonymousObject) {
|
||||
append("<no name provided>")
|
||||
return
|
||||
}
|
||||
val name = when (declaration) {
|
||||
is FirRegularClass -> declaration.name
|
||||
is FirSimpleFunction -> declaration.name
|
||||
is FirProperty -> declaration.name
|
||||
is FirValueParameter -> declaration.name
|
||||
is FirTypeParameter -> declaration.name
|
||||
is FirTypeAlias -> declaration.name
|
||||
is FirEnumEntry -> declaration.name
|
||||
is FirField -> declaration.name
|
||||
else -> TODO("Unexpected declaration ${declaration::class.qualifiedName}")
|
||||
}
|
||||
append(name.render())
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderVisibility(declaration: FirMemberDeclaration) {
|
||||
if (declaration is FirConstructor && declaration.containingClassLookupTag()?.toFirRegularClassSymbol(useSiteSession)?.isEnumClass == true) {
|
||||
return
|
||||
}
|
||||
val visibility = declaration.visibility
|
||||
if (RendererModifier.VISIBILITY !in options.modifiers) return
|
||||
|
||||
val currentVisibility = when (visibility) {
|
||||
Visibilities.Local -> Visibilities.Public
|
||||
Visibilities.PrivateToThis -> Visibilities.Public
|
||||
Visibilities.InvisibleFake -> Visibilities.Public
|
||||
Visibilities.Inherited -> Visibilities.Public
|
||||
Visibilities.Unknown -> Visibilities.Public
|
||||
else -> visibility
|
||||
}.applyIf(options.normalizedVisibilities) {
|
||||
normalize()
|
||||
}
|
||||
|
||||
if (currentVisibility == Visibilities.DEFAULT_VISIBILITY) return
|
||||
append(currentVisibility.internalDisplayName)
|
||||
append(' ')
|
||||
}
|
||||
|
||||
private fun PrettyPrinter.renderModality(memberDeclaration: FirMemberDeclaration) {
|
||||
val modality = memberDeclaration.modality ?: return
|
||||
if ((memberDeclaration as? FirRegularClass)?.isInterface == true) return
|
||||
if (modality == Modality.FINAL) return
|
||||
if (memberDeclaration.getContainingClassSymbol(useSiteSession)?.classKind == ClassKind.INTERFACE) return
|
||||
if (memberDeclaration.isOverride) return
|
||||
renderIf(RendererModifier.MODALITY in options.modifiers, modality.name.toLowerCaseAsciiOnly())
|
||||
}
|
||||
|
||||
|
||||
private fun PrettyPrinter.renderOverride(callableMember: FirMemberDeclaration) {
|
||||
if (RendererModifier.OVERRIDE !in options.modifiers) return
|
||||
renderIf(callableMember.isOverride || options.forceRenderingOverrideModifier, "override")
|
||||
}
|
||||
|
||||
protected fun PrettyPrinter.renderIf(value: Boolean, text: String) {
|
||||
if (value) {
|
||||
append(text)
|
||||
append(" ")
|
||||
}
|
||||
}
|
||||
|
||||
protected fun PrettyPrinter.renderAnnotationsAndModifiers(declaration: FirMemberDeclaration) {
|
||||
if (!options.renderDeclarationHeader) return
|
||||
renderAnnotations(declaration)
|
||||
renderVisibility(declaration)
|
||||
renderOverride(declaration)
|
||||
renderModality(declaration)
|
||||
renderIf(declaration.isExternal, "external")
|
||||
renderIf(RendererModifier.EXPECT in options.modifiers && declaration.isExpect, "expect")
|
||||
renderIf(RendererModifier.ACTUAL in options.modifiers && declaration.isActual, "actual")
|
||||
renderIf(declaration.isTailRec, "tailrec")
|
||||
renderIf(declaration.isConst, "const")
|
||||
renderIf(declaration.isInner, "inner")
|
||||
renderIf(declaration.isLateInit, "lateinit")
|
||||
renderIf(declaration.isSuspend, "suspend")
|
||||
renderIf(declaration.isInline, "inline")
|
||||
renderIf(declaration.isInfix, "infix")
|
||||
renderIf(RendererModifier.OPERATOR in options.modifiers && declaration.isOperator, "operator")
|
||||
}
|
||||
|
||||
protected fun PrettyPrinter.renderClassifierKind(classifier: FirDeclaration) {
|
||||
when (classifier) {
|
||||
is FirTypeAlias -> append("typealias")
|
||||
is FirRegularClass ->
|
||||
append(if (classifier.isCompanion) "companion object" else classifier.classKind.codeRepresentation)
|
||||
is FirAnonymousObject -> append("object")
|
||||
is FirEnumEntry -> append("enum entry")
|
||||
else ->
|
||||
throw AssertionError("Unexpected classifier: $classifier")
|
||||
}
|
||||
append(' ')
|
||||
}
|
||||
|
||||
|
||||
protected fun PrettyPrinter.renderSuperTypes(klass: FirClass) {
|
||||
if (klass.defaultType().isNothing) return
|
||||
|
||||
val supertypes = klass.superTypeRefs.asSequence()
|
||||
.applyIf(klass.classKind == ClassKind.ENUM_CLASS) {
|
||||
filterNot {
|
||||
it.coneType.classId == StandardClassIds.Enum
|
||||
}
|
||||
}.applyIf(klass.classKind == ClassKind.ANNOTATION_CLASS) {
|
||||
filterNot {
|
||||
it.coneType.classId == StandardClassIds.Annotation
|
||||
}
|
||||
}.toList()
|
||||
|
||||
if (supertypes.isEmpty() || klass.superTypeRefs.singleOrNull()?.isAny == true) return
|
||||
|
||||
append(": ")
|
||||
printCollection(supertypes) {
|
||||
renderType(it)
|
||||
}
|
||||
append(' ')
|
||||
}
|
||||
}
|
||||
|
||||
-2
@@ -5,8 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.containingDeclarationProvider
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtTypeRendererOptions
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.renderScopeWithParentDeclarations
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol
|
||||
|
||||
-115
@@ -11,124 +11,9 @@ import org.jetbrains.kotlin.analysis.api.renderer.declarations.impl.KtDeclaratio
|
||||
import org.jetbrains.kotlin.analysis.api.renderer.types.KtTypeRenderer
|
||||
import org.jetbrains.kotlin.analysis.api.renderer.types.impl.KtTypeRendererForSource
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtDeclarationSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
/**
|
||||
* KtType to string renderer options
|
||||
* @see KtType
|
||||
* @see KtSymbolDeclarationRendererProvider.renderType
|
||||
*/
|
||||
public data class KtTypeRendererOptions(
|
||||
/**
|
||||
* Render type name without package name for not local types
|
||||
*/
|
||||
public val shortQualifiedNames: Boolean = false,
|
||||
/**
|
||||
* Render public function types public functionN using Kotlin public function type syntax
|
||||
* @see public function
|
||||
* @sample public function0<Int> returns () -> Int
|
||||
*/
|
||||
public val renderFunctionType: Boolean = true,
|
||||
|
||||
/**
|
||||
* When met type with unresolved qualifier, render it as it is resolved
|
||||
* When `true` will render as `UnresolvedQualifier`
|
||||
* When `false` will render as "ERROR_TYPE <symbol not found for UnresolvedQualifier>"
|
||||
*/
|
||||
public val renderUnresolvedTypeAsResolved: Boolean = true,
|
||||
|
||||
/**
|
||||
* Should annotations on types be rendered.
|
||||
*/
|
||||
public val renderTypeAnnotations: Boolean = true
|
||||
) {
|
||||
public companion object {
|
||||
public val DEFAULT: KtTypeRendererOptions = KtTypeRendererOptions()
|
||||
public val SHORT_NAMES: KtTypeRendererOptions = DEFAULT.copy(shortQualifiedNames = true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* KtSymbol to string renderer options
|
||||
* @see KtSymbol
|
||||
* @see KtSymbolDeclarationRendererProvider.renderType
|
||||
*/
|
||||
public data class KtDeclarationRendererOptions(
|
||||
/**
|
||||
* Set of modifiers that needed to be rendered
|
||||
* @see RendererModifier
|
||||
*/
|
||||
val modifiers: Set<RendererModifier> = RendererModifier.ALL,
|
||||
/**
|
||||
* Type render options @see KtTypeRendererOptions
|
||||
* @see KtTypeRendererOptions
|
||||
*/
|
||||
val typeRendererOptions: KtTypeRendererOptions = KtTypeRendererOptions.DEFAULT,
|
||||
/**
|
||||
* Render Unit return type for public functions
|
||||
*/
|
||||
val renderUnitReturnType: Boolean = false,
|
||||
/**
|
||||
* Normalize java-specific visibilities for java declaration
|
||||
*/
|
||||
val normalizedVisibilities: Boolean = false,
|
||||
/**
|
||||
* Render members of a classes and objects if any
|
||||
*/
|
||||
val renderClassMembers: Boolean = false,
|
||||
/**
|
||||
* Approximate Kotlin not-denotable types into denotable for declarations return type
|
||||
*/
|
||||
val approximateTypes: Boolean = false,
|
||||
|
||||
/**
|
||||
* Declaration header is something like `public abstract class`, `public fun`, or `private public interface ` in a declaration.
|
||||
*/
|
||||
val renderDeclarationHeader: Boolean = true,
|
||||
|
||||
/**
|
||||
* Whether to forcefully add `override` modifier when rendering public functions or properties. Note that the [modifiers] option still
|
||||
* controls whether `override` is rendered. That is, if [modifiers] don't contain `override`, then this flag does not have any effect.
|
||||
*/
|
||||
val forceRenderingOverrideModifier: Boolean = false,
|
||||
|
||||
val renderDefaultParameterValue: Boolean = true,
|
||||
|
||||
/**
|
||||
* Sort nested declarations by kind (enum values, then constructors, then properties, then functions) and name.
|
||||
*/
|
||||
val sortNestedDeclarations: Boolean = false,
|
||||
) {
|
||||
public companion object {
|
||||
public val DEFAULT: KtDeclarationRendererOptions = KtDeclarationRendererOptions()
|
||||
}
|
||||
}
|
||||
|
||||
public enum class RendererModifier(public val includeByDefault: Boolean) {
|
||||
VISIBILITY(true),
|
||||
MODALITY(true),
|
||||
OVERRIDE(true),
|
||||
ANNOTATIONS(false),
|
||||
INNER(true),
|
||||
DATA(true),
|
||||
INLINE(true),
|
||||
EXPECT(true),
|
||||
ACTUAL(true),
|
||||
CONST(true),
|
||||
LATEINIT(true),
|
||||
FUN(true),
|
||||
VALUE(true),
|
||||
OPERATOR(true)
|
||||
;
|
||||
|
||||
public companion object {
|
||||
public val ALL: Set<RendererModifier> = values().toSet()
|
||||
public val DEFAULT: Set<RendererModifier> = values().filterTo(mutableSetOf()) { it.includeByDefault }
|
||||
public val NONE: Set<RendererModifier> = emptySet()
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class KtSymbolDeclarationRendererProvider : KtAnalysisSessionComponent() {
|
||||
public abstract fun renderDeclaration(symbol: KtDeclarationSymbol, renderer: KtDeclarationRenderer): String
|
||||
|
||||
Reference in New Issue
Block a user