Skip to content
This repository was archived by the owner on Jan 19, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package com.larsreimann.api_editor.codegen
import com.larsreimann.api_editor.model.ComparisonOperator
import com.larsreimann.api_editor.model.PythonParameterAssignment
import com.larsreimann.api_editor.mutable_model.MutablePythonClass
import com.larsreimann.api_editor.mutable_model.MutablePythonConstructor
import com.larsreimann.api_editor.mutable_model.MutablePythonFunction
import com.larsreimann.api_editor.mutable_model.MutablePythonModule
import com.larsreimann.api_editor.mutable_model.MutablePythonParameter
import com.larsreimann.api_editor.mutable_model.OriginalPythonParameter

/**
* Builds a string containing the formatted module content
Expand Down Expand Up @@ -117,6 +119,7 @@ private fun MutablePythonClass.buildConstructor(): String {
constructorSeparator = "\n"
}
var constructorSuffix = constructorSeparator + assignments
constructorSuffix += this.constructor?.buildConstructorCall() ?: ""
if (constructorSuffix.isBlank()) {
constructorSuffix = "pass"
}
Expand All @@ -126,16 +129,25 @@ private fun MutablePythonClass.buildConstructor(): String {
""".trimMargin()
}

private fun MutablePythonConstructor.buildConstructorCall(): String {
return "self.instance = ${callToOriginalAPI!!.qualifiedName}(${this.buildParameterCall()})"
}

/**
* Builds a string containing the formatted function content
* @receiver The function whose adapter content should be built
* @return The string containing the formatted function content
*/
fun MutablePythonFunction.toPythonCode(): String {
return """
val function = """
|def $name(${buildParameters(this.parameters)}):
|${(buildFunctionBody(this)).prependIndent(" ")}
""".trimMargin()

return when {
isStaticMethod() -> "@staticmethod\n$function"
else -> function
}
}

private fun buildAttributeAssignments(pythonClass: MutablePythonClass): List<String> {
Expand Down Expand Up @@ -204,11 +216,23 @@ private fun buildFunctionBody(pythonFunction: MutablePythonFunction): String {
if (formattedBoundaries.isNotBlank()) {
formattedBoundaries = "$formattedBoundaries\n"
}

if (!pythonFunction.isMethod() || pythonFunction.isStaticMethod()) {
return (
formattedBoundaries +
pythonFunction.originalFunction!!.qualifiedName +
"(" +
pythonFunction.buildParameterCall() +
")"
)
}

return (
formattedBoundaries +
pythonFunction.originalFunction!!.qualifiedName +
"self.instance." +
pythonFunction.originalFunction!!.qualifiedName.split(".").last() +
"(" +
buildParameterCall(pythonFunction) +
pythonFunction.buildParameterCall() +
")"
)
}
Expand Down Expand Up @@ -297,10 +321,28 @@ private fun buildBoundaryChecks(pythonFunction: MutablePythonFunction): List<Str
return formattedBoundaries
}

private fun buildParameterCall(pythonFunction: MutablePythonFunction): String {
private fun MutablePythonFunction.buildParameterCall(): String {
return buildParameterCall(
parameters,
originalFunction!!.parameters
)
}

private fun MutablePythonConstructor.buildParameterCall(): String {
return buildParameterCall(
parameters,
callToOriginalAPI!!.parameters
)
}

private fun buildParameterCall(
parameters: List<MutablePythonParameter>,
originalParameters: List<OriginalPythonParameter>
): String {

val formattedParameters: MutableList<String?> = ArrayList()
val originalNameToValueMap: MutableMap<String, String?> = HashMap()
pythonFunction.parameters.forEach {
parameters.forEach {
val value: String? =
if (it.assignedBy == PythonParameterAssignment.CONSTANT || it.assignedBy == PythonParameterAssignment.ATTRIBUTE) {
it.defaultValue
Expand All @@ -309,7 +351,7 @@ private fun buildParameterCall(pythonFunction: MutablePythonFunction): String {
}
originalNameToValueMap[it.originalParameter!!.name] = value
}
pythonFunction.originalFunction!!.parameters
originalParameters
.filter { it.assignedBy != PythonParameterAssignment.IMPLICIT }
.forEach {
if (it.assignedBy === PythonParameterAssignment.NAME_ONLY) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ internal fun MutablePythonFunction.toSmlFunction(): SmlFunction {

return createSmlFunction(
name = stubName,
isStatic = isStaticMethod(),
annotations = buildList {
if (isPure) {
add(createSmlAnnotationUse("Pure"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,11 @@ open class Node {
}
}

operator fun getValue(node: Node, property: KProperty<*>): T? {
operator fun getValue(thisRef: Any?, property: KProperty<*>): T? {
return this.node
}

operator fun setValue(oldNode: Node, property: KProperty<*>, newNode: T?) {
operator fun setValue(thisRef: Any?, property: KProperty<*>, newNode: T?) {
this.node = newNode
}
}
Expand Down Expand Up @@ -382,11 +382,11 @@ open class Node {
handleMove(from, to)
}

operator fun getValue(node: T, property: KProperty<*>): T? {
operator fun getValue(thisRef: Any?, property: KProperty<*>): T? {
return this.node
}

operator fun setValue(oldNode: T, property: KProperty<*>, newNode: T?) {
operator fun setValue(thisRef: Any?, property: KProperty<*>, newNode: T?) {
this.node = newNode
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ class MutablePythonClass(
}

class MutablePythonConstructor(
parameters: List<MutablePythonParameter> = emptyList()
parameters: List<MutablePythonParameter> = emptyList(),
val callToOriginalAPI: OriginalPythonFunction? = null
) : MutablePythonAstNode() {

val parameters = MutableContainmentList(parameters)
Expand Down Expand Up @@ -141,7 +142,8 @@ class MutablePythonFunction(
yieldAll(results)
}

fun isStatic() = "staticmethod" in decorators
fun isMethod() = parent is MutablePythonClass
fun isStaticMethod() = isMethod() && "staticmethod" in decorators
}

data class OriginalPythonFunction(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.larsreimann.api_editor.mutable_model.MutablePythonClass
import com.larsreimann.api_editor.mutable_model.MutablePythonConstructor
import com.larsreimann.api_editor.mutable_model.MutablePythonFunction
import com.larsreimann.api_editor.mutable_model.MutablePythonPackage
import com.larsreimann.api_editor.mutable_model.OriginalPythonFunction
import com.larsreimann.api_editor.mutable_model.descendants

/**
Expand Down Expand Up @@ -51,12 +52,36 @@ fun MutablePythonPackage.createConstructors() {
}

private fun MutablePythonClass.createConstructor() {
this.constructor = MutablePythonConstructor()
when (val constructorMethod = this.methods.firstOrNull { it.name == "__init__" }) {
null -> {
this.constructor = MutablePythonConstructor(
parameters = emptyList(),
callToOriginalAPI = OriginalPythonFunction(
qualifiedName = this.qualifiedName()
)
)
}
else -> {
val qualifiedName = constructorMethod.originalFunction
?.qualifiedName
?.removeSuffix(".__init__")
?: qualifiedName()

val constructorMethod = this.methods.firstOrNull { it.name == "__init__" } ?: return
val parameters = constructorMethod.originalFunction
?.parameters
?: emptyList()

this.constructor?.parameters?.addAll(constructorMethod.parameters.toList())
constructorMethod.release()
this.constructor = MutablePythonConstructor(
parameters = constructorMethod.parameters.toList(),
callToOriginalAPI = OriginalPythonFunction(
qualifiedName = qualifiedName,
parameters = parameters
)
)

constructorMethod.release()
}
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,18 @@ private fun MutablePythonParameter.updateParameterAssignment() {
private fun MutablePythonParameter.isImplicit(): Boolean {
val currentFunction = this.parent as? MutablePythonFunction ?: return false
return currentFunction.parent is MutablePythonClass &&
!currentFunction.isStatic() &&
!currentFunction.isStaticMethod() &&
currentFunction.parameters.firstOrNull() == this
}

/**
* Changes the name of implicit parameters to "self".
*/
fun MutablePythonPackage.normalizeNamesOfImplicitParameters() {
this.descendants()
.filterIsInstance<MutablePythonParameter>()
.filter { it.assignedBy == PythonParameterAssignment.IMPLICIT }
.forEach {
it.name = "self"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ private fun MutablePythonPackage.preprocess() {
changeModulePrefix(newPrefix = "simpleml")
replaceClassMethodsWithStaticMethods()
updateParameterAssignment()
normalizeNamesOfImplicitParameters()
}

/**
Expand All @@ -40,5 +41,6 @@ private fun MutablePythonPackage.processAnnotations() {
private fun MutablePythonPackage.postprocess() {
removeEmptyModules()
reorderParameters()
createConstructors()
createAttributesForParametersOfConstructor()
}
Loading