302 lines
10 KiB
Kotlin
302 lines
10 KiB
Kotlin
/*
|
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
*/
|
|
|
|
package org.jetbrains.kotlin.generators.builtins.numbers.primitives
|
|
|
|
import java.io.File
|
|
|
|
private fun String.shift(): String {
|
|
return this.split(END_LINE).joinToString(separator = END_LINE) { if (it.isEmpty()) it else " $it" }
|
|
}
|
|
|
|
internal fun file(init: FileBuilder.() -> Unit): FileBuilder {
|
|
val file = FileBuilder()
|
|
file.init()
|
|
return file
|
|
}
|
|
|
|
internal interface PrimitiveBuilder {
|
|
fun build(): String
|
|
|
|
fun throwIfAlreadyInitialized(arg: Any?, propertyName: String, className: String) {
|
|
if (arg != null) {
|
|
throw AssertionError("Property '$propertyName' for '$className' was already initialized")
|
|
}
|
|
}
|
|
|
|
fun throwIfWasNotInitialized(arg: Any?, propertyName: String, className: String) {
|
|
if (arg == null) {
|
|
throw AssertionError("Property '$propertyName' for '$className' wasn't set to its value")
|
|
}
|
|
}
|
|
|
|
fun throwNotInitialized(propertyName: String, className: String): Nothing {
|
|
throw AssertionError("Property '$propertyName' for '$className' wasn't initialized to access")
|
|
}
|
|
}
|
|
|
|
internal abstract class AnnotatedAndDocumented {
|
|
private var doc: String? = null
|
|
val annotations: MutableList<String> = mutableListOf()
|
|
var additionalDoc: String? = null
|
|
|
|
fun appendDoc(doc: String) {
|
|
if (this.doc == null) {
|
|
this.doc = doc
|
|
} else {
|
|
this.doc += "$END_LINE$doc"
|
|
}
|
|
}
|
|
|
|
protected fun StringBuilder.printDocumentationAndAnnotations(forceMultiLineDoc: Boolean = false) {
|
|
if (doc != null) {
|
|
appendLine(doc!!.printAsDoc(forceMultiLineDoc))
|
|
}
|
|
|
|
if (annotations.isNotEmpty()) {
|
|
appendLine(annotations.joinToString(separator = END_LINE) { "@$it" })
|
|
}
|
|
|
|
if (additionalDoc != null) {
|
|
appendLine("// $additionalDoc")
|
|
}
|
|
}
|
|
|
|
private fun String.printAsDoc(forceMultiLine: Boolean = false): String {
|
|
if (this.contains(END_LINE) || forceMultiLine) {
|
|
return this.split(END_LINE).joinToString(
|
|
separator = END_LINE, prefix = "/**$END_LINE", postfix = "$END_LINE */"
|
|
) { if (it.isEmpty()) " *" else " * $it" }
|
|
}
|
|
return "/** $this */"
|
|
}
|
|
}
|
|
|
|
internal class FileBuilder : PrimitiveBuilder {
|
|
private val suppresses: MutableList<String> = mutableListOf()
|
|
private val imports: MutableList<String> = mutableListOf()
|
|
private val classes: MutableList<ClassBuilder> = mutableListOf()
|
|
|
|
fun suppress(suppress: String) {
|
|
suppresses += suppress
|
|
}
|
|
|
|
fun import(newImport: String) {
|
|
imports += newImport
|
|
}
|
|
|
|
fun klass(init: ClassBuilder.() -> Unit): ClassBuilder {
|
|
val classBuilder = ClassBuilder()
|
|
classes += classBuilder.apply(init)
|
|
return classBuilder
|
|
}
|
|
|
|
override fun build(): String {
|
|
return buildString {
|
|
appendLine(File("license/COPYRIGHT_HEADER.txt").readText())
|
|
appendLine()
|
|
appendLine("// Auto-generated file. DO NOT EDIT!")
|
|
appendLine()
|
|
|
|
if (suppresses.isNotEmpty()) {
|
|
appendLine(suppresses.joinToString(separator = ", ", prefix = "@file:Suppress(", postfix = ")") { "\"$it\"" })
|
|
appendLine()
|
|
}
|
|
|
|
appendLine("package kotlin")
|
|
appendLine()
|
|
|
|
if (imports.isNotEmpty()) {
|
|
appendLine(imports.joinToString(separator = END_LINE) { "import $it" })
|
|
appendLine()
|
|
}
|
|
|
|
append(classes.joinToString(separator = END_LINE) { it.build() })
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class ClassBuilder : AnnotatedAndDocumented(), PrimitiveBuilder {
|
|
var isFinal: Boolean = false
|
|
var name: String = ""
|
|
private var constructorParam: MethodParameterBuilder? = null
|
|
private var companionObject: CompanionObjectBuilder? = null
|
|
private val methods: MutableList<MethodBuilder> = mutableListOf()
|
|
|
|
fun constructorParam(init: MethodParameterBuilder.() -> Unit) {
|
|
throwIfAlreadyInitialized(constructorParam, "constructorParam", "ClassBuilder")
|
|
constructorParam = MethodParameterBuilder().apply(init)
|
|
}
|
|
|
|
fun companionObject(init: CompanionObjectBuilder.() -> Unit): CompanionObjectBuilder {
|
|
throwIfAlreadyInitialized(companionObject, "companionObject", "ClassBuilder")
|
|
val companionObjectBuilder = CompanionObjectBuilder()
|
|
companionObject = companionObjectBuilder.apply(init)
|
|
return companionObjectBuilder
|
|
}
|
|
|
|
fun method(init: MethodBuilder.() -> Unit): MethodBuilder {
|
|
val methodBuilder = MethodBuilder()
|
|
methods += methodBuilder.apply(init)
|
|
return methodBuilder
|
|
}
|
|
|
|
override fun build(): String {
|
|
return buildString {
|
|
this.printDocumentationAndAnnotations()
|
|
|
|
append("public ")
|
|
if (isFinal) append("final ")
|
|
appendLine("class $name private constructor(${constructorParam?.build() ?: ""}) : Number(), Comparable<$name> {")
|
|
|
|
companionObject?.let { appendLine(it.build().shift()) }
|
|
appendLine(methods.joinToString(separator = END_LINE + END_LINE) { it.build().shift() })
|
|
appendLine("}")
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class CompanionObjectBuilder : AnnotatedAndDocumented(), PrimitiveBuilder {
|
|
var isPublic: Boolean = false
|
|
private val properties: MutableList<PropertyBuilder> = mutableListOf()
|
|
|
|
fun property(init: PropertyBuilder.() -> Unit): PropertyBuilder {
|
|
val propertyBuilder = PropertyBuilder()
|
|
properties += propertyBuilder.apply(init)
|
|
return propertyBuilder
|
|
}
|
|
|
|
override fun build(): String {
|
|
return buildString {
|
|
printDocumentationAndAnnotations()
|
|
if (isPublic) append("public ")
|
|
appendLine("companion object {")
|
|
appendLine(properties.joinToString(separator = END_LINE + END_LINE) { it.build().shift() })
|
|
appendLine("}")
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class MethodSignatureBuilder : PrimitiveBuilder {
|
|
var isExternal: Boolean = false
|
|
var visibility: MethodVisibility = MethodVisibility.PUBLIC
|
|
var isOverride: Boolean = false
|
|
var isInline: Boolean = false
|
|
var isInfix: Boolean = false
|
|
var isOperator: Boolean = false
|
|
|
|
var methodName: String? = null
|
|
private var parameter: MethodParameterBuilder? = null
|
|
var returnType: String? = null
|
|
|
|
val parameterName: String
|
|
get() = parameter?.name ?: throwNotInitialized("name", "MethodParameterBuilder")
|
|
|
|
val parameterType: String
|
|
get() = parameter?.type ?: throwNotInitialized("type", "MethodParameterBuilder")
|
|
|
|
fun parameter(init: MethodParameterBuilder.() -> Unit): MethodParameterBuilder {
|
|
throwIfAlreadyInitialized(parameter, "parameter", "MethodSignatureBuilder")
|
|
val argBuilder = MethodParameterBuilder()
|
|
parameter = argBuilder.apply(init)
|
|
return argBuilder
|
|
}
|
|
|
|
override fun build(): String {
|
|
throwIfWasNotInitialized(methodName, "methodName", "MethodSignatureBuilder")
|
|
throwIfWasNotInitialized(returnType, "returnType", "MethodSignatureBuilder")
|
|
|
|
return buildString {
|
|
if (isExternal) append("external ")
|
|
append("${visibility.name.lowercase()} ")
|
|
if (isOverride) append("override ")
|
|
if (isInline) append("inline ")
|
|
if (isInfix) append("infix ")
|
|
if (isOperator) append("operator ")
|
|
append("fun $methodName(${parameter?.build() ?: ""}): $returnType")
|
|
}
|
|
}
|
|
}
|
|
|
|
internal enum class MethodVisibility {
|
|
PUBLIC, INTERNAL, PRIVATE
|
|
}
|
|
|
|
internal class MethodParameterBuilder : PrimitiveBuilder {
|
|
var name: String? = null
|
|
var type: String? = null
|
|
|
|
override fun build(): String {
|
|
throwIfWasNotInitialized(name, "name", "MethodParameterBuilder")
|
|
throwIfWasNotInitialized(type, "type", "MethodParameterBuilder")
|
|
return "$name: $type"
|
|
}
|
|
}
|
|
|
|
internal class MethodBuilder : AnnotatedAndDocumented(), PrimitiveBuilder {
|
|
private var signature: MethodSignatureBuilder? = null
|
|
private var body: String? = null
|
|
|
|
val methodName: String
|
|
get() = signature?.methodName ?: throwNotInitialized("methodName", "MethodSignatureBuilder")
|
|
|
|
val returnType: String
|
|
get() = signature?.returnType ?: throwNotInitialized("returnType", "MethodSignatureBuilder")
|
|
|
|
val parameterName: String
|
|
get() = signature?.parameterName ?: throwNotInitialized("name", "MethodParameterBuilder")
|
|
|
|
val parameterType: String
|
|
get() = signature?.parameterType ?: throwNotInitialized("type", "MethodParameterBuilder")
|
|
|
|
fun signature(init: MethodSignatureBuilder.() -> Unit): MethodSignatureBuilder {
|
|
throwIfAlreadyInitialized(signature, "signature", "MethodBuilder")
|
|
val signatureBuilder = MethodSignatureBuilder()
|
|
signature = signatureBuilder.apply(init)
|
|
return signatureBuilder
|
|
}
|
|
|
|
fun modifySignature(modify: MethodSignatureBuilder.() -> Unit) {
|
|
throwIfWasNotInitialized(signature, "signature", "MethodBuilder")
|
|
signature!!.apply(modify)
|
|
}
|
|
|
|
override fun build(): String {
|
|
throwIfWasNotInitialized(signature, "signature", "MethodBuilder")
|
|
|
|
return buildString {
|
|
printDocumentationAndAnnotations()
|
|
append(signature!!.build())
|
|
append(body ?: "")
|
|
}
|
|
}
|
|
|
|
fun String.addAsSingleLineBody(bodyOnNewLine: Boolean = false) {
|
|
val skip = if (bodyOnNewLine) "$END_LINE " else " "
|
|
body = " =$skip$this"
|
|
}
|
|
|
|
fun String.addAsMultiLineBody() {
|
|
body = " {$END_LINE${this.shift()}$END_LINE}"
|
|
}
|
|
}
|
|
|
|
internal class PropertyBuilder : AnnotatedAndDocumented(), PrimitiveBuilder {
|
|
var name: String? = null
|
|
var type: String? = null
|
|
var value: String? = null
|
|
|
|
override fun build(): String {
|
|
throwIfWasNotInitialized(name, "name", "PropertyBuilder")
|
|
throwIfWasNotInitialized(type, "type", "PropertyBuilder")
|
|
throwIfWasNotInitialized(value, "value", "PropertyBuilder")
|
|
|
|
return buildString {
|
|
printDocumentationAndAnnotations(forceMultiLineDoc = true)
|
|
append("public const val $name: $type = $value")
|
|
}
|
|
}
|
|
}
|