Generate references to superclasses
This commit is contained in:
@@ -38,14 +38,20 @@ import java.lang.AssertionError
|
|||||||
class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGeneratorExtension(declarationGenerator) {
|
class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGeneratorExtension(declarationGenerator) {
|
||||||
fun generateClass(ktClassOrObject: KtClassOrObject): IrClass {
|
fun generateClass(ktClassOrObject: KtClassOrObject): IrClass {
|
||||||
val descriptor = getOrFail(BindingContext.CLASS, ktClassOrObject)
|
val descriptor = getOrFail(BindingContext.CLASS, ktClassOrObject)
|
||||||
|
val startOffset = ktClassOrObject.startOffset
|
||||||
|
val endOffset = ktClassOrObject.endOffset
|
||||||
|
|
||||||
return context.symbolTable.declareClass(
|
return context.symbolTable.declareClass(
|
||||||
ktClassOrObject.startOffset, ktClassOrObject.endOffset,
|
startOffset, endOffset, IrDeclarationOrigin.DEFINED, descriptor
|
||||||
IrDeclarationOrigin.DEFINED,
|
|
||||||
descriptor
|
|
||||||
).buildWithScope { irClass ->
|
).buildWithScope { irClass ->
|
||||||
|
descriptor.typeConstructor.supertypes.mapNotNullTo(irClass.superClasses) {
|
||||||
|
it.constructor.declarationDescriptor?.safeAs<ClassDescriptor>()?.let {
|
||||||
|
context.symbolTable.referenceClass(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
irClass.thisReceiver = context.symbolTable.declareValueParameter(
|
irClass.thisReceiver = context.symbolTable.declareValueParameter(
|
||||||
ktClassOrObject.startOffset, ktClassOrObject.endOffset,
|
startOffset, endOffset,
|
||||||
IrDeclarationOrigin.INSTANCE_RECEIVER,
|
IrDeclarationOrigin.INSTANCE_RECEIVER,
|
||||||
irClass.descriptor.thisAsReceiverParameter
|
irClass.descriptor.thisAsReceiverParameter
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-1
@@ -68,7 +68,7 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator {
|
|||||||
fun generateClassOrObjectDeclaration(ktClassOrObject: KtClassOrObject): IrClass =
|
fun generateClassOrObjectDeclaration(ktClassOrObject: KtClassOrObject): IrClass =
|
||||||
ClassGenerator(this).generateClass(ktClassOrObject)
|
ClassGenerator(this).generateClass(ktClassOrObject)
|
||||||
|
|
||||||
fun generateTypeAliasDeclaration(ktDeclaration: KtTypeAlias): IrDeclaration =
|
private fun generateTypeAliasDeclaration(ktDeclaration: KtTypeAlias): IrDeclaration =
|
||||||
IrTypeAliasImpl(
|
IrTypeAliasImpl(
|
||||||
ktDeclaration.startOffset, ktDeclaration.endOffset, IrDeclarationOrigin.DEFINED,
|
ktDeclaration.startOffset, ktDeclaration.endOffset, IrDeclarationOrigin.DEFINED,
|
||||||
getOrFail(BindingContext.TYPE_ALIAS, ktDeclaration)
|
getOrFail(BindingContext.TYPE_ALIAS, ktDeclaration)
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ interface IrClass : IrSymbolDeclaration<IrClassSymbol>, IrDeclarationContainer,
|
|||||||
val isCompanion: Boolean
|
val isCompanion: Boolean
|
||||||
val isData: Boolean
|
val isData: Boolean
|
||||||
|
|
||||||
|
// NB type parameters can't be top-level classifiers in supetypes of a class
|
||||||
|
val superClasses: MutableList<IrClassSymbol>
|
||||||
|
|
||||||
var thisReceiver: IrValueParameter?
|
var thisReceiver: IrValueParameter?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ class IrClassImpl(
|
|||||||
|
|
||||||
override val typeParameters: MutableList<IrTypeParameter> = SmartList()
|
override val typeParameters: MutableList<IrTypeParameter> = SmartList()
|
||||||
|
|
||||||
|
override val superClasses: MutableList<IrClassSymbol> = SmartList()
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||||
visitor.visitClass(this, data)
|
visitor.visitClass(this, data)
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
|||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
class DeclarationStubGenerator(
|
class DeclarationStubGenerator(
|
||||||
val symbolTable: SymbolTable,
|
val symbolTable: SymbolTable,
|
||||||
@@ -56,7 +57,7 @@ class DeclarationStubGenerator(
|
|||||||
throw AssertionError("Unexpected member descriptor: $descriptor")
|
throw AssertionError("Unexpected member descriptor: $descriptor")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generatePropertyStub(descriptor: PropertyDescriptor): IrProperty =
|
private fun generatePropertyStub(descriptor: PropertyDescriptor): IrProperty =
|
||||||
IrPropertyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor).also { irProperty ->
|
IrPropertyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor).also { irProperty ->
|
||||||
val getterDescriptor = descriptor.getter
|
val getterDescriptor = descriptor.getter
|
||||||
if (getterDescriptor == null) {
|
if (getterDescriptor == null) {
|
||||||
@@ -75,16 +76,16 @@ class DeclarationStubGenerator(
|
|||||||
generateValueParametersStubs(descriptor.valueParameters, irFunction)
|
generateValueParametersStubs(descriptor.valueParameters, irFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateConstructorStub(descriptor: ClassConstructorDescriptor): IrConstructor =
|
private fun generateConstructorStub(descriptor: ClassConstructorDescriptor): IrConstructor =
|
||||||
symbolTable.declareConstructor(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor.original).also { irConstructor ->
|
symbolTable.declareConstructor(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor.original).also { irConstructor ->
|
||||||
generateValueParametersStubs(descriptor.valueParameters, irConstructor)
|
generateValueParametersStubs(descriptor.valueParameters, irConstructor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateValueParametersStubs(valueParameters: Collection<ValueParameterDescriptor>, function: IrFunction) {
|
private fun generateValueParametersStubs(valueParameters: Collection<ValueParameterDescriptor>, function: IrFunction) {
|
||||||
valueParameters.mapTo(function.valueParameters) { generateValueParameterStub(it) }
|
valueParameters.mapTo(function.valueParameters) { generateValueParameterStub(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateValueParameterStub(descriptor: ValueParameterDescriptor): IrValueParameter =
|
private fun generateValueParameterStub(descriptor: ValueParameterDescriptor): IrValueParameter =
|
||||||
IrValueParameterImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor).also { irValueParameter ->
|
IrValueParameterImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor).also { irValueParameter ->
|
||||||
if (descriptor.declaresDefaultValue()) {
|
if (descriptor.declaresDefaultValue()) {
|
||||||
irValueParameter.defaultValue =
|
irValueParameter.defaultValue =
|
||||||
@@ -97,29 +98,36 @@ class DeclarationStubGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateClassStub(descriptor: ClassDescriptor): IrClass =
|
private fun generateClassStub(descriptor: ClassDescriptor): IrClass =
|
||||||
symbolTable.declareClass(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor).also { irClass ->
|
symbolTable.declareClass(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor).also { irClass ->
|
||||||
|
// TODO get rid of code duplication, see ClassGenerator#generateClass
|
||||||
|
descriptor.typeConstructor.supertypes.mapNotNullTo(irClass.superClasses) {
|
||||||
|
it.constructor.declarationDescriptor?.safeAs<ClassDescriptor>()?.let {
|
||||||
|
symbolTable.referenceClass(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
generateTypeParameterStubs(descriptor.declaredTypeParameters, irClass)
|
generateTypeParameterStubs(descriptor.declaredTypeParameters, irClass)
|
||||||
generateChildStubs(descriptor.constructors, irClass)
|
generateChildStubs(descriptor.constructors, irClass)
|
||||||
generateMemberStubs(descriptor.defaultType.memberScope, irClass)
|
generateMemberStubs(descriptor.defaultType.memberScope, irClass)
|
||||||
generateMemberStubs(descriptor.staticScope, irClass)
|
generateMemberStubs(descriptor.staticScope, irClass)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateEnumEntryStub(descriptor: ClassDescriptor): IrEnumEntry =
|
private fun generateEnumEntryStub(descriptor: ClassDescriptor): IrEnumEntry =
|
||||||
symbolTable.declareEnumEntry(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor)
|
symbolTable.declareEnumEntry(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor)
|
||||||
|
|
||||||
fun generateTypeParameterStubs(typeParameters: List<TypeParameterDescriptor>, container: IrTypeParametersContainer) {
|
private fun generateTypeParameterStubs(typeParameters: List<TypeParameterDescriptor>, container: IrTypeParametersContainer) {
|
||||||
typeParameters.mapTo(container.typeParameters) { generateTypeParameterStub(it) }
|
typeParameters.mapTo(container.typeParameters) { generateTypeParameterStub(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateTypeParameterStub(descriptor: TypeParameterDescriptor): IrTypeParameter =
|
private fun generateTypeParameterStub(descriptor: TypeParameterDescriptor): IrTypeParameter =
|
||||||
IrTypeParameterImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor)
|
IrTypeParameterImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor)
|
||||||
|
|
||||||
fun generateMemberStubs(memberScope: MemberScope, container: IrDeclarationContainer) {
|
private fun generateMemberStubs(memberScope: MemberScope, container: IrDeclarationContainer) {
|
||||||
generateChildStubs(memberScope.getContributedDescriptors(), container)
|
generateChildStubs(memberScope.getContributedDescriptors(), container)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateChildStubs(descriptors: Collection<DeclarationDescriptor>, container: IrDeclarationContainer) {
|
private fun generateChildStubs(descriptors: Collection<DeclarationDescriptor>, container: IrDeclarationContainer) {
|
||||||
descriptors.sortedWith(StableDescriptorsComparator).mapTo(container.declarations) { generateMemberStub(it) }
|
descriptors.sortedWith(StableDescriptorsComparator).mapTo(container.declarations) { generateMemberStub(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.ir.declarations.*
|
|||||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
||||||
@@ -96,6 +97,19 @@ open class DeepCopyIrTree : IrElementTransformerVoid() {
|
|||||||
).apply {
|
).apply {
|
||||||
thisReceiver = declaration.thisReceiver?.withDescriptor(descriptor.thisAsReceiverParameter)
|
thisReceiver = declaration.thisReceiver?.withDescriptor(descriptor.thisAsReceiverParameter)
|
||||||
transformTypeParameters(declaration, descriptor.declaredTypeParameters)
|
transformTypeParameters(declaration, descriptor.declaredTypeParameters)
|
||||||
|
|
||||||
|
descriptor.typeConstructor.supertypes.forEachIndexed { index, supertype ->
|
||||||
|
val superclassDescriptor = supertype.constructor.declarationDescriptor
|
||||||
|
if (superclassDescriptor is ClassDescriptor) {
|
||||||
|
val oldSuperclassSymbol = declaration.superClasses.getOrNull(index)
|
||||||
|
val newSuperclassSymbol =
|
||||||
|
if (superclassDescriptor == oldSuperclassSymbol?.descriptor)
|
||||||
|
oldSuperclassSymbol
|
||||||
|
else
|
||||||
|
IrClassSymbolImpl(superclassDescriptor)
|
||||||
|
superClasses.add(newSuperclassSymbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrValueParameter.withDescriptor(newDescriptor: ParameterDescriptor) =
|
private fun IrValueParameter.withDescriptor(newDescriptor: ParameterDescriptor) =
|
||||||
|
|||||||
@@ -88,6 +88,9 @@ open class DeepCopyIrTreeWithSymbols(private val symbolRemapper: SymbolRemapper)
|
|||||||
mapDeclarationOrigin(declaration.origin),
|
mapDeclarationOrigin(declaration.origin),
|
||||||
symbolRemapper.getDeclaredClass(declaration.symbol)
|
symbolRemapper.getDeclaredClass(declaration.symbol)
|
||||||
).apply {
|
).apply {
|
||||||
|
declaration.superClasses.mapTo(superClasses) {
|
||||||
|
symbolRemapper.getReferencedClass(it)
|
||||||
|
}
|
||||||
thisReceiver = declaration.thisReceiver?.transform()
|
thisReceiver = declaration.thisReceiver?.transform()
|
||||||
declaration.typeParameters.transformTo(typeParameters)
|
declaration.typeParameters.transformTo(typeParameters)
|
||||||
declaration.transformDeclarationsTo(this)
|
declaration.transformDeclarationsTo(this)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
|
||||||
|
|
||||||
class DependenciesCollector {
|
class DependenciesCollector {
|
||||||
private val modulesForDependencyDescriptors = LinkedHashSet<ModuleDescriptor>()
|
private val modulesForDependencyDescriptors = LinkedHashSet<ModuleDescriptor>()
|
||||||
@@ -41,6 +42,14 @@ class DependenciesCollector {
|
|||||||
assert(symbolTable.unboundValueParameters.isEmpty()) { "Unbound value parameters: ${symbolTable.unboundValueParameters}" }
|
assert(symbolTable.unboundValueParameters.isEmpty()) { "Unbound value parameters: ${symbolTable.unboundValueParameters}" }
|
||||||
assert(symbolTable.unboundVariables.isEmpty()) { "Unbound variables: ${symbolTable.unboundVariables}" }
|
assert(symbolTable.unboundVariables.isEmpty()) { "Unbound variables: ${symbolTable.unboundVariables}" }
|
||||||
|
|
||||||
|
for (unboundClass in symbolTable.unboundClasses.toTypedArray()) {
|
||||||
|
for (superClassifier in unboundClass.descriptor.getAllSuperClassifiers()) {
|
||||||
|
if (superClassifier is ClassDescriptor) {
|
||||||
|
symbolTable.referenceClass(superClassifier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
symbolTable.unboundClasses.addTopLevelDeclarations()
|
symbolTable.unboundClasses.addTopLevelDeclarations()
|
||||||
symbolTable.unboundConstructors.addTopLevelDeclarations()
|
symbolTable.unboundConstructors.addTopLevelDeclarations()
|
||||||
symbolTable.unboundEnumEntries.addTopLevelDeclarations()
|
symbolTable.unboundEnumEntries.addTopLevelDeclarations()
|
||||||
|
|||||||
@@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.util
|
package org.jetbrains.kotlin.ir.util
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.SourceManager
|
import org.jetbrains.kotlin.ir.SourceManager
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrBindableSymbol
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
@@ -78,6 +80,7 @@ class DumpIrTreeVisitor(out: Appendable) : IrElementVisitor<Unit, String> {
|
|||||||
override fun visitClass(declaration: IrClass, data: String) {
|
override fun visitClass(declaration: IrClass, data: String) {
|
||||||
declaration.dumpLabeledElementWith(data) {
|
declaration.dumpLabeledElementWith(data) {
|
||||||
declaration.thisReceiver?.accept(this, "\$this")
|
declaration.thisReceiver?.accept(this, "\$this")
|
||||||
|
declaration.superClasses.renderDeclarationElementsOrDescriptors("superClasses")
|
||||||
declaration.typeParameters.dumpElements()
|
declaration.typeParameters.dumpElements()
|
||||||
declaration.declarations.dumpElements()
|
declaration.declarations.dumpElements()
|
||||||
}
|
}
|
||||||
@@ -85,16 +88,7 @@ class DumpIrTreeVisitor(out: Appendable) : IrElementVisitor<Unit, String> {
|
|||||||
|
|
||||||
override fun visitSimpleFunction(declaration: IrSimpleFunction, data: String) {
|
override fun visitSimpleFunction(declaration: IrSimpleFunction, data: String) {
|
||||||
declaration.dumpLabeledElementWith(data) {
|
declaration.dumpLabeledElementWith(data) {
|
||||||
if (declaration.overriddenSymbols.isNotEmpty()) {
|
declaration.overriddenSymbols.renderDeclarationElementsOrDescriptors("overridden")
|
||||||
indented("overridden") {
|
|
||||||
for (overriddenSymbol in declaration.overriddenSymbols) {
|
|
||||||
if (overriddenSymbol.isBound)
|
|
||||||
overriddenSymbol.owner.render()
|
|
||||||
else
|
|
||||||
printer.println("UNBOUND: ", DescriptorRenderer.COMPACT.render(overriddenSymbol.descriptor))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
declaration.typeParameters.dumpElements()
|
declaration.typeParameters.dumpElements()
|
||||||
declaration.dispatchReceiverParameter?.accept(this, "\$this")
|
declaration.dispatchReceiverParameter?.accept(this, "\$this")
|
||||||
declaration.extensionReceiverParameter?.accept(this, "\$receiver")
|
declaration.extensionReceiverParameter?.accept(this, "\$receiver")
|
||||||
@@ -103,6 +97,25 @@ class DumpIrTreeVisitor(out: Appendable) : IrElementVisitor<Unit, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun <D : DeclarationDescriptor, B : IrSymbolOwner> Collection<IrBindableSymbol<D, B>>.renderDeclarationElementsOrDescriptors(
|
||||||
|
caption: String
|
||||||
|
) {
|
||||||
|
if (isNotEmpty()) {
|
||||||
|
indented(caption) {
|
||||||
|
for (symbol in this) {
|
||||||
|
symbol.renderDeclarationElementOrDescriptor()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <D : DeclarationDescriptor, B : IrSymbolOwner> IrBindableSymbol<D, B>.renderDeclarationElementOrDescriptor() {
|
||||||
|
if (isBound)
|
||||||
|
owner.render()
|
||||||
|
else
|
||||||
|
printer.println("UNBOUND: ", DescriptorRenderer.COMPACT.render(descriptor))
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitConstructor(declaration: IrConstructor, data: String) {
|
override fun visitConstructor(declaration: IrConstructor, data: String) {
|
||||||
declaration.dumpLabeledElementWith(data) {
|
declaration.dumpLabeledElementWith(data) {
|
||||||
declaration.typeParameters.dumpElements()
|
declaration.typeParameters.dumpElements()
|
||||||
|
|||||||
Reference in New Issue
Block a user