/*
* 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.
*/
protected package std.deriving.impl
import std.deriving.api.*
import std.ast.*
import std.collection.*
extend Decl {
func generics(): Array<GenericDecl> {
if (!isGenericDecl) {
return []
}
return genericParam.parameters |> filter<Token> { t => t.kind == TokenKind.IDENTIFIER } |>
map<Token, GenericDecl> { it =>
GenericDecl(it)
} |> collectArray
}
/*
* Returns all named fields and property decls including constructor parameters
* and possibly static
*/
func allNamedDecls(): Iterator<Decl> {
match (this) {
case c: ClassDecl => c.allNamedDeclsImpl()
case c: StructDecl => c.allNamedDeclsImpl()
case en: EnumDecl => en.decls.iterator().filter { it => it is PropDecl }
case _ => Array<Decl>().iterator()
}
}
}
interface ClassLikeDecl {
mut prop body: Body
func allFields(): Array<TargetNamedAttribute> {
allNamedDeclsImpl().filter { member =>
match (member) {
case v: VarDecl where !v.isStatic() => true
case fp: FuncParam => true
case p: PropDecl where !p.isStatic() => true
case _ => false
}
}.map { member =>
match (member) {
case v: VarDecl => TargetNamedAttribute.FieldAttribute(v)
case fp: FuncParam => ConstructorFieldAttribute(fp)
case p: PropDecl => PropertyAttribute(p)
case _ => throw Exception()
}
} |> collectArray
}
func allNamedDeclsImpl(): Iterator<Decl> {
body.declsUnwrapped().iterator().flatMap { member: Decl =>
match (member) {
case ctor: PrimaryCtorDecl => unwrapParams(ctor)
case other where hasIdentifier(other) => [other].iterator()
case _ => Array<Decl>().iterator()
}
}
}
func allProperties(): Array<PropDecl> {
body.declsUnwrapped() |> filterIsInstance<Decl, PropDecl> |> collectArray
}
func allGenerics(): Array<GenericDecl>
}
private func unwrapParams(ctor: PrimaryCtorDecl): Iterator<Decl> {
ctor.funcParamsUnwrapped()
.filter { p => p.isMemberParam() }
.map { f => f }
}
private func hasIdentifier(decl: Decl): Bool {
let id = decl.identifier
id.kind == TokenKind.IDENTIFIER && !id.value.isEmpty()
}
extend ClassDecl <: ClassLikeDecl {
public func allGenerics(): Array<GenericDecl> {
generics()
}
}
extend StructDecl <: ClassLikeDecl {
public func allGenerics(): Array<GenericDecl> {
generics()
}
}
extend EnumDecl {
func allCases(): Array<TargetEnumCase> {
constructors |> map { ctor: Constructor =>
TargetEnumCase(ctor.identifier.value, ctor, argsToField(ctor.typeArguments))
} |> collectArray
}
func allProperties(): Array<PropDecl> {
declsUnwrapped() |> filterIsInstance<Decl, PropDecl> |> collectArray
}
private static func argsToField(args: Iterable<TypeNode>): Array<TargetEnumField> {
args |> enumerate |> map<(Int64, TypeNode), TargetEnumField> { pair =>
let (index, node) = pair
TargetEnumField(index, node)
} |> collectArray
}
}
func mapInterfaceSettings(
genericDecls: Array<GenericDecl>,
options: Array<DeriveInterfaceOption>,
logger: Logger
): Array<DerivingInterfaceSettings> {
options |> map { iface: DeriveInterfaceOption =>
let generics = iface.constraints |> mapNotNone { c: ParsedGenericConstraint =>
let decl = genericDecls.iterator().filter { it => it.identifier == c.genericParameter }.first()
match (decl) {
case Some(decl) => c.toDerivingGeneric(decl)
case None =>
logger.error(c.genericParameter.token, "Generic parameter not found")
Option<DerivingGenericSettings>.None
}
} |> collectArray
DerivingInterfaceSettings(iface.resolvedInterface, generics)
} |> collectArray
}