From 8c2d5525e8cca7e0c6445e9e6940eda940567936 Mon Sep 17 00:00:00 2001 From: modmuss Date: Wed, 2 Oct 2024 09:43:37 +0100 Subject: [PATCH] Fix #1184 : GradleUtils.getDependencyProject not working for typesafe project accessors (#1185) --- .../loom/util/gradle/GradleUtils.java | 36 ++++++++--- .../loom/test/unit/GradleUtilsTest.groovy | 59 +++++++++++++++++++ 2 files changed, 87 insertions(+), 8 deletions(-) create mode 100644 src/test/groovy/net/fabricmc/loom/test/unit/GradleUtilsTest.groovy diff --git a/src/main/java/net/fabricmc/loom/util/gradle/GradleUtils.java b/src/main/java/net/fabricmc/loom/util/gradle/GradleUtils.java index e700a870d..6de98bff9 100644 --- a/src/main/java/net/fabricmc/loom/util/gradle/GradleUtils.java +++ b/src/main/java/net/fabricmc/loom/util/gradle/GradleUtils.java @@ -32,10 +32,15 @@ import org.gradle.api.artifacts.ProjectDependency; import org.gradle.api.file.RegularFileProperty; import org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency; +import org.gradle.api.internal.catalog.DelegatingProjectDependency; import org.gradle.api.invocation.Gradle; import org.gradle.api.provider.Provider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public final class GradleUtils { + private static final Logger LOGGER = LoggerFactory.getLogger(GradleUtils.class); + private GradleUtils() { } @@ -95,14 +100,29 @@ public static File configurationInputFile(Project project, File file) { // Get the project from the field with reflection to suppress the deprecation warning. // If you hate it find a solution yourself and make a PR, I'm getting a bit tired of chasing Gradle updates public static Project getDependencyProject(ProjectDependency projectDependency) { - try { - final Class clazz = DefaultProjectDependency.class; - final Field dependencyProject = clazz.getDeclaredField("dependencyProject"); - dependencyProject.setAccessible(true); - return (Project) dependencyProject.get(projectDependency); - } catch (NoSuchFieldException | IllegalAccessException ignored) { - // Just fallback and trigger the warning, this will break in Gradle 9 - return projectDependency.getDependencyProject(); + if (projectDependency instanceof DefaultProjectDependency) { + try { + final Class clazz = DefaultProjectDependency.class; + final Field dependencyProject = clazz.getDeclaredField("dependencyProject"); + dependencyProject.setAccessible(true); + return (Project) dependencyProject.get(projectDependency); + } catch (NoSuchFieldException | IllegalAccessException e) { + LOGGER.warn("Failed to reflect DefaultProjectDependency", e); + } + } else if (projectDependency instanceof DelegatingProjectDependency) { + try { + final Class clazz = DelegatingProjectDependency.class; + final Field delgeate = clazz.getDeclaredField("delegate"); + delgeate.setAccessible(true); + return getDependencyProject((ProjectDependency) delgeate.get(projectDependency)); + } catch (NoSuchFieldException | IllegalAccessException e) { + LOGGER.warn("Failed to reflect DelegatingProjectDependency", e); + } } + + // Just fallback and trigger the warning, this will break in Gradle 9 + final Project project = projectDependency.getDependencyProject(); + LOGGER.warn("Loom was unable to suppress the deprecation warning for ProjectDependency#getDependencyProject, if you are on the latest version of Loom please report this issue to the Loom developers and provide the error above, this WILL stop working in a future Gradle version."); + return project; } } diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/GradleUtilsTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/GradleUtilsTest.groovy new file mode 100644 index 000000000..20f9c96f9 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/unit/GradleUtilsTest.groovy @@ -0,0 +1,59 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2024 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.test.unit + +import org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency +import org.gradle.api.internal.catalog.DelegatingProjectDependency +import org.gradle.api.internal.project.ProjectInternal +import spock.lang.Specification + +import net.fabricmc.loom.util.gradle.GradleUtils + +class GradleUtilsTest extends Specification { + def "get default project dependency"() { + given: + def project = Mock(ProjectInternal) + def dependency = new DefaultProjectDependency(project, false) + + when: + def result = GradleUtils.getDependencyProject(dependency) + + then: + result == project + } + + def "get delegated project dependency"() { + given: + def project = Mock(ProjectInternal) + def dependency = new DefaultProjectDependency(project, true) + def delegate = new DelegatingProjectDependency(null, dependency) + + when: + def result = GradleUtils.getDependencyProject(delegate) + + then: + result == project + } +}