| /* |
| * 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 |
| import kotlin.reflect.KClass |
| |
| private fun String.shift(): String { |
| return this.split(END_LINE).joinToString(separator = END_LINE) { if (it.isEmpty()) it else " $it" } |
| } |
| |
| internal fun file(builtBy: KClass<*>, init: FileBuilder.() -> Unit): FileBuilder { |
| val file = FileBuilder(builtBy.qualifiedName!!) |
| 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 additionalComments: 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 (additionalComments != null) { |
| additionalComments!!.lines().forEach { line -> |
| appendLine("// $line") |
| } |
| } |
| |
| if (annotations.isNotEmpty()) { |
| appendLine(annotations.joinToString(separator = END_LINE) { "@$it" }) |
| } |
| } |
| |
| 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(private val builtBy: String) : PrimitiveBuilder { |
| private val suppresses: MutableList<String> = mutableListOf() |
| private val imports: MutableList<String> = mutableListOf() |
| private val fileComments: MutableList<String> = mutableListOf() |
| private val classes: MutableList<ClassBuilder> = mutableListOf() |
| |
| fun suppress(suppress: String) { |
| suppresses += suppress |
| } |
| |
| fun import(newImport: String) { |
| imports += newImport |
| } |
| |
| fun appendFileComment(doc: String) { |
| fileComments += doc |
| } |
| |
| 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("// Generated by $builtBy") |
| 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() |
| } |
| |
| if (fileComments.isNotEmpty()) { |
| appendLine(fileComments.joinToString(separator = END_LINE) { "// $it" }) |
| appendLine() |
| } |
| |
| append(classes.joinToString(separator = END_LINE) { it.build() }) |
| } |
| } |
| } |
| |
| internal class ClassBuilder : AnnotatedAndDocumented(), PrimitiveBuilder { |
| var name: String = "" |
| private var primaryConstructor: PrimaryConstructorBuilder = PrimaryConstructorBuilder() |
| private var secondaryConstructor: SecondaryConstructorBuilder? = null |
| private var superTypes: List<String> = emptyList() |
| private var companionObject: CompanionObjectBuilder? = null |
| |
| private var builders: MutableList<PrimitiveBuilder> = mutableListOf() |
| |
| fun primaryConstructor(init: PrimaryConstructorBuilder.() -> Unit) { |
| primaryConstructor = PrimaryConstructorBuilder().apply(init) |
| } |
| |
| fun secondaryConstructor(init: SecondaryConstructorBuilder.() -> Unit): SecondaryConstructorBuilder { |
| val secondaryConstructorBuilder = SecondaryConstructorBuilder() |
| secondaryConstructor = secondaryConstructorBuilder.apply(init) |
| return secondaryConstructorBuilder |
| } |
| |
| fun superType(type: String) { |
| superTypes += type |
| } |
| |
| fun companionObject(init: CompanionObjectBuilder.() -> Unit): CompanionObjectBuilder { |
| throwIfAlreadyInitialized(companionObject, "companionObject", "ClassBuilder") |
| val companionObjectBuilder = CompanionObjectBuilder() |
| companionObject = companionObjectBuilder.apply(init) |
| builders.add(companionObjectBuilder) |
| return companionObjectBuilder |
| } |
| |
| fun method(init: MethodBuilder.() -> Unit): MethodBuilder { |
| val methodBuilder = MethodBuilder() |
| builders.add(methodBuilder.apply(init)) |
| return methodBuilder |
| } |
| |
| override fun build(): String { |
| return buildString { |
| this.printDocumentationAndAnnotations() |
| |
| append("public ") |
| appendLine("class $name ${primaryConstructor.build()}: ${superTypes.joinToString()} {") |
| |
| secondaryConstructor?.let { |
| appendLine(it.build().shift()) |
| appendLine() |
| } |
| |
| appendLine(builders.joinToString(separator = END_LINE + END_LINE) { it.build().shift() }) |
| appendLine("}") |
| } |
| } |
| } |
| |
| internal class CompanionObjectBuilder : AnnotatedAndDocumented(), PrimitiveBuilder { |
| 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() |
| append("public ") |
| if (properties.isEmpty()) { |
| append("companion object {}") |
| } else { |
| appendLine("companion object {") |
| appendLine(properties.joinToString(separator = END_LINE + END_LINE) { it.build().shift() }) |
| append("}") |
| } |
| } |
| } |
| } |
| |
| internal class PrimaryConstructorBuilder : AnnotatedAndDocumented(), PrimitiveBuilder { |
| var visibility: MethodVisibility? = MethodVisibility.PRIVATE |
| private var parameters: MutableList<MethodParameterBuilder> = mutableListOf() |
| |
| fun parameter(init: MethodParameterBuilder.() -> Unit): MethodParameterBuilder { |
| val argBuilder = MethodParameterBuilder() |
| parameters.add(argBuilder.apply(init)) |
| return argBuilder |
| } |
| |
| override fun build(): String { |
| return buildString { |
| if (annotations.isNotEmpty()) appendLine() |
| printDocumentationAndAnnotations() |
| |
| visibility?.let { append("${it.name.lowercase()} ") } |
| append("constructor") |
| append(parameters.joinToString(prefix = "(", postfix = ") ") { it.build() }) |
| } |
| } |
| } |
| |
| internal class SecondaryConstructorBuilder : AnnotatedAndDocumented(), PrimitiveBuilder { |
| var visibility: MethodVisibility = MethodVisibility.PRIVATE |
| private var parameters: MutableList<MethodParameterBuilder> = mutableListOf() |
| private var argumentsToPrimaryContructor: MutableList<String> = mutableListOf() |
| |
| fun parameter(init: MethodParameterBuilder.() -> Unit): MethodParameterBuilder { |
| val argBuilder = MethodParameterBuilder() |
| parameters.add(argBuilder.apply(init)) |
| return argBuilder |
| } |
| |
| fun argument(arg: String) { |
| argumentsToPrimaryContructor += arg |
| } |
| |
| override fun build(): String { |
| return buildString { |
| printDocumentationAndAnnotations() |
| |
| append("${visibility.name.lowercase()} ") |
| append("constructor") |
| append(parameters.joinToString(prefix = "(", postfix = ") : ") { it.build() }) |
| append(argumentsToPrimaryContructor.joinToString(prefix = "this(", postfix = ")")) |
| } |
| } |
| } |
| |
| 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 { |
| append("${visibility.name.lowercase()} ") |
| if (isExternal) append("external ") |
| 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 noBody() { body = null } |
| |
| fun String.setAsExpressionBody() { |
| body = " =$END_LINE $this" |
| } |
| |
| fun String.setAsBlockBody() { |
| body = " {$END_LINE${this.shift()}$END_LINE}" |
| } |
| } |
| |
| internal class PropertyBuilder : AnnotatedAndDocumented(), PrimitiveBuilder { |
| var visibility: MethodVisibility? = MethodVisibility.PUBLIC |
| 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) |
| visibility?.let { append("${it.name.lowercase()} ") } |
| append("const val $name: $type = $value") |
| } |
| } |
| } |