/*
* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* This source file is part of the Cangjie project, licensed under Apache-2.0
* with Runtime Library Exception.
*
* See https://cangjie-lang.cn/pages/LICENSE for license information.
*/
// The Cangjie API is in Beta. For details on its capabilities and limitations, please refer to the README file.
package std.reflect
import std.collection.*
public class GenericTypeInfo <: TypeInfo & Equatable<GenericTypeInfo> {
public operator func ==(other: GenericTypeInfo): Bool {
return this.name == other.name
}
init(cp: CPointer<Unit>) {
super(cp)
}
}
/**
* Contains the reflective information about instance functions.
*/
public class InstanceFunctionInfo <: Equatable<InstanceFunctionInfo> & Hashable & ToString {
let _info: CPointer<Unit>
var _name: Option<String> = None
var _parameters: Option<ArrayList<ParameterInfo>> = None
var _returnType: Option<TypeInfo> = None
var _modifiers: Option<Collection<ModifierInfo>> = None
var _annotations: Option<Collection<Annotation>> = None
var _genericParams: Option<Collection<GenericTypeInfo>> = None
var _declaringTypeInfo: CPointer<Unit>
init(cp: CPointer<Unit>, info: CPointer<Unit>) {
_info = cp
_declaringTypeInfo = info
}
public prop genericParams: Collection<GenericTypeInfo> {
get() {
match (_genericParams) {
case Some(params) => params
case None =>
let genericParametersNum = getNumOfGenericParameters(_info)
if (genericParametersNum == 0) {
_genericParams = Option<Collection<GenericTypeInfo>>.None
return ArrayList<GenericTypeInfo>()
}
let params = ArrayList<GenericTypeInfo>(
Int64(genericParametersNum),
{
index =>
let pointer = getGenericParameterInfo(_info, UInt32(index))
if (pointer.isNull()) {
throw InfoNotFoundException("Get parameters failed!")
}
GenericTypeInfo(pointer)
}
)
_genericParams = Some(params)
params
}
}
}
/**
* Returns the name of instance function.
*/
public prop name: String {
get() {
_name.getOrThrow()
}
}
/**
* Returns the list of parameters of instance function.
*/
public prop parameters: ReadOnlyList<ParameterInfo> {
get() {
match (_parameters) {
case Some(res) => res
case None =>
let infos = getParameters(_info)
_parameters = infos
infos
}
}
}
/**
* Returns the return type of instance function.
*/
public prop returnType: TypeInfo {
get() {
match (_returnType) {
case Some(res) => res
case None =>
let pointer = getMethodReturnType(_info)
let info = TypeInfo.getOrCreate(pointer)
_returnType = info
info
}
}
}
/**
* Returns the collection of modifiers of instance function.
*/
public prop modifiers: Collection<ModifierInfo> {
get() {
match (_modifiers) {
case Some(res) => res
case None =>
let infos = ModifierInfo.byMask(getMethodModifier(_info))
_modifiers = infos
infos
}
}
}
/**
* Returns the collection of annotations of instance function.
*/
public prop annotations: Collection<Annotation> {
get() {
match (_annotations) {
case Some(res) => res
case None =>
let infos = match (getMethodAnnotations(_info, TypeInfo.of<Array<Object>>()._info)) {
case arr: Array<Annotation> => arr
case _ => Array<Annotation>()
}
_annotations = infos
infos
}
}
}
/**
* Returns true if instance function is 'public', false otherwise.
*/
public func isOpen(): Bool {
containsModifier(modifiers, ModifierInfo.Open)
}
/**
* Returns true if instance function is 'abstract', false otherwise.
*/
public func isAbstract(): Bool {
containsModifier(modifiers, ModifierInfo.Abstract)
}
/**
* Makes a call of public instance function with incoming args for incoming instance.
*
* @param args parameter list.
*
* @throw IllegalArgumentException, if the number of input parameters is different from the number of invoked function parameters.
* @throw IllegalTypeException, if the input parameter type does not match the required parameter type.
* @throw InvocationTargetException, if an exception is thrown when the function is abstract.
*/
public func apply(instance: Any, args: Array<Any>): Any {
let nullEntryPointer = methodEntryPointIsNull(_info)
if (isAbstract() && nullEntryPointer) {
throw InvocationTargetException("The abstract function cannot be applied.")
}
try {
if (genericParams.size > 0) {
throw InvocationTargetException("The generic function cannot be applied without `genericTypeArgs`.")
}
} catch (_: InfoNotFoundException) {
throw InvocationTargetException("The generic function cannot be applied without `genericTypeArgs`.")
}
checkArgsSizeAndType(parameters, args)
checkMethodDeclaringClassType(instance, _declaringTypeInfo)
applyCJInstanceMethod(_info, instance, args)
}
public func apply(instance: Any, genericTypeArgs: Array<TypeInfo>, args: Array<Any>): Any {
if (genericParams.size == 0) {
throw InvocationTargetException("The function cannot be applied with `genericTypeArgs`.")
}
let nullEntryPointer = methodEntryPointIsNull(_info)
if (isAbstract() && nullEntryPointer) {
throw InvocationTargetException("The abstract function cannot be applied.")
}
checkParamaterSize(genericParams, parameters.size, genericTypeArgs, args)
checkMethodDeclaringClassType(instance, _declaringTypeInfo)
let gArgs = ArrayList<CPointer<Unit>>(Int64(genericTypeArgs.size)) {index => genericTypeArgs[index]._info}
if (!checkMethodActualArgs(_info, gArgs.toArray(), args)) {
throw IllegalTypeException(
"The input parameter does not match the type of the input parameter required by the function.")
}
applyCJGenericInstanceMethod(_info, instance, gArgs.toArray(), args)
}
/**
* Searches the instance function's annotation by incoming name.
*/
public func findAnnotation<T>(): ?T where T <: Annotation {
findAnnotation<T>(annotations)
}
public func findAllAnnotations<T>(): Array<T> where T <: Annotation {
findAllAnnotations<T>(annotations)
}
public func getAllAnnotations(): Array<Annotation> {
annotations.toArray()
}
public operator func ==(other: InstanceFunctionInfo): Bool {
this._info == other._info
}
public operator func !=(other: InstanceFunctionInfo): Bool {
!(this == other)
}
public func hashCode(): Int64 {
this._info.toUIntNative().hashCode()
}
public func toString(): String {
let sb = StringBuilder()
for (m in modifiers) {
sb.append(m)
sb.append(" ")
}
sb.append("func ")
sb.append(name)
sb.append("(")
for (index in 0..parameters.size) {
sb.append(parameters[index])
if (index < parameters.size - 1) {
sb.append(", ")
}
}
sb.append("): ")
sb.append(returnType)
sb.toString()
}
}
/**
* Contains the reflective information about static functions.
*/
public class StaticFunctionInfo <: Equatable<StaticFunctionInfo> & Hashable & ToString {
let _info: CPointer<Unit>
var _name: Option<String> = None
var _parameters: Option<ArrayList<ParameterInfo>> = None
var _genericParams: Option<Collection<GenericTypeInfo>> = None
var _returnType: Option<TypeInfo> = None
var _modifiers: Option<Collection<ModifierInfo>> = None
var _annotations: Option<Collection<Annotation>> = None
var _declaringTypeInfo: CPointer<Unit>
init(cp: CPointer<Unit>, declaringTypeInfo: CPointer<Unit>) {
_info = cp
_declaringTypeInfo = declaringTypeInfo
}
public prop genericParams: Collection<GenericTypeInfo> {
get() {
match (_genericParams) {
case Some(params) => params
case None =>
let genericParametersNum = getNumOfGenericParameters(_info)
if (genericParametersNum == 0) {
_genericParams = Option<Collection<GenericTypeInfo>>.None
return ArrayList<GenericTypeInfo>()
}
let params = ArrayList<GenericTypeInfo>(
Int64(genericParametersNum),
{
index =>
let pointer = getGenericParameterInfo(_info, UInt32(index))
if (pointer.isNull()) {
throw InfoNotFoundException("Get parameters failed!")
}
GenericTypeInfo(pointer)
}
)
_genericParams = Some(params)
params
}
}
}
/**
* Returns the name of static function.
*/
public prop name: String {
get() {
_name.getOrThrow()
}
}
/**
* Returns the list of parameters of static function.
*/
public prop parameters: ReadOnlyList<ParameterInfo> {
get() {
match (_parameters) {
case Some(res) => res
case None =>
let infos = getParameters(_info)
_parameters = infos
infos
}
}
}
/**
* Returns the return type of static function.
*/
public prop returnType: TypeInfo {
get() {
match (_returnType) {
case Some(res) => res
case None =>
let pointer = getMethodReturnType(_info)
let info = TypeInfo.getOrCreate(pointer)
_returnType = info
info
}
}
}
/**
* Returns the collection of modifiers of static function.
*/
public prop modifiers: Collection<ModifierInfo> {
get() {
match (_modifiers) {
case Some(res) => res
case None =>
let infos = ModifierInfo.byMask(getMethodModifier(_info))
_modifiers = infos
infos
}
}
}
/**
* Returns the collection of annotations of static function.
*/
public prop annotations: Collection<Annotation> {
get() {
match (_annotations) {
case Some(res) => res
case None =>
let infos = match (getMethodAnnotations(_info, TypeInfo.of<Array<Object>>()._info)) {
case arr: Array<Annotation> => arr
case _ => Array<Annotation>()
}
_annotations = infos
infos
}
}
}
/**
* Makes a call of static function with incoming args.
*
* @param args parameter list.
*
* @throw IllegalArgumentException, if the number of input parameters is different from the number of invoked function parameters.
* @throw IllegalTypeException, if the input parameter type does not match the required parameter type.
*/
public func apply(thisType: TypeInfo, args: Array<Any>): Any {
try {
if (genericParams.size > 0) {
throw InvocationTargetException("The generic function cannot be applied without `genericTypeArgs`.")
}
} catch (_: InfoNotFoundException) {
throw InvocationTargetException("The generic function cannot be applied without `genericTypeArgs`.")
}
if (methodEntryPointIsNull(_info)) {
throw InfoNotFoundException("Failed to find the method entry.")
}
let name = TypeInfo.getOrCreate(_declaringTypeInfo).qualifiedName
if (thisType.qualifiedName != name) {
throw IllegalArgumentException("Wrong typeInfo, excepted ${thisType.qualifiedName} but ${name} got.")
}
checkArgsSizeAndType(parameters, args)
applyCJStaticMethod(_info, args, thisType._info)
}
public func apply(thisType: TypeInfo, genericTypeArgs: Array<TypeInfo>, args: Array<Any>): Any {
if (genericParams.size == 0) {
throw InvocationTargetException("The function cannot be applied with `genericTypeArgs`.")
}
if (methodEntryPointIsNull(_info)) {
throw InfoNotFoundException("Failed to find the method entry.")
}
let name = TypeInfo.getOrCreate(_declaringTypeInfo).qualifiedName
if (thisType.qualifiedName != name) {
throw IllegalArgumentException("Wrong typeInfo, excepted ${thisType.qualifiedName} but ${name} got.")
}
checkParamaterSize(genericParams, parameters.size, genericTypeArgs, args)
let gArgs = ArrayList<CPointer<Unit>>(Int64(genericTypeArgs.size)) {index => genericTypeArgs[index]._info}
if (!checkMethodActualArgs(_info, gArgs.toArray(), args)) {
throw IllegalTypeException(
"The input parameter does not match the type of the input parameter required by the function.")
}
applyCJGenericStaticMethod(_info, gArgs.toArray(), args, thisType._info)
}
/**
* Searches the static function's annotation by incoming name.
*/
public func findAnnotation<T>(): ?T where T <: Annotation {
findAnnotation<T>(annotations)
}
public func findAllAnnotations<T>(): Array<T> where T <: Annotation {
findAllAnnotations<T>(annotations)
}
public func getAllAnnotations(): Array<Annotation> {
annotations.toArray()
}
public operator func ==(other: StaticFunctionInfo): Bool {
this._info == other._info
}
public operator func !=(other: StaticFunctionInfo): Bool {
!(this == other)
}
public func hashCode(): Int64 {
this._info.toUIntNative().hashCode()
}
public func toString(): String {
let sb = StringBuilder()
for (m in modifiers) {
sb.append(m)
sb.append(" ")
}
sb.append("func ")
sb.append(name)
sb.append("(")
for (index in 0..parameters.size) {
sb.append(parameters[index])
if (index < parameters.size - 1) {
sb.append(", ")
}
}
sb.append("): ")
sb.append(returnType)
sb.toString()
}
}
/**
* Contains the reflective information about instance properties.
*/
public class InstancePropertyInfo <: Equatable<InstancePropertyInfo> & Hashable & ToString {
let _name: String
// must have value
var _getterInfo: Option<InstanceFunctionInfo> = None
var _setterInfo: Option<InstanceFunctionInfo> = None
var _typeInfo: Option<TypeInfo> = None
var _modifiers: Option<Collection<ModifierInfo>> = None
var _annotations: Option<Collection<Annotation>> = None
var _declaringTypeInfo: CPointer<Unit>
init(name: String, declaringTypeInfo: CPointer<Unit>) {
_name = name
_declaringTypeInfo = declaringTypeInfo
}
/**
* Returns the name of instance property.
*/
public prop name: String {
get() {
_name
}
}
/**
* Returns the return type of instance property.
*/
public prop typeInfo: TypeInfo {
get() {
match (_typeInfo) {
case Some(res) => res
case None =>
_typeInfo = _getterInfo?.returnType
_typeInfo.getOrThrow()
}
}
}
/**
* Returns the collection of modifiers of instance property.
*/
public prop modifiers: Collection<ModifierInfo> {
get() {
match (_modifiers) {
case Some(res) => res
case None =>
let infos = if (isMutable()) {
let array = ArrayList<ModifierInfo>((_getterInfo?.modifiers).getOrThrow())
array.add(ModifierInfo.Mut)
array.toArray()
} else {
(_getterInfo?.modifiers).getOrThrow()
}
_modifiers = infos
infos
}
}
}
/**
* Returns the collection of annotations of instance property.
*/
public prop annotations: Collection<Annotation> {
get() {
match (_annotations) {
case Some(res) => res
case None =>
let infos = match (getMethodAnnotations(_getterInfo.getOrThrow()._info,
TypeInfo.of<Array<Object>>()._info)) {
case arr: Array<Annotation> => arr
case _ => Array<Annotation>()
}
_annotations = infos
infos
}
}
}
/**
* Returns true if instance property is 'public', false otherwise.
*/
public func isOpen(): Bool {
containsModifier(modifiers, ModifierInfo.Open)
}
/**
* Returns true if instance property is 'abstract', false otherwise.
*/
public func isAbstract(): Bool {
containsModifier(modifiers, ModifierInfo.Abstract)
}
/**
* Returns true if instance property is 'mut'
*/
public func isMutable(): Bool {
_setterInfo.isSome()
}
/**
* Returns the instance property's value for incoming instance.
*/
public func getValue(instance: Any): Any {
if (isAbstract()) {
throw UnsupportedException("Abstract prop cannot get value.")
}
// instance type is checked in apply
if (let Some(v) <- _getterInfo) { // Getter must be implemented, no need to consider `None`
return v.apply(instance, Array<Any>())
}
}
/**
* Updates the instance property's value with incoming new value for incoming instance.
*/
public func setValue(instance: Any, newValue: Any): Unit {
if (isAbstract()) {
throw IllegalSetException("Attempt to modify abstract variable '${name}'")
}
if (!isMutable()) {
throw IllegalSetException("Attempt to modify immutable property '${name}'")
}
// instance type is checked in apply
match (_setterInfo) {
case Some(v) => v.apply(instance, Array<Any>(1, repeat: newValue))
case None => throw IllegalSetException("Attempt to modify immutable property '${name}'")
}
}
/**
* Searches the instance property's annotation by incoming name.
*/
public func findAnnotation<T>(): ?T where T <: Annotation {
findAnnotation<T>(annotations)
}
public func findAllAnnotations<T>(): Array<T> where T <: Annotation {
findAllAnnotations<T>(annotations)
}
public func getAllAnnotations(): Array<Annotation> {
annotations.toArray()
}
public operator func ==(other: InstancePropertyInfo): Bool {
this._getterInfo.getOrThrow()._info == other._getterInfo.getOrThrow()._info
}
public operator func !=(other: InstancePropertyInfo): Bool {
!(this == other)
}
public func hashCode(): Int64 {
this._getterInfo.getOrThrow()._info.toUIntNative().hashCode()
}
public func toString(): String {
let sb = StringBuilder()
for (m in modifiers) {
sb.append(m)
sb.append(" ")
}
sb.append("prop ")
sb.append(name)
sb.append(": ")
sb.append(typeInfo)
sb.toString()
}
func setFunc(isGetter: Bool, pointer: CPointer<Unit>) {
if (isGetter) {
_getterInfo = InstanceFunctionInfo(pointer, _declaringTypeInfo)
} else {
_setterInfo = InstanceFunctionInfo(pointer, _declaringTypeInfo)
}
}
}
/**
* Contains the reflective information about static properties.
*/
public class StaticPropertyInfo <: Equatable<StaticPropertyInfo> & Hashable & ToString {
let _name: String
// must have value
var _getterInfo: Option<StaticFunctionInfo> = None
var _setterInfo: Option<StaticFunctionInfo> = None
var _typeInfo: Option<TypeInfo> = None
var _modifiers: Option<Collection<ModifierInfo>> = None
var _annotations: Option<Collection<Annotation>> = None
var _declaringTypeInfo: CPointer<Unit>
init(name: String, declaringTypeInfo: CPointer<Unit>) {
_name = name
_declaringTypeInfo = declaringTypeInfo
}
/**
* Returns the name of static property.
*/
public prop name: String {
get() {
_name
}
}
/**
* Returns the return type of static property.
*/
public prop typeInfo: TypeInfo {
get() {
match (_typeInfo) {
case Some(res) => res
case None =>
_typeInfo = _getterInfo?.returnType
_typeInfo.getOrThrow()
}
}
}
/**
* Returns the collection of modifiers of static property.
*/
public prop modifiers: Collection<ModifierInfo> {
get() {
match (_modifiers) {
case Some(res) => res
case None =>
let infos = if (isMutable()) {
let array = ArrayList<ModifierInfo>((_getterInfo?.modifiers).getOrThrow())
array.add(ModifierInfo.Mut)
array.toArray()
} else {
(_getterInfo?.modifiers).getOrThrow()
}
_modifiers = infos
infos
}
}
}
/**
* Returns the collection of annotations of static property.
*/
public prop annotations: Collection<Annotation> {
get() {
match (_annotations) {
case Some(res) => res
case None =>
let infos = match (getMethodAnnotations(_getterInfo.getOrThrow()._info,
TypeInfo.of<Array<Object>>()._info)) {
case arr: Array<Annotation> => arr
case _ => Array<Annotation>()
}
_annotations = infos
infos
}
}
}
/**
* Returns true if static property is 'mut'
*/
public func isMutable(): Bool {
_setterInfo.isSome()
}
/**
* Returns the static property's value for incoming instance.
*/
public func getValue(): Any {
if (let Some(v) <- _getterInfo) { // getter must be implemented, no need to consider `None`
return v.apply(TypeInfo.getOrCreate(_declaringTypeInfo), Array<Any>())
}
}
/**
* Updates the static property's value with incoming new value for incoming instance.
*/
public func setValue(newValue: Any): Unit {
if (!isMutable()) {
throw IllegalSetException("Attempt to modify immutable property '${name}'")
}
match (_setterInfo) {
case Some(v) => v.apply(TypeInfo.getOrCreate(_declaringTypeInfo), Array<Any>(1, repeat: newValue))
case None => throw IllegalSetException("Attempt to modify immutable property '${name}'")
}
}
/**
* Searches the static property's annotation by incoming name.
*/
public func findAnnotation<T>(): ?T where T <: Annotation {
findAnnotation<T>(annotations)
}
public func findAllAnnotations<T>(): Array<T> where T <: Annotation {
findAllAnnotations<T>(annotations)
}
public func getAllAnnotations(): Array<Annotation> {
annotations.toArray()
}
public operator func ==(other: StaticPropertyInfo): Bool {
this._getterInfo.getOrThrow()._info == other._getterInfo.getOrThrow()._info
}
public operator func !=(other: StaticPropertyInfo): Bool {
!(this == other)
}
public func hashCode(): Int64 {
this._getterInfo.getOrThrow()._info.toUIntNative().hashCode()
}
public func toString(): String {
let sb = StringBuilder()
for (m in modifiers) {
sb.append(m)
sb.append(" ")
}
sb.append("prop ")
sb.append(name)
sb.append(": ")
sb.append(typeInfo)
sb.toString()
}
func setFunc(isGetter: Bool, pointer: CPointer<Unit>) {
if (isGetter) {
_getterInfo = StaticFunctionInfo(pointer, _declaringTypeInfo)
} else {
_setterInfo = StaticFunctionInfo(pointer, _declaringTypeInfo)
}
}
}
/**
* Contains the reflective information about constructors.
*/
public class ConstructorInfo <: Equatable<ConstructorInfo> & Hashable & ToString {
let _info: CPointer<Unit>
var _parameters: Option<ArrayList<ParameterInfo>> = None
var _annotations: Option<Collection<Annotation>> = None
private var _isAbstract: Option<Bool> = None
var _declaringTypeInfo: CPointer<Unit>
init(infoPointer: CPointer<Unit>, declaringTypeInfo: CPointer<Unit>) {
_info = infoPointer
_declaringTypeInfo = declaringTypeInfo
}
/**
* Returns the list of parameters of constructor.
*/
public prop parameters: ReadOnlyList<ParameterInfo> {
get() {
match (_parameters) {
case Some(res) => res
case None =>
let infos = getParameters(_info)
_parameters = infos
infos
}
}
}
/**
* Returns the collection of annotations of constructor.
*/
public prop annotations: Collection<Annotation> {
get() {
match (_annotations) {
case Some(res) => res
case None =>
let infos = match (getMethodAnnotations(_info, TypeInfo.of<Array<Object>>()._info)) {
case arr: Array<Annotation> => arr
case _ => Array<Annotation>()
}
_annotations = infos
infos
}
}
}
private prop isAbstract: Bool {
get() {
match (_isAbstract) {
case Some(res) => res
case None =>
let isDeclaringClassAbstract = ModifierInfo.isAbstract(getMethodModifier(_info)) ||
ModifierInfo.isAbstract(getTypeInfoModifier(_declaringTypeInfo))
_isAbstract = isDeclaringClassAbstract
isDeclaringClassAbstract
}
}
}
/**
* Makes a call of constructor with incoming args.
*
* @param args parameter list.
*
* @throw IllegalArgumentException, if the number of input parameters is different from the number of invoked function parameters.
* @throw IllegalTypeException, if the input parameter type does not match the required parameter type.
* @throw InvocationTargetException, if the constructor is abstract
*/
public func apply(args: Array<Any>): Any {
let nullEntryPointer = methodEntryPointIsNull(_info)
if (isAbstract || nullEntryPointer) {
throw InvocationTargetException("Abstract constructor cannot apply.")
}
checkArgsSizeAndType(parameters, args)
applyCJStaticMethod(_info, args, CPointer<Unit>())
}
/**
* Searches the constructor's annotation by incoming name.
*/
public func findAnnotation<T>(): ?T where T <: Annotation {
findAnnotation<T>(annotations)
}
public func findAllAnnotations<T>(): Array<T> where T <: Annotation {
findAllAnnotations<T>(annotations)
}
public func getAllAnnotations(): Array<Annotation> {
annotations.toArray()
}
public operator func ==(other: ConstructorInfo): Bool {
this._info == other._info
}
public operator func !=(other: ConstructorInfo): Bool {
!(this == other)
}
public func hashCode(): Int64 {
this._info.toUIntNative().hashCode()
}
public func toString(): String {
let sb = StringBuilder(constructorName)
sb.append("(")
for (index in 0..parameters.size) {
sb.append(parameters[index])
if (index < parameters.size - 1) {
sb.append(", ")
}
}
sb.append(")")
sb.toString()
}
}
/**
* Contains the reflective information about global functions.
*/
public class GlobalFunctionInfo <: Equatable<GlobalFunctionInfo> & Hashable & ToString {
let _info: CPointer<Unit>
var _name: ?String = None
var _parameters: Option<ArrayList<ParameterInfo>> = None
var _genericParams = Option<Collection<GenericTypeInfo>>.None
var _returnType: Option<TypeInfo> = None
var _annotations: Option<Collection<Annotation>> = None
init(cp: CPointer<Unit>) {
_info = cp
}
public prop genericParams: Collection<GenericTypeInfo> {
get() {
match (_genericParams) {
case Some(params) => params
case None =>
let genericParametersNum = getNumOfGenericParameters(_info)
if (genericParametersNum == 0) {
_genericParams = Option<Collection<GenericTypeInfo>>.None
return ArrayList<GenericTypeInfo>()
}
let params = ArrayList<GenericTypeInfo>(
Int64(genericParametersNum),
{
index =>
let pointer = getGenericParameterInfo(_info, UInt32(index))
if (pointer.isNull()) {
throw InfoNotFoundException("Get parameters failed!")
}
GenericTypeInfo(pointer)
}
)
_genericParams = Some(params)
params
}
}
}
// Function name, overloaded functions have the same function name
public prop name: String {
get() {
_name.getOrThrow()
}
}
/**
* Returns the list of parameters of global function.
*/
public prop parameters: ReadOnlyList<ParameterInfo> {
get() {
match (_parameters) {
case Some(res) => res
case None =>
let infos = getParameters(_info)
_parameters = infos
infos
}
}
}
/**
* Returns the return type of global function.
*/
public prop returnType: TypeInfo {
get() {
match (_returnType) {
case Some(res) => res
case None =>
let pointer = getMethodReturnType(_info)
let info = TypeInfo.getOrCreate(pointer)
_returnType = info
info
}
}
}
// Annotation, when there is no data, size is 0. Note that this api does not guarantee a constant traversal order.
public prop annotations: Collection<Annotation> {
get() {
match (_annotations) {
case Some(res) => res
case None =>
let infos = match (getMethodAnnotations(_info, TypeInfo.of<Array<Object>>()._info)) {
case arr: Array<Annotation> => arr
case _ => Array<Annotation>()
}
_annotations = infos
infos
}
}
}
/**
* Makes a call of global function with incoming args.
*
* @param args parameter list.
*
* @throw IllegalArgumentException, if the number of input parameters is different from the number of invoked function parameters.
* @throw IllegalTypeException, if the input parameter type does not match the required parameter type.
* @throw InvocationTargetException, if then generic parameter check failed.
*/
public func apply(args: Array<Any>): Any {
try {
if (genericParams.size > 0) {
throw InvocationTargetException("The generic function cannot be applied without `genericTypeArgs`.")
}
} catch (_: InfoNotFoundException) {
throw InvocationTargetException("The generic function cannot be applied without `genericTypeArgs`.")
}
checkArgsSizeAndType(parameters, args)
applyCJStaticMethod(_info, args, CPointer<Unit>())
}
public func apply(genericTypeArgs: Array<TypeInfo>, args: Array<Any>): Any {
if (genericParams.size == 0) {
throw InvocationTargetException("The function cannot be applied with `genericTypeArgs`.")
}
checkParamaterSize(genericParams, parameters.size, genericTypeArgs, args)
let gArgs = ArrayList<CPointer<Unit>>(Int64(genericTypeArgs.size)) {index => genericTypeArgs[index]._info}
if (!checkMethodActualArgs(_info, gArgs.toArray(), args)) {
throw IllegalTypeException(
"The input parameter does not match the type of the input parameter required by the function.")
}
applyCJGenericStaticMethod(_info, gArgs.toArray(), args, CPointer<Unit>())
}
// Get the annotation by name, return None if not found
public func findAnnotation<T>(): ?T where T <: Annotation {
findAnnotation<T>(annotations)
}
public func findAllAnnotations<T>(): Array<T> where T <: Annotation {
findAllAnnotations<T>(annotations)
}
public func getAllAnnotations(): Array<Annotation> {
annotations.toArray()
}
public operator func ==(other: GlobalFunctionInfo): Bool {
this._info == other._info
}
public operator func !=(other: GlobalFunctionInfo): Bool {
!(this == other)
}
public func hashCode(): Int64 {
this._info.toUIntNative().hashCode()
}
public func toString(): String {
let sb = StringBuilder()
sb.append("func ")
sb.append(name)
sb.append("(")
for (index in 0..parameters.size) {
sb.append(parameters[index])
if (index < parameters.size - 1) {
sb.append(", ")
}
}
sb.append("): ")
sb.append(returnType)
sb.toString()
}
}
func getFuncName(parentPointer: CPointer<Unit>): String {
let pointer = getMethodName(parentPointer)
if (pointer.isNull()) {
throw InfoNotFoundException("Get function name failed!")
}
CString(pointer).toString()
}
func getParameters(cp: CPointer<Unit>): ArrayList<ParameterInfo> {
let actualParametersNum = getNumOfActualParameters(cp)
ArrayList<ParameterInfo>(
Int64(actualParametersNum),
{
index =>
let pointer = getActualParameterInfo(cp, UInt32(index))
if (pointer.isNull()) {
throw InfoNotFoundException("Get parameters failed!")
}
ParameterInfo(pointer)
}
)
}
func checkMethodDeclaringClassType(instance: Any, declaringTypeInfo: CPointer<Unit>): Unit {
let declaringClassTypeInfo = TypeInfo.getOrCreate(declaringTypeInfo)
let instanceTypeInfo = TypeInfo.of(instance)
if (declaringClassTypeInfo != instanceTypeInfo) {
throw IllegalTypeException(
"The input instance should be \"${declaringClassTypeInfo}\", but now it`s \"${instanceTypeInfo}\"")
}
}
func checkParamaterSize(genericParams: Collection<GenericTypeInfo>, actualParamSize: Int64,
genericTypeParameters: Collection<TypeInfo>, args: Array<Any>): Unit {
if (genericTypeParameters.size != genericParams.size) {
throw IllegalArgumentException("The input generic parameter item does not comply with the required quantity.")
}
if (args.size != actualParamSize) {
throw IllegalArgumentException("The input parameter item does not comply with the required quantity.")
}
}