import * as idl from "@idlizer/core/idl"
import { currentModule, mapLibraryName, isInCurrentModule, isInExternalModule, isInIdlize, Language, LayoutManagerStrategy, LayoutNodeRole, LayoutTargetDescription, PeerLibrary, getSyntheticTypesFileName } from "@idlizer/core"
import { peerGeneratorConfiguration } from "@idlizer/libohos"
function selectInternalsPath(): string {
return currentModule().name + ".INTERNAL"
}
function selectInteropPath(): string {
return "@koalaui/interop"
}
function canCropCurrentModulePrefix(): boolean {
const module = currentModule()
return module.packages.every(it => it.startsWith(module.name))
}
function cropCurrentModulePrefix(fqname: string): string {
if (!canCropCurrentModulePrefix())
throw new Error("Can not crop prefix for current module")
const prefix = currentModule().name
if (fqname == prefix)
return fqname.split('.').at(-1)!
return fqname.slice(prefix.length + 1)
}
export function HandwrittenModule(language: Language): string {
switch (language) {
case Language.TS: return "./handwritten"
case Language.ARKTS: return "./handwritten"
case Language.KOTLIN: return "handwritten"
default: throw new Error("Not implemented")
}
}
function getLibraryName(node: idl.IDLEntry, lang: Language, prefix: string = "@") {
const conf = peerGeneratorConfiguration()
return mapLibraryName(node, lang, conf?.libraryNameMapping, prefix)
}
export class OhosTsLayout implements LayoutManagerStrategy {
constructor(
protected library: PeerLibrary
) { }
handwrittenPackage(): string {
return "#handwritten"
}
protected readonly interopObjects = [
'SerializerBase',
'DeserializerBase',
'Finalizable',
'resourceFinalizerRegister'
]
protected selectInterface(node: idl.IDLEntry): string {
if (idl.isInIdlize(node)) {
if (this.interopObjects.includes(node.name)) {
return selectInteropPath()
}
return selectInternalsPath()
}
if (idl.isHandwritten(node)) {
return HandwrittenModule(this.library.language)
}
if (isInCurrentModule(node)) {
if (canCropCurrentModulePrefix()) {
const cropped = cropCurrentModulePrefix(idl.getPackageName(node))
return currentModule().useFoldersLayout
? cropped.split('.').join("/") || 'synthetic'
: cropped
}
return currentModule().useFoldersLayout
? idl.getPackageClause(node).join("/") || 'synthetic'
: "@" + idl.getPackageName(node)
}
return getLibraryName(node, this.library.language)
}
protected selectPeer(node:idl.IDLEntry): string {
return this.selectInterface(node)
}
protected selectGlobal(node:idl.IDLEntry): string {
if (!idl.getPackageNameSafe(node))
return selectInternalsPath()
return this.selectInterface(node)
}
protected selectSerializer(node:idl.IDLEntry): string {
if (isInExternalModule(node)) {
return selectInternalsPath()
}
return this.selectInterface(node)
}
resolve({ role, node }: LayoutTargetDescription): string {
switch (role) {
case LayoutNodeRole.SERIALIZER: return this.selectSerializer(node)
case LayoutNodeRole.INTERFACE: return this.selectInterface(node)
case LayoutNodeRole.PEER: return this.selectPeer(node)
case LayoutNodeRole.GLOBAL: return this.selectGlobal(node)
case LayoutNodeRole.COMPONENT: return ''
case LayoutNodeRole.MODIFIER_FUNCTIONS: return ''
}
}
}
export class OhosKotlinLayout implements LayoutManagerStrategy {
constructor(
protected library: PeerLibrary
) { }
handwrittenPackage(): string {
return "handwritten"
}
protected readonly interopObjects = [
"SerializerBase",
"DeserializerBase",
"Finalizable",
"resourceFinalizerRegister"
]
private selectInteropPath() {
return "koalaui.interop"
}
protected selectInterface(node: idl.IDLEntry): string {
const packageName = idl.getPackageNameSafe(node)
const arkuiPackages = ["arkui.component"]
if (packageName) {
for (const pkg of arkuiPackages) {
if (packageName === pkg || packageName.startsWith(`${pkg}.`)) {
return "koalaui.arkoala"
}
}
}
if (isInIdlize(node)) {
if (this.interopObjects.includes(node.name)) {
return this.selectInteropPath()
}
return selectInternalsPath()
}
if (idl.isHandwritten(node)) {
return HandwrittenModule(this.library.language)
}
if (this.isSyntheticType(node)) {
return getSyntheticTypesFileName()
}
if (isInCurrentModule(node)) {
return currentModule().useFoldersLayout
? idl.getPackageClause(node).join(".") || getSyntheticTypesFileName()
: idl.getPackageName(node)
}
const conf = peerGeneratorConfiguration()
return mapLibraryName(node, this.library.language, conf?.libraryNameMapping, "")
}
protected selectPeer(node:idl.IDLEntry): string {
return this.selectInterface(node)
}
protected selectGlobal(node:idl.IDLEntry): string {
if (!idl.getPackageNameSafe(node))
return selectInternalsPath()
return this.selectInterface(node)
}
protected selectSerializer(node:idl.IDLEntry): string {
if (isInExternalModule(node)) {
return selectInternalsPath()
}
return this.selectInterface(node)
}
resolve({ role, node }: LayoutTargetDescription): string {
switch (role) {
case LayoutNodeRole.SERIALIZER: return this.selectSerializer(node)
case LayoutNodeRole.INTERFACE: return this.selectInterface(node)
case LayoutNodeRole.PEER: return this.selectPeer(node)
case LayoutNodeRole.GLOBAL: return this.selectGlobal(node)
case LayoutNodeRole.COMPONENT: return ''
case LayoutNodeRole.MODIFIER_FUNCTIONS: return ''
}
}
private isSyntheticType(node: idl.IDLEntry): boolean {
if (idl.isSyntheticEntry(node) && idl.isInterface(node) && node.subkind === idl.IDLInterfaceSubkind.Tuple) {
return true
}
return false
}
}
export function ohosLayout(library: PeerLibrary): LayoutManagerStrategy {
switch(library.language) {
case Language.TS:
case Language.ARKTS:
case Language.CJ:
return new OhosTsLayout(library)
case Language.KOTLIN:
return new OhosKotlinLayout(library)
default: throw new Error(`Ohos layout for language ${library.language.name} is not implemented`)
}
}