Skip to content

Commit

Permalink
GetProjectSchema shows available software types
Browse files Browse the repository at this point in the history
  • Loading branch information
eskatos committed May 20, 2024
1 parent aa679a7 commit 38516f2
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import org.gradle.client.ui.theme.spacing

private const val LEFT_WEIGHT = 0.3f
private const val RIGHT_WEIGHT = 0.7f
private const val LEFT_WEIGHT = 0.2f
private const val RIGHT_WEIGHT = 0.8f

@Composable
fun TwoPanes(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package org.gradle.client.ui.connected.actions

import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.text.font.FontFamily
import org.gradle.declarative.dsl.schema.*
import org.gradle.declarative.dsl.tooling.models.DeclarativeSchemaModel

Expand All @@ -17,41 +19,108 @@ class GetProjectSchema : GetModelAction<DeclarativeSchemaModel> {
text = "Gradle Project Schema",
style = MaterialTheme.typography.titleMedium
)
Text(
text = "Schema: ${model.projectSchema.toHumanReadable()}",
style = MaterialTheme.typography.labelSmall
)
SelectionContainer {
Text(
text = "Available Software Types:\n${model.projectSchema.describeSoftwareTypes()}",
style = MaterialTheme.typography.labelSmall.copy(fontFamily = FontFamily.Monospace),
)
}
}

private fun AnalysisSchema.toHumanReadable(): String {
private fun AnalysisSchema.dataClassFor(typeRef: DataTypeRef.Name): DataClass =
dataClassesByFqName.getValue(typeRef.fqName)

private fun AnalysisSchema.describeSoftwareTypes(): String {
val memberFunctions = this.topLevelReceiverType.memberFunctions
return buildString {
memberFunctions.forEach {
memberFunctions.forEach { softwareType ->
appendLine()
appendDescription(this@describeSoftwareTypes, softwareType)
appendLine()
}
}
}

private val indentChars = " "

@Suppress("NestedBlockDepth")
private fun StringBuilder.appendDescription(
schema: AnalysisSchema,
function: SchemaMemberFunction,
indentLevel: Int = 0
) {
when (val functionSemantics = function.semantics) {

// Configuring blocks
is FunctionSemantics.AccessAndConfigure -> {
append(indentChars.repeat(indentLevel))
append(function.simpleName)
append(" {")
appendLine()
append("\t")
append(it.receiver.toHumanReadable())
append(".")
append(it.simpleName)
when (val blockType = functionSemantics.configuredType) {
is DataTypeRef.Name -> {
val blockDataClass = schema.dataClassFor(blockType)
blockDataClass.properties.forEach { property ->
val propTypeName = when (val propType = property.valueType) {
is DataTypeRef.Type -> propType.dataType.toString()
is DataTypeRef.Name -> propType.toHumanReadable()
}
append(indentChars.repeat(indentLevel + 1))
append("${property.name}: $propTypeName")
appendLine()
}
blockDataClass.memberFunctions.forEach { subBlock ->
appendDescription(schema, subBlock, indentLevel + 1)
appendLine()
}
}

is DataTypeRef.Type -> TODO("Block '${function.simpleName}' type is not a type ref")
}
append(indentChars.repeat(indentLevel))
append("}")
}

// Factory function
is FunctionSemantics.Pure -> {
append(indentChars.repeat(indentLevel + 1))
append(function.simpleName)
append("(")
append(it.parameters.joinToString {dp -> dp.toHumanReadable()})
append(function.parameters.joinToString { dp -> dp.toHumanReadable() })
append("): ")
append(function.returnValueType.toHumanReadable())
}

// Add and configure function
is FunctionSemantics.AddAndConfigure -> {
append(indentChars.repeat(indentLevel + 1))
append(function.simpleName)
append("(")
append(function.parameters.joinToString { dp -> dp.toHumanReadable() })
append(")")
append(" -> ")
append(it.returnValueType.toHumanReadable())
}

is FunctionSemantics.Builder -> {
append(indentChars.repeat(indentLevel + 1))
append("TODO Block '${function.simpleName}' is a Builder")
}
}
}

private fun DataTypeRef.toHumanReadable(): String =
when (this) {
is DataTypeRef.Name -> fqName.qualifiedName
is DataTypeRef.Name -> fqName.simpleName
is DataTypeRef.Type -> toHumanReadable()
}

is DataTypeRef.Type -> when (dataType) {
is DataType.NullType -> "null"
is DataType.UnitType -> "void"
is DataType.ConstantType<*> -> (dataType as DataType.ConstantType<*>).constantType.simpleName
is DataClass -> (dataType as DataClass).name.qualifiedName
}
private fun DataTypeRef.Type.toHumanReadable(): String =
when (val type = this.dataType) {
is DataType.NullType -> "null"
is DataType.UnitType -> Unit::class.simpleName!!
is DataType.ConstantType<*> -> type.toString()
is DataClass -> type.name.simpleName
}

private fun DataParameter.toHumanReadable(): String = type.toHumanReadable()
private fun DataParameter.toHumanReadable(): String =
type.toHumanReadable()
}

0 comments on commit 38516f2

Please sign in to comment.