Minor. Code clean: use class kind utils
This commit is contained in:
+2
-2
@@ -18,11 +18,11 @@ package org.jetbrains.kotlin.backend.common
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.util.isAnnotationClass
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
@@ -198,7 +198,7 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor
|
|||||||
override fun visitClass(declaration: IrClass) {
|
override fun visitClass(declaration: IrClass) {
|
||||||
super.visitClass(declaration)
|
super.visitClass(declaration)
|
||||||
|
|
||||||
if (declaration.descriptor.kind != ClassKind.ANNOTATION_CLASS) {
|
if (!declaration.isAnnotationClass) {
|
||||||
// Check that all functions and properties from memberScope are present in IR
|
// Check that all functions and properties from memberScope are present in IR
|
||||||
// (including FAKE_OVERRIDE ones).
|
// (including FAKE_OVERRIDE ones).
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.declarations.IrClass
|
|||||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.util.isInterface
|
||||||
import org.jetbrains.kotlin.ir.util.isReal
|
import org.jetbrains.kotlin.ir.util.isReal
|
||||||
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
|
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
@@ -24,7 +25,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
|||||||
|
|
||||||
private val className = context.getNameForSymbol(irClass.symbol)
|
private val className = context.getNameForSymbol(irClass.symbol)
|
||||||
private val classNameRef = className.makeRef()
|
private val classNameRef = className.makeRef()
|
||||||
private val baseClass = irClass.superClasses.firstOrNull { it.owner.kind != ClassKind.INTERFACE }
|
private val baseClass = irClass.superClasses.firstOrNull { !it.owner.isInterface }
|
||||||
private val baseClassName = baseClass?.let { context.getNameForSymbol(it) }
|
private val baseClassName = baseClass?.let { context.getNameForSymbol(it) }
|
||||||
private val classPrototypeRef = prototypeOf(classNameRef)
|
private val classPrototypeRef = prototypeOf(classNameRef)
|
||||||
private val classBlock = JsBlock()
|
private val classBlock = JsBlock()
|
||||||
@@ -74,7 +75,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
|||||||
// interface I { foo() = "OK" }
|
// interface I { foo() = "OK" }
|
||||||
// interface II : I
|
// interface II : I
|
||||||
// II.prototype.foo = I.prototype.foo
|
// II.prototype.foo = I.prototype.foo
|
||||||
if (irClass.kind != ClassKind.INTERFACE) {
|
if (!irClass.isInterface) {
|
||||||
declaration.resolveFakeOverride()?.let {
|
declaration.resolveFakeOverride()?.let {
|
||||||
val implClassDesc = it.descriptor.containingDeclaration as ClassDescriptor
|
val implClassDesc = it.descriptor.containingDeclaration as ClassDescriptor
|
||||||
if (!KotlinBuiltIns.isAny(implClassDesc)) {
|
if (!KotlinBuiltIns.isAny(implClassDesc)) {
|
||||||
@@ -153,7 +154,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
|||||||
|
|
||||||
private fun generateSuperClasses(): JsPropertyInitializer = JsPropertyInitializer(
|
private fun generateSuperClasses(): JsPropertyInitializer = JsPropertyInitializer(
|
||||||
JsNameRef(Namer.METADATA_INTERFACES),
|
JsNameRef(Namer.METADATA_INTERFACES),
|
||||||
JsArrayLiteral(irClass.superClasses.filter { it.owner.kind == ClassKind.INTERFACE }.map { JsNameRef(context.getNameForSymbol(it.owner.symbol)) })
|
JsArrayLiteral(irClass.superClasses.filter { it.owner.isInterface }.map { JsNameRef(context.getNameForSymbol(it.owner.symbol)) })
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -40,7 +40,7 @@ import org.jetbrains.org.objectweb.asm.Type
|
|||||||
import java.lang.RuntimeException
|
import java.lang.RuntimeException
|
||||||
|
|
||||||
class ClassCodegen private constructor(
|
class ClassCodegen private constructor(
|
||||||
private val irClass: IrClass,
|
internal val irClass: IrClass,
|
||||||
val context: JvmBackendContext,
|
val context: JvmBackendContext,
|
||||||
private val parentClassCodegen: ClassCodegen? = null
|
private val parentClassCodegen: ClassCodegen? = null
|
||||||
) : InnerClassConsumer {
|
) : InnerClassConsumer {
|
||||||
|
|||||||
+7
-9
@@ -26,8 +26,8 @@ import org.jetbrains.kotlin.ir.declarations.IrClass
|
|||||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.util.dump
|
import org.jetbrains.kotlin.ir.util.dump
|
||||||
|
import org.jetbrains.kotlin.ir.util.isAnnotationClass
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||||
@@ -60,7 +60,7 @@ open class FunctionCodegen(private val irFunction: IrFunction, private val class
|
|||||||
FunctionCodegen.generateMethodAnnotations(descriptor, signature.asmMethod, methodVisitor, classCodegen, state.typeMapper)
|
FunctionCodegen.generateMethodAnnotations(descriptor, signature.asmMethod, methodVisitor, classCodegen, state.typeMapper)
|
||||||
FunctionCodegen.generateParameterAnnotations(descriptor, methodVisitor, signature, classCodegen, state)
|
FunctionCodegen.generateParameterAnnotations(descriptor, methodVisitor, signature, classCodegen, state)
|
||||||
|
|
||||||
if (!state.classBuilderMode.generateBodies || flags.and(Opcodes.ACC_ABSTRACT) != 0 || descriptor.isExternal) {
|
if (!state.classBuilderMode.generateBodies || flags.and(Opcodes.ACC_ABSTRACT) != 0 || irFunction.isExternal) {
|
||||||
generateAnnotationDefaultValueIfNeeded(methodVisitor)
|
generateAnnotationDefaultValueIfNeeded(methodVisitor)
|
||||||
methodVisitor.visitEnd()
|
methodVisitor.visitEnd()
|
||||||
return
|
return
|
||||||
@@ -72,16 +72,15 @@ open class FunctionCodegen(private val irFunction: IrFunction, private val class
|
|||||||
|
|
||||||
private fun calculateMethodFlags(isStatic: Boolean): Int {
|
private fun calculateMethodFlags(isStatic: Boolean): Int {
|
||||||
var flags = AsmUtil.getMethodAsmFlags(descriptor, OwnerKind.IMPLEMENTATION, state).or(if (isStatic) Opcodes.ACC_STATIC else 0).xor(
|
var flags = AsmUtil.getMethodAsmFlags(descriptor, OwnerKind.IMPLEMENTATION, state).or(if (isStatic) Opcodes.ACC_STATIC else 0).xor(
|
||||||
if (DescriptorUtils.isAnnotationClass(descriptor.containingDeclaration)) Opcodes.ACC_FINAL else 0/*TODO*/
|
if (classCodegen.irClass.isAnnotationClass) Opcodes.ACC_FINAL else 0/*TODO*/
|
||||||
).or(if (descriptor is JvmDescriptorWithExtraFlags) descriptor.extraFlags else 0)
|
).or(if (descriptor is JvmDescriptorWithExtraFlags) descriptor.extraFlags else 0)
|
||||||
|
|
||||||
if (irFunction.origin == DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER) {
|
if (irFunction.origin == DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER) {
|
||||||
flags = flags.xor(AsmUtil.getVisibilityAccessFlag(descriptor)).or(Opcodes.ACC_PUBLIC)
|
flags = flags.xor(AsmUtil.getVisibilityAccessFlag(descriptor)).or(Opcodes.ACC_PUBLIC)
|
||||||
}
|
}
|
||||||
|
|
||||||
val interfaceClInit = JvmCodegenUtil.isJvmInterface(classCodegen.descriptor) && InitializersLowering.clinitName == descriptor.name
|
if (classCodegen.irClass.isJvmInterface && InitializersLowering.clinitName == irFunction.name) {
|
||||||
if (interfaceClInit) {
|
//reset abstract flag for <clinit>
|
||||||
//reset abstract flag
|
|
||||||
flags = flags.xor(Opcodes.ACC_ABSTRACT)
|
flags = flags.xor(Opcodes.ACC_ABSTRACT)
|
||||||
}
|
}
|
||||||
return flags
|
return flags
|
||||||
@@ -97,9 +96,8 @@ open class FunctionCodegen(private val irFunction: IrFunction, private val class
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateAnnotationDefaultValueIfNeeded(methodVisitor: MethodVisitor) {
|
private fun generateAnnotationDefaultValueIfNeeded(methodVisitor: MethodVisitor) {
|
||||||
val directMember = JvmCodegenUtil.getDirectMember(descriptor)
|
if (classCodegen.irClass.isAnnotationClass) {
|
||||||
if (DescriptorUtils.isAnnotationClass(directMember.containingDeclaration)) {
|
val source = JvmCodegenUtil.getDirectMember(descriptor).source
|
||||||
val source = directMember.source
|
|
||||||
(source.getPsi() as? KtParameter)?.defaultValue?.apply {
|
(source.getPsi() as? KtParameter)?.defaultValue?.apply {
|
||||||
val defaultValue = this
|
val defaultValue = this
|
||||||
val constant = org.jetbrains.kotlin.codegen.ExpressionCodegen.getCompileTimeConstant(
|
val constant = org.jetbrains.kotlin.codegen.ExpressionCodegen.getCompileTimeConstant(
|
||||||
|
|||||||
-4
@@ -16,19 +16,15 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm.lower
|
package org.jetbrains.kotlin.backend.jvm.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
|
|||||||
+3
-3
@@ -44,7 +44,7 @@ import java.util.*
|
|||||||
|
|
||||||
class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||||
override fun lower(irClass: IrClass) {
|
override fun lower(irClass: IrClass) {
|
||||||
if (irClass.kind != ClassKind.ENUM_CLASS) return
|
if (!irClass.isEnumClass) return
|
||||||
|
|
||||||
EnumClassTransformer(irClass).run()
|
EnumClassTransformer(irClass).run()
|
||||||
}
|
}
|
||||||
@@ -399,10 +399,10 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
|||||||
// TODO local (non-enum) class in enum class constructor?
|
// TODO local (non-enum) class in enum class constructor?
|
||||||
val previous = enumConstructorCallTransformer
|
val previous = enumConstructorCallTransformer
|
||||||
|
|
||||||
if (containingClass.kind == ClassKind.ENUM_ENTRY) {
|
if (containingClass.isEnumEntry) {
|
||||||
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" }
|
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" }
|
||||||
enumConstructorCallTransformer = InEnumEntryClassConstructor(enumEntryClassToEntry[containingClass]!!)
|
enumConstructorCallTransformer = InEnumEntryClassConstructor(enumEntryClassToEntry[containingClass]!!)
|
||||||
} else if (containingClass.kind == ClassKind.ENUM_CLASS) {
|
} else if (containingClass.isEnumClass) {
|
||||||
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" }
|
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" }
|
||||||
enumConstructorCallTransformer = InEnumClassConstructor(declaration)
|
enumConstructorCallTransformer = InEnumClassConstructor(declaration)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
|||||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil.isCompanionObjectInInterfaceNotIntrinsic
|
import org.jetbrains.kotlin.codegen.JvmCodegenUtil.isCompanionObjectInInterfaceNotIntrinsic
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.util.isObject
|
||||||
|
|
||||||
class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass {
|
class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass {
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformer
|
|||||||
|
|
||||||
|
|
||||||
private fun process(irClass: IrClass) {
|
private fun process(irClass: IrClass) {
|
||||||
if (irClass.descriptor.kind != ClassKind.OBJECT) return
|
if (!irClass.isObject) return
|
||||||
|
|
||||||
val publicInstance = context.descriptorsFactory.getSymbolForObjectInstance(irClass.symbol)
|
val publicInstance = context.descriptorsFactory.getSymbolForObjectInstance(irClass.symbol)
|
||||||
|
|
||||||
|
|||||||
+2
-4
@@ -18,20 +18,18 @@ package org.jetbrains.kotlin.backend.jvm.lower
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.lower.DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER
|
import org.jetbrains.kotlin.backend.common.lower.DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|
||||||
|
|
||||||
class StaticDefaultFunctionLowering(val state: GenerationState) : IrElementTransformerVoid(), ClassLoweringPass {
|
class StaticDefaultFunctionLowering(val state: GenerationState) : IrElementTransformerVoid(), ClassLoweringPass {
|
||||||
|
|
||||||
override fun lower(irClass: IrClass) {
|
override fun lower(irClass: IrClass) {
|
||||||
val kind = irClass.kind
|
if (irClass.isJvmInterface) {
|
||||||
if (kind == ClassKind.INTERFACE || kind == ClassKind.ANNOTATION_CLASS) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
irClass.accept(this, null)
|
irClass.accept(this, null)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
|
|||||||
import org.jetbrains.kotlin.ir.expressions.mapValueParameters
|
import org.jetbrains.kotlin.ir.expressions.mapValueParameters
|
||||||
import org.jetbrains.kotlin.ir.util.StableDescriptorsComparator
|
import org.jetbrains.kotlin.ir.util.StableDescriptorsComparator
|
||||||
import org.jetbrains.kotlin.ir.util.declareSimpleFunctionWithOverrides
|
import org.jetbrains.kotlin.ir.util.declareSimpleFunctionWithOverrides
|
||||||
|
import org.jetbrains.kotlin.ir.util.isEnumClass
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
||||||
import org.jetbrains.kotlin.psi.KtEnumEntry
|
import org.jetbrains.kotlin.psi.KtEnumEntry
|
||||||
@@ -72,11 +73,11 @@ class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGe
|
|||||||
|
|
||||||
generateFakeOverrideMemberDeclarations(irClass, ktClassOrObject)
|
generateFakeOverrideMemberDeclarations(irClass, ktClassOrObject)
|
||||||
|
|
||||||
if (descriptor.isData) {
|
if (irClass.isData) {
|
||||||
generateAdditionalMembersForDataClass(irClass, ktClassOrObject)
|
generateAdditionalMembersForDataClass(irClass, ktClassOrObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor.kind == ClassKind.ENUM_CLASS) {
|
if (irClass.isEnumClass) {
|
||||||
generateAdditionalMembersForEnumClass(irClass)
|
generateAdditionalMembersForEnumClass(irClass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user