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

Enums and Settings #29

Merged
merged 4 commits into from
Oct 1, 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
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.io.File;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class GetResolvedDomAction implements BuildAction<ResolvedDomPrerequisites> {
Expand All @@ -37,10 +38,10 @@ private static Pair<File, List<File>> getDeclarativeBuildFiles(BuildController c
if (declarativeBuildFiles.isEmpty()) {
throw new RuntimeException("No declarative project file found");
}
return Pair.of(rootProjectDirectory, declarativeBuildFiles);
return Pair.of(rootProjectDirectory, declarativeBuildFiles);
}


private static final class ResolvedDomPrerequisitesImpl implements ResolvedDomPrerequisites {

private final InterpretationSequence settingsSequence;
Expand All @@ -51,7 +52,7 @@ private static final class ResolvedDomPrerequisitesImpl implements ResolvedDomPr
public ResolvedDomPrerequisitesImpl(
InterpretationSequence settingsSequence,
InterpretationSequence projectSequence,
File rootDir,
File rootDir,
List<File> declarativeBuildFiles
) {
this.settingsSequence = settingsSequence;
Expand Down Expand Up @@ -91,8 +92,11 @@ public File getSettingsFile() {
}

@Override
public List<File> getDeclarativeBuildFiles() {
return declarativeBuildFiles;
public List<File> getDeclarativeFiles() {
return Stream.concat(
declarativeBuildFiles.stream(),
getSettingsFile().canRead() ? Stream.of(getSettingsFile()) : Stream.empty()
).collect(Collectors.toList());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ public interface ResolvedDomPrerequisites extends Serializable {

File getSettingsFile();

List<File> getDeclarativeBuildFiles();
List<File> getDeclarativeFiles();
}
1 change: 1 addition & 0 deletions gradle-client/proguard-desktop.pro
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

# Kotlin embedded compiler dependencies
-dontwarn kotlin.annotations.jvm.**
-dontwarn org.jetbrains.concurrency.**
-dontwarn org.jetbrains.kotlin.com.google.common.**
-dontwarn org.jetbrains.kotlin.com.google.gson.**
-dontwarn org.jetbrains.kotlin.com.google.errorprone.**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,17 @@ package org.gradle.client.core.gradle.dcl

import org.gradle.internal.declarativedsl.dom.DeclarativeDocument
import org.gradle.internal.declarativedsl.dom.DocumentResolution
import org.gradle.internal.declarativedsl.dom.UnresolvedBase
import org.gradle.internal.declarativedsl.dom.data.collectToMap
import org.gradle.internal.declarativedsl.dom.operations.overlay.DocumentOverlay.overlayResolvedDocuments
import org.gradle.internal.declarativedsl.dom.operations.overlay.DocumentOverlayResult
import org.gradle.internal.declarativedsl.dom.resolution.DocumentResolutionContainer
import org.gradle.internal.declarativedsl.dom.resolution.DocumentWithResolution
import org.gradle.internal.declarativedsl.evaluator.main.AnalysisDocumentUtils.resolvedDocument
import org.gradle.internal.declarativedsl.evaluator.main.AnalysisSequenceResult
import org.gradle.internal.declarativedsl.evaluator.runner.stepResultOrPartialResult
import org.gradle.internal.declarativedsl.language.SourceData
import org.gradle.internal.declarativedsl.language.SyntheticallyProduced
import java.util.*

fun DeclarativeDocument.relevantRange(): IntRange {
Expand Down Expand Up @@ -42,3 +51,109 @@ fun DeclarativeDocument.nodeAt(fileIdentifier: String, offset: Int): Declarative
}
return node
}

fun settingsWithNoOverlayOrigin(analysisSequenceResult: AnalysisSequenceResult): DocumentOverlayResult? {
val docs = analysisSequenceResult.stepResults.map { it.value.stepResultOrPartialResult.resolvedDocument() }
if (docs.isEmpty())
return null

return indexBasedOverlayResultFromDocuments(docs)
}


internal fun indexBasedOverlayResultFromDocuments(docs: List<DocumentWithResolution>): DocumentOverlayResult {
val emptyDoc = DocumentWithResolution(
object : DeclarativeDocument {
override val content: List<DeclarativeDocument.DocumentNode> = emptyList()
override val sourceData: SourceData = SyntheticallyProduced
},
indexBasedMultiResolutionContainer(emptyList())
)

val lastDocWithAllResolutionResults = DocumentWithResolution(
docs.last().document,
indexBasedMultiResolutionContainer(docs)
)

/**
* NB: No real overlay origin data is going to be present, as we are overlaying the doc with all the resolution
* results collected over the empty document.
*/
return overlayResolvedDocuments(emptyDoc, lastDocWithAllResolutionResults)
}

/**
* A resolution results container collected from multiple resolved instances of the same document (or multiple
* different instances of the same document, no referential equality required).
*
* The document parts are matched based on indices.
*
* If any of the [docs] is different from the others, the result is undefined (likely to be a broken container).
*/
internal fun indexBasedMultiResolutionContainer(docs: List<DocumentWithResolution>): DocumentResolutionContainer {
val indicesMaps: Map<DocumentWithResolution, Map<IntRange, DeclarativeDocument.Node>> = docs.associateWith {
buildMap {
fun visitValue(valueNode: DeclarativeDocument.ValueNode) {
put(valueNode.sourceData.indexRange, valueNode)
when (valueNode) {
is DeclarativeDocument.ValueNode.ValueFactoryNode -> valueNode.values.forEach(::visitValue)
is DeclarativeDocument.ValueNode.LiteralValueNode,
is DeclarativeDocument.ValueNode.NamedReferenceNode -> Unit
}
}

fun visitDocumentNode(documentNode: DeclarativeDocument.DocumentNode) {
put(documentNode.sourceData.indexRange, documentNode)
when (documentNode) {
is DeclarativeDocument.DocumentNode.ElementNode -> {
documentNode.elementValues.forEach(::visitValue)
documentNode.content.forEach(::visitDocumentNode)
}

is DeclarativeDocument.DocumentNode.PropertyNode -> visitValue(documentNode.value)
is DeclarativeDocument.DocumentNode.ErrorNode -> Unit
}
}

it.document.content.forEach(::visitDocumentNode)
}
}

/**
* The resolution containers work with node identities.
* Querying resolution results using nodes from a different document is prohibited.
* Given that all documents are the same, we can map the node indices and use them to find matching nodes in
* the documents that we are merging.
*/
return object : DocumentResolutionContainer {
inline fun <reified N : DeclarativeDocument.Node, reified T> retryOverContainers(
node: N,
noinline get: DocumentResolutionContainer.(N) -> T
) = docs.map { doc ->
val matchingNode = indicesMaps.getValue(doc)[node.sourceData.indexRange]
?: error("index not found in index map")
get(doc.resolutionContainer, matchingNode as N)
}.let { results ->
results.firstOrNull {
it !is DocumentResolution.UnsuccessfulResolution || !it.reasons.contains(UnresolvedBase)
} ?: results.first()
}

override fun data(node: DeclarativeDocument.DocumentNode.ElementNode) = retryOverContainers(node) { data(it) }
override fun data(node: DeclarativeDocument.DocumentNode.ErrorNode) = retryOverContainers(node) { data(it) }
override fun data(node: DeclarativeDocument.DocumentNode.PropertyNode) = retryOverContainers(node) { data(it) }
override fun data(node: DeclarativeDocument.ValueNode.LiteralValueNode) = retryOverContainers(node) { data(it) }
override fun data(node: DeclarativeDocument.ValueNode.NamedReferenceNode) =
retryOverContainers(node) { data(it) }

override fun data(node: DeclarativeDocument.ValueNode.ValueFactoryNode) = retryOverContainers(node) { data(it) }
}
}

internal fun DocumentResolutionContainer.isUnresolvedBase(node: DeclarativeDocument.Node): Boolean {
val resolution = when (node) {
is DeclarativeDocument.DocumentNode -> data(node)
is DeclarativeDocument.ValueNode -> data(node)
}
return resolution is DocumentResolution.UnsuccessfulResolution && resolution.reasons != listOf(UnresolvedBase)
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ object MutationUtils {
overlayResult: DocumentOverlayResult,
): NodeData<List<ApplicableMutation>> {
val overlayDocument = overlayResult.inputOverlay
val compatibleMutationsCatalog = DefaultMutationDefinitionCatalog().apply {
mutationCatalog.mutationDefinitionsById.values.forEach {
if (it.isCompatibleWithSchema(modelSchema)) {
val compatibleMutationsCatalog = DefaultMutationDefinitionCatalog().apply {
mutationCatalog.mutationDefinitionsById.values.forEach {
if (it.isCompatibleWithSchema(modelSchema)) {
registerMutationDefinition(it)
}
}
Expand Down Expand Up @@ -124,3 +124,9 @@ internal class OverlayRoutedNodeDataContainer<DNode, DElement : DNode, DProperty
is FromOverlay -> overlay.data(node)
}
}

internal class NoApplicableMutationsNodeData : NodeData<List<ApplicableMutation>> {
override fun data(node: DeclarativeDocument.DocumentNode.ElementNode) = emptyList<ApplicableMutation>()
override fun data(node: DeclarativeDocument.DocumentNode.ErrorNode) = emptyList<ApplicableMutation>()
override fun data(node: DeclarativeDocument.DocumentNode.PropertyNode) = emptyList<ApplicableMutation>()
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ package org.gradle.client.ui.connected.actions
import org.gradle.internal.declarativedsl.dom.DeclarativeDocument
import org.gradle.internal.declarativedsl.dom.DeclarativeDocument.DocumentNode.ElementNode
import org.gradle.internal.declarativedsl.dom.DeclarativeDocument.DocumentNode.PropertyNode
import org.gradle.internal.declarativedsl.dom.DocumentNodeContainer

val DeclarativeDocument.singleSoftwareTypeNode: ElementNode?
get() = content.filterIsInstance<ElementNode>().singleOrNull()

fun ElementNode.childElementNode(
fun DocumentNodeContainer.childElementNode(
name: String
): ElementNode? =
content.filterIsInstance<ElementNode>().singleOrNull() { it.name == name }

fun ElementNode.property(name: String): PropertyNode? =
fun DocumentNodeContainer.property(name: String): PropertyNode? =
content.filterIsInstance<PropertyNode>().singleOrNull { it.name == name }
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import org.gradle.declarative.dsl.schema.*
import kotlin.reflect.KClass

fun AnalysisSchema.dataClassFor(typeRef: DataTypeRef.Name): DataClass =
dataClassesByFqName.getValue(typeRef.fqName)
dataClassTypesByFqName.getValue(typeRef.fqName) as? DataClass
?: error("unexpected type for $typeRef")

val AnalysisSchema.softwareTypes: List<SchemaMemberFunction>
get() = topLevelReceiverType.memberFunctions
Expand All @@ -24,14 +25,6 @@ val DataProperty.typeName: String
is DataTypeRef.Name -> propType.toHumanReadable()
}

val DataProperty.kotlinType: KClass<*>
get() = when (typeName) {
"String" -> String::class
"Int" -> Int::class
"Boolean" -> Boolean::class
else -> Any::class
}

fun DataTypeRef.toHumanReadable(): String =
when (this) {
is DataTypeRef.Name -> fqName.simpleName
Expand All @@ -43,7 +36,7 @@ fun DataTypeRef.Type.toHumanReadable(): String =
is DataType.NullType -> "null"
is DataType.UnitType -> Unit::class.simpleName!!
is DataType.ConstantType<*> -> type.toString()
is DataClass -> type.name.simpleName
is DataType.ClassDataType -> type.name.simpleName
}

fun DataParameter.toHumanReadable(): String =
Expand Down
Loading