fun generateKotlinDeclarations()

in build-logic/generatorlegacybuild/src/main/kotlin/karakum/browser/Generator.kt [336:591]


fun generateKotlinDeclarations(
    idlDir: File,
    eventsSourceFile: File,
    definitionsDir: File,
    webDefinitionsFile: File,
    webworkerDefinitionsFile: File,
    serviceworkerDefinitionsFile: File,
    audioWorkletDefinitionsFile: File,
    sourceDir: File,
) {
    IDLRegistry.rootDirectory = idlDir
    EventDataRegistry.sourceFile = eventsSourceFile

    val webDefinitionsParts = webDefinitionsFile.parts()
    val webworkerDefinitionsParts = webworkerDefinitionsFile.parts()
    val serviceworkerDefinitionsParts = serviceworkerDefinitionsFile.parts()
    val audioWorkletDefinitionsParts = audioWorkletDefinitionsFile.parts()

    IterableRegistry.fill(
        definitionsDir,
        webDefinitionsParts.second,
        WEB_GPU_ITERABLE_CONTENT,
        webworkerDefinitionsParts.second,
        serviceworkerDefinitionsParts.second,
    )

    val webDefinitionsContent = webDefinitionsParts.first
        .plus(WEB_GPU_CONTENT)
        .withTrustedTypes()

    MarkerRegistry.fill(webDefinitionsContent)
    RenderingContextRegistry.fill(webDefinitionsContent)

    val content = webDefinitionsContent.applyPatches()

    val webglTargetDir = sourceDir
        .resolve("web/gl")
        .also { it.mkdirs() }

    val webWorkerContent = webWorkerContent(webworkerDefinitionsParts.first)
    val serviceWorkerContent = serviceWorkerContent(serviceworkerDefinitionsParts.first)
    val (mainEventDeclarations, knownEventTypes) = eventDeclarations(content, webWorkerContent, serviceWorkerContent)
    val eventDeclarations = mainEventDeclarations +
            webWorkersEventDeclarations(webWorkerContent) +
            serviceWorkersEventDeclarations(content, serviceWorkerContent)

    for ((name, body, optPkg) in eventDeclarations) {
        val pkg = optPkg ?: EVENT_INFO_MAP.getValue(name.substringBefore("."))
            .fqn
            .substringBeforeLast(".")

        val targetDir = sourceDir
            .resolve(pkg.replace(".", "/"))
            .also { it.mkdirs() }

        targetDir.resolve("$name.kt")
            .also { check(!it.exists()) { "Duplicated file: ${it.name}" } }
            .writeCode(fileContent(body = body, pkg = pkg))
    }

    val aliases = listOf<ConversionResult>()
        .plus(htmlFactories(content))
        .plus(htmlDeclarations(content))
        .plus(htmlUnions())
        .plus(jsUnions())
        .plus(browserConstants(content))
        .plus(browserTypes(content))
        .plus(browserFunctions(content))
        .plus(browserFunctionTypes(content))
        .plus(cssObject(content))
        .plus(keyboardTypes())
        .plus(mouseButtonTypes())
        .plus(windowTypes())
        .plus(tagNames(content))
        .plus(decoratorsDeclarations(definitionsDir))
        .plus(dateDeclarations(definitionsDir))
        .plus(intlDeclarations(definitionsDir))
        .plus(atomicsDeclarations(definitionsDir))
        .plus(webAssemblyDeclarations(content))
        .plus(webWorkersDeclarations(webworkerDefinitionsParts.first))
        .plus(serviceWorkersDeclarations(serviceworkerDefinitionsParts.first))
        .plus(workerFunctions(serviceWorkerContent))
        .plus(audioWorkletDeclarations(audioWorkletDefinitionsParts.first))
        .withEventInstances(knownEventTypes)

    for ((name, body, pkg) in aliases) {
        pkg!!

        val suppresses = buildSet<Suppress> {
            if (name == "Locale")
                add(VIRTUAL_MEMBER_HIDDEN)

            if (Mixins.isUnsafeMixin(name, body) || name == LOCALIZABLE)
                add(NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE)

            if (name == "ChildNode"
                || name == "ParentNode"
                || name == "AbstractWorker"
                || name == "MessageEventTarget"
                || name == "GlobalEventHandlers"
                || name == "WindowEventHandlers"
            )
                add(INTERFACE_WITH_SUPERCLASS)

            if ("companion object" in body && "sealed external interface" in body)
                add(NESTED_CLASS_IN_EXTERNAL_INTERFACE)
        }.toTypedArray()

        val annotations = if (suppresses.isNotEmpty()) {
            fileSuppress(*suppresses)
        } else ""

        val imports = when (name) {
            "setInterval",
            "setTimeout",
                -> """
            import kotlin.time.Duration
            import kotlin.time.DurationUnit.MILLISECONDS
            """.trimIndent()

            "Navigator" -> """
            import web.mediadevices.MediaDevices
            import web.mediakey.MediaKeySystemAccess
            import web.mediakey.MediaKeySystemConfiguration
            import web.clipboard.Clipboard
            import web.credentials.CredentialsContainer
            import web.geolocation.Geolocation
            import web.gamepad.Gamepad
            import web.midi.MIDIOptions
            import web.midi.MIDIAccess
            import web.useractivation.UserActivation
            import web.wakelock.WakeLock
            """.trimIndent()

            "CredentialCreationOptions",
            "CredentialRequestOptions",
                -> """
            import web.authn.PublicKeyCredentialCreationOptions
            import web.authn.PublicKeyCredentialRequestOptions
            """.trimIndent()

            "DigitalCredential",
            "PublicKeyCredential",
                -> """
            import web.credentials.Credential
            """.trimIndent()

            "GlobalEventHandlers",
            "WindowEventHandlers",
            "FileReader",
                -> """
            import web.cssom.TransitionEvent
            import web.animations.AnimationEvent
            import web.clipboard.ClipboardEvent
            import web.csp.SecurityPolicyViolationEvent
            import web.gamepad.GamepadEvent
            import web.history.HashChangeEvent
            import web.history.PageTransitionEvent
            import web.history.PopStateEvent
            import web.storage.StorageEvent
            import web.promise.PromiseRejectionEvent
            """.trimIndent()

            "WorkerNavigator",
                -> """
            import web.navigator.*
            """.trimIndent()

            // TEMP
            "Window",
            "Document",
            "DocumentOrShadowRoot",
            "Text",
            "Element",
            "HTMLElement",
            "SVGElement",
            "OffscreenCanvas",
            "HTMLCanvasElement",
            "HTMLDetailsElement",
            "HTMLMediaElement",
            "HTMLFormElement",
            "HTMLInputElement",
            "HTMLSelectElement",
            "HTMLTextAreaElement",
            "HTMLTrackElement",
            "HTMLButtonElement",
            "MathMLElement",
            "WorkerGlobalScope",
            "ServiceWorkerGlobalScope",
            "DedicatedWorkerGlobalScope",
                -> """
            import web.cssom.ContentVisibilityAutoStateChangeEvent
            import web.cssom.TransitionEvent
            import web.popover.ToggleEvent
            import web.dom.*
            import web.window.*
            import web.animations.AnimationEvent
            import web.gl.WebGLContextEvent
            import web.clipboard.ClipboardEvent
            import web.csp.SecurityPolicyViolationEvent
            import web.device.DeviceMotionEvent
            import web.device.DeviceOrientationEvent
            import web.gamepad.GamepadEvent
            import web.history.HashChangeEvent
            import web.history.PageTransitionEvent
            import web.history.PopStateEvent
            import web.storage.StorageEvent
            import web.promise.PromiseRejectionEvent
            import web.push.PushEvent
            import web.rtc.RTCTransformEvent
            import web.cssom.StyleSheetList
            import web.fonts.FontFaceSource
            import web.html.*
            import web.xpath.XPathEvaluatorBase
            import web.workers.WorkerGlobalScope
            """.trimIndent()

            "VisualViewport.events",
                -> """
            import web.dom.*
            """.trimIndent()

            else -> ""
        }

        val targetDir = sourceDir
            .resolve(pkg.replace(".", "/"))
            .also { it.mkdirs() }

        targetDir.resolve("$name.kt")
            .also { check(!it.exists()) { "Duplicated file: ${it.name}" } }
            .writeCode(
                fileContent(
                    annotations = annotations,
                    imports = imports,
                    body = toCommonBody(body),
                    pkg = pkg,
                )
            )
    }

    for ((name, body) in webglDeclarations(content)) {
        val suppresses = buildSet<Suppress> {
            if ("companion object" in body && "sealed external interface" in body)
                add(NESTED_CLASS_IN_EXTERNAL_INTERFACE)
        }.toTypedArray()

        val annotations = if (suppresses.isNotEmpty()) {
            fileSuppress(*suppresses)
        } else ""

        webglTargetDir.resolve("$name.kt")
            .also { check(!it.exists()) { "Duplicated file: ${it.name}" } }
            .writeCode(fileContent(annotations, "", toCommonBody(body), "web.gl"))
    }
}