* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
capitalize,
ConfigTypeInfer,
CoreConfigurationSchema,
DefaultIDLLinterOptions,
generatorConfiguration,
IDLLinterOptions,
isDefined,
Language,
parseConfigFiles,
} from "@idlizer/core";
import { D } from "@idlizer/core";
const T = {
stringArray: () => D.array(D.string())
}
export const TransformOnSerializeSchema = D.object({
from: D.string(),
to: D.string(),
})
export const PeerGeneratorConfigurationSchema = D.combine(
CoreConfigurationSchema,
D.object({
GenerateUnused: D.boolean(),
ApiVersion: D.number(),
dumpSerialized: D.boolean(),
currentModulePackagesPaths: D.maybe(D.array(D.object({ package: D.string(), path: D.string() }))),
currentModuleExportedPackages: D.maybe(T.stringArray()),
cppPrefix: D.string(),
components: D.object({
ignoreComponents: T.stringArray(),
ignorePeerMethod: T.stringArray(),
invalidAttributes: T.stringArray(),
customNodeTypes: T.stringArray(),
ignoreEntry: T.stringArray(),
custom: T.stringArray(),
handWritten: T.stringArray(),
replaceThrowErrorReturn: T.stringArray(),
}),
dummy: D.object({
ignoreMethods: D.map(D.string(), T.stringArray())
}),
materialized: D.object({
ignoreReturnTypes: T.stringArray()
}),
serializer: D.object({
ignore: T.stringArray()
}),
constants: D.default(
D.map(D.string(), D.string()),
new Map()
),
patchMaterialized: D.default(
D.map(D.string(), D.map(D.string(), D.string())),
new Map()
),
transformAnnotations: D.default(
D.map(D.string(), D.string()),
new Map<string, string>()
),
transformOnSerialize: D.array(TransformOnSerializeSchema),
handwrittenDeserializers: T.stringArray(),
})
)
export type PeerGeneratorConfigurationType = ConfigTypeInfer<typeof PeerGeneratorConfigurationSchema>
export type PeerGeneratorConfiguration = PeerGeneratorConfigurationType & PeerGeneratorConfigurationExtension
export interface PeerGeneratorConfigurationExtension {
ignoreEntry(name: string, language: Language): boolean
isHandWritten(component: string): boolean
isResource(name: string | undefined): boolean
isShouldReplaceThrowingError(name: string): boolean
noDummyGeneration(component: string, method?: string): boolean
linter: IDLLinterOptions
}
export function expandPeerGeneratorConfiguration(data: PeerGeneratorConfigurationType): PeerGeneratorConfiguration {
const config = {
...data,
ignoreEntry(name: string, language: Language): boolean {
return this.components.ignoreEntry.includes(name)
},
isHandWritten(component: string): boolean {
return this.components.handWritten.concat(this.components.custom).includes(component)
},
isResource(name: string | undefined): boolean {
return name != undefined && this.forceResource.includes(name)
},
isShouldReplaceThrowingError(name: string): boolean {
for (const ignore of this.components.replaceThrowErrorReturn) {
if (name.endsWith(ignore)) return true
}
return false
},
noDummyGeneration(component: string, method?: string): boolean {
const ignoreMethods = this.dummy.ignoreMethods.get(component)
if (!isDefined(ignoreMethods)) return false
if (isWhole(ignoreMethods)) return true
if (method && ignoreMethods.includes(method)) return true
return false
},
linter: DefaultIDLLinterOptions
}
return config
}
function isWhole(methods: string[]): boolean {
return methods.includes("*")
}
export function loadPeerConfiguration(configurationFiles: string[]): PeerGeneratorConfiguration {
return expandPeerGeneratorConfiguration(parseConfigFiles(PeerGeneratorConfigurationSchema, configurationFiles))
}
export function peerGeneratorConfiguration(): PeerGeneratorConfiguration {
return generatorConfiguration<PeerGeneratorConfiguration>()
}
interface HookMethod {
hookName: string,
replaceImplementation: boolean
}
export function getHookMethod(className: string, methodName: string): HookMethod | undefined {
const hookMethods = peerGeneratorConfiguration().hooks.get(className)
if (!hookMethods) return undefined
const hook = hookMethods.get(methodName)
if (!hook) return undefined
const method: HookMethod = {
hookName: hook.hookName ?? `hook${className}${capitalize(methodName)}`,
replaceImplementation: hook.replaceImplementation ?? true
}
return method
}