Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement obtaining of the resolved DOM #5

Merged
merged 2 commits into from
May 17, 2024
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
14 changes: 14 additions & 0 deletions build-action/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
plugins {
java
}

dependencies {
implementation(libs.gradle.tooling.api)
implementation(libs.gradle.declarative.dsl.tooling.models)
}

java {
toolchain {
languageVersion = JavaLanguageVersion.of(8)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.gradle.client.build.action;

import org.gradle.client.build.model.ResolvedDomPrerequisites;
import org.gradle.declarative.dsl.schema.AnalysisSchema;
import org.gradle.declarative.dsl.tooling.models.DeclarativeSchemaModel;
import org.gradle.tooling.BuildAction;
import org.gradle.tooling.BuildController;
import org.gradle.tooling.model.gradle.GradleBuild;

import java.io.File;

public class GetResolvedDomAction implements BuildAction<ResolvedDomPrerequisites> {

@Override
public ResolvedDomPrerequisites execute(BuildController controller) {
AnalysisSchema projectSchema = getProjectSchema(controller);
String buildFileContent = getBuildFileContent(controller);
return new ResolvedDomPrerequisitesImpl(projectSchema, buildFileContent);
}

private static AnalysisSchema getProjectSchema(BuildController controller) {
DeclarativeSchemaModel declarativeSchemaModel = controller.getModel(DeclarativeSchemaModel.class);
return declarativeSchemaModel.getProjectSchema();
}

private static String getBuildFileContent(BuildController controller) {
GradleBuild gradleBuild = controller.getModel(GradleBuild.class);
File randomProjectBuildFile = gradleBuild.getProjects().getAll().stream()
.map(p -> new File(p.getProjectDirectory(), "build.gradle.dcl"))
.filter(File::exists)
.findFirst()
.orElseThrow(() -> new RuntimeException("Declarative project file not found"));

return randomProjectBuildFile.getAbsolutePath();


}

private static final class ResolvedDomPrerequisitesImpl implements ResolvedDomPrerequisites {

private final AnalysisSchema analysisSchema;
private final String buildFilePath;

public ResolvedDomPrerequisitesImpl(AnalysisSchema analysisSchema, String buildFilePath) {
this.analysisSchema = analysisSchema;
this.buildFilePath = buildFilePath;
}

@Override
public AnalysisSchema getAnalysisSchema() {
return analysisSchema;
}

@Override
public String getBuildFilePath() {
return buildFilePath;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.gradle.client.build.model;

import org.gradle.declarative.dsl.schema.AnalysisSchema;

import java.io.Serializable;

public interface ResolvedDomPrerequisites extends Serializable {

AnalysisSchema getAnalysisSchema();

String getBuildFilePath();

}
3 changes: 3 additions & 0 deletions gradle-client/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ kotlin {

jvmMain.dependencies {

implementation(project(":build-action"))

implementation(libs.gradle.tooling.api)

implementation(libs.sqldelight.extensions.coroutines)
Expand Down Expand Up @@ -64,6 +66,7 @@ kotlin {
implementation(libs.slf4j.api)
implementation(libs.logback.classic)

implementation(libs.gradle.declarative.dsl.core)
implementation(libs.gradle.declarative.dsl.tooling.models)

runtimeOnly(libs.kotlinx.coroutines.swing)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import org.gradle.client.core.gradle.GradleConnectionParameters
import org.gradle.client.core.gradle.GradleDistribution
import org.gradle.client.ui.AppDispatchers
import org.gradle.client.ui.connected.actions.*
import org.gradle.tooling.BuildAction
import org.gradle.tooling.GradleConnector
import org.gradle.tooling.ProjectConnection
import org.gradle.tooling.events.OperationType
Expand All @@ -21,7 +22,6 @@ import org.slf4j.LoggerFactory
import java.io.File
import java.time.Duration
import java.time.Instant
import kotlin.reflect.KClass

private val logger = LoggerFactory.getLogger(ConnectedComponent::class.java)

Expand Down Expand Up @@ -59,7 +59,8 @@ class ConnectedComponent(
GetBuildEnvironment(),
GetGradleBuild(),
GetGradleProject(),
GetProjectSchema()
GetProjectSchema(),
GetResolvedDom()
)

private val scope = coroutineScope(appDispatchers.main + SupervisorJob())
Expand Down Expand Up @@ -104,30 +105,53 @@ class ConnectedComponent(
}
}

fun getModel(modelType: KClass<*>) {
fun getModel(modelAction: GetModelAction<out Any>) {
scope.launch {
model.value.requireConnected { current ->
mutableModel.value = current.copy(events = emptyList(), outcome = Outcome.Building)
withContext(appDispatchers.io) {
logger.atDebug().log { "Get ${modelType.simpleName} model!" }
@Suppress("TooGenericExceptionCaught")
try {
val result = connection.model(modelType.java)
.addArguments(
when (parameters.javaHomeDir) {
null -> "-Dorg.gradle.java.home=${System.getenv("JAVA_HOME")}"
else -> "-Dorg.gradle.java.home=${parameters.javaHomeDir}"
if (modelAction is GetModelAction.GetCompositeModelAction) {
logger.atDebug().log { "Run ${modelAction.javaClass.simpleName} build action!" }
val result = connection.action(modelAction.buildAction)
.addArguments(
when (parameters.javaHomeDir) {
null -> "-Dorg.gradle.java.home=${System.getenv("JAVA_HOME")}"
else -> "-Dorg.gradle.java.home=${parameters.javaHomeDir}"
}
)
.addProgressListener(
newEventListener(),
OperationType.entries.toSet() - OperationType.GENERIC
)
.run()
logger.atInfo().log { "Ran ${modelAction.javaClass.simpleName} build action: $result" }
model.value.requireConnected { model ->
withContext(appDispatchers.main) {
mutableModel.value = model.copy(outcome = Outcome.Result(result))
}
}
} else { // todo: refactor, very ugly
val modelType = modelAction.modelType
logger.atDebug().log { "Get ${modelType.simpleName} model!" }
val result = connection.model(modelType.java)
.addArguments(
when (parameters.javaHomeDir) {
null -> "-Dorg.gradle.java.home=${System.getenv("JAVA_HOME")}"
else -> "-Dorg.gradle.java.home=${parameters.javaHomeDir}"
}
)
.addProgressListener(
newEventListener(),
OperationType.entries.toSet() - OperationType.GENERIC
)
.get()
logger.atInfo().log { "Got ${modelType.simpleName} model: $result" }
model.value.requireConnected { model ->
withContext(appDispatchers.main) {
mutableModel.value = model.copy(outcome = Outcome.Result(result))
}
)
.addProgressListener(
newEventListener(),
OperationType.entries.toSet() - OperationType.GENERIC
)
.get()
logger.atInfo().log { "Got ${modelType.simpleName} model: $result" }
model.value.requireConnected { model ->
withContext(appDispatchers.main) {
mutableModel.value = model.copy(outcome = Outcome.Result(result))
}
}
} catch (ex: Exception) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ private fun ConnectedMainContent(component: ConnectedComponent, model: Connectio
ListItem(
modifier = Modifier.selectable(
selected = false,
onClick = { component.getModel(action.modelType) }
onClick = { component.getModel(action) }
),
leadingContent = { Icon(Icons.Default.PlayCircle, action.displayName) },
headlineContent = { Text(action.displayName, style = MaterialTheme.typography.titleSmall) },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import org.gradle.tooling.model.gradle.GradleBuild
import java.io.File
import java.io.IOException
import java.nio.file.Files

class GetGradleBuild : GetModelAction<GradleBuild> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package org.gradle.client.ui.connected.actions

import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.runtime.Composable
import org.gradle.declarative.dsl.schema.FqName.Empty.simpleName
import org.gradle.tooling.BuildAction
import kotlin.reflect.KClass

interface GetModelAction<T : Any> {
Expand All @@ -13,4 +15,12 @@ interface GetModelAction<T : Any> {

@Composable
fun ColumnScope.ModelContent(model: T)

interface GetCompositeModelAction<T : Any> : GetModelAction<T> {

val buildAction : BuildAction<T>

override val displayName: String
get() = "Run ${buildAction::class.simpleName}"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class GetProjectSchema : GetModelAction<DeclarativeSchemaModel> {
@Composable
override fun ColumnScope.ModelContent(model: DeclarativeSchemaModel) {
Text(
text = "Gradle Project",
text = "Gradle Project Schema",
style = MaterialTheme.typography.titleMedium
)
Text(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.gradle.client.ui.connected.actions

import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import org.gradle.client.build.action.GetResolvedDomAction
import org.gradle.client.build.model.ResolvedDomPrerequisites
import org.gradle.internal.declarativedsl.analysis.analyzeEverything
import org.gradle.internal.declarativedsl.dom.resolvedDocument
import org.gradle.internal.declarativedsl.language.LanguageTreeResult
import org.gradle.internal.declarativedsl.language.SourceIdentifier
import org.gradle.internal.declarativedsl.parsing.DefaultLanguageTreeBuilder
import org.gradle.internal.declarativedsl.parsing.parse
import org.gradle.tooling.BuildAction
import java.io.File

class GetResolvedDom : GetModelAction.GetCompositeModelAction<ResolvedDomPrerequisites> {

override val modelType = ResolvedDomPrerequisites::class

override val buildAction: BuildAction<ResolvedDomPrerequisites> = GetResolvedDomAction()

@Composable
override fun ColumnScope.ModelContent(model: ResolvedDomPrerequisites) {
val buildFile = File(model.buildFilePath)
val buildFileContent = buildFile.readText()
val parsedLightTree = parse(buildFileContent)
val languageTreeResult = DefaultLanguageTreeBuilder().build(parsedLightTree, SourceIdentifier(buildFile.name))

val resolvedDocument = resolvedDocument(model.analysisSchema, languageTreeResult, analyzeEverything, true)

Text(
text = "Gradle Resolved DOM",
style = MaterialTheme.typography.titleMedium
)
Text(
text = "Schema: $resolvedDocument",
// todo: this is just a useless println, but the content is there, can be seen in the debugger
style = MaterialTheme.typography.labelSmall
)
}
}
3 changes: 2 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ kotlinx-coroutines = "1.7.3"
kotlinx-serialization = "1.6.2"
compose-plugin = "1.6.1"
decompose = "3.0.0-alpha07"
gradle-tooling = "8.9-20240515001350+0000"
gradle-tooling = "8.9-branch-jb_declarative_dsl_fix_misc_issue_related_to_models-20240517104245+0000"
declarative-dsl = "8.9-branch-jb_declarative_dsl_fix_misc_issue_related_to_models-20240517104245+0000"
sqldelight = "2.0.1"
ktor = "2.3.9"
Expand All @@ -25,6 +25,7 @@ decompose-decompose = { module = "com.arkivanov.decompose:decompose", version.re
decompose-compose = { module = "com.arkivanov.decompose:extensions-compose", version.ref = "decompose" }
essenty-lifecycle-coroutines = { module = "com.arkivanov.essenty:lifecycle-coroutines", version = "1.3.0" }
gradle-tooling-api = { module = "org.gradle:gradle-tooling-api", version.ref = "gradle-tooling" }
gradle-declarative-dsl-core = { module = "org.gradle:gradle-declarative-dsl-tooling-models", version.ref = "declarative-dsl" }
gradle-declarative-dsl-tooling-models = { module = "org.gradle:gradle-declarative-dsl-core", version.ref = "declarative-dsl" }
material3WindowSizeClassMultiplatform = { module = "dev.chrisbanes.material3:material3-window-size-class-multiplatform", version = "0.3.1" }
materialKolor = { module = "com.materialkolor:material-kolor", version = "1.4.4" }
Expand Down
3 changes: 3 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pluginManagement {
gradlePluginPortal {
content {
includeGroupAndSubgroups("com.gradle")
includeGroupAndSubgroups("org.gradle")
includeGroupAndSubgroups("io.github.gradle")
}
}
Expand All @@ -15,6 +16,7 @@ pluginManagement {
plugins {
id("com.gradle.enterprise") version "3.16.2"
id("io.github.gradle.gradle-enterprise-conventions-plugin") version "0.9.1"
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}

dependencyResolutionManagement {
Expand Down Expand Up @@ -47,3 +49,4 @@ require(JavaVersion.current() == JavaVersion.VERSION_17) {
rootProject.name = "gradle-client-root"

include(":gradle-client")
include(":build-action")
Loading