diff --git a/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java index 485c4e70..1e7a880f 100644 --- a/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java +++ b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java @@ -70,9 +70,7 @@ public interface LoomGradleExtensionAPI { ConfigurableFileCollection getLog4jConfigs(); - default Dependency officialMojangMappings() { - return layered(LayeredMappingSpecBuilder::officialMojangMappings); - } + Dependency officialMojangMappings(); Dependency layered(Action action); diff --git a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java index aa6365ec..3d27b4ba 100644 --- a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java +++ b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java @@ -78,6 +78,9 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA private final NamedDomainObjectContainer runConfigs; private final NamedDomainObjectContainer decompilers; + // A common mistake with layered mappings is to call the wrong `officialMojangMappings` method, use this to keep track of when we are building a layered mapping spec. + protected final ThreadLocal layeredSpecBuilderScope = ThreadLocal.withInitial(() -> false); + protected LoomGradleExtensionApiImpl(Project project, LoomFiles directories) { this.jarProcessors = project.getObjects().listProperty(JarProcessor.class) .empty(); @@ -162,10 +165,23 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA return jarProcessors; } + @Override + public Dependency officialMojangMappings() { + if (layeredSpecBuilderScope.get()) { + throw new IllegalStateException("Use `officialMojangMappings()` when configuring layered mappings, not the extension method `loom.officialMojangMappings()`"); + } + + return layered(LayeredMappingSpecBuilder::officialMojangMappings); + } + @Override public Dependency layered(Action action) { LayeredMappingSpecBuilderImpl builder = new LayeredMappingSpecBuilderImpl(); + + layeredSpecBuilderScope.set(true); action.execute(builder); + layeredSpecBuilderScope.set(false); + LayeredMappingSpec builtSpec = builder.build(); return new LayeredMappingsDependency(getProject(), new GradleMappingContext(getProject(), builtSpec.getVersion().replace("+", "_").replace(".", "_")), builtSpec, builtSpec.getVersion()); } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/MojangMappingsProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/MojangMappingsProjectTest.groovy index 6afba527..2e1db92c 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/MojangMappingsProjectTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/MojangMappingsProjectTest.groovy @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2018-2021 FabricMC + * Copyright (c) 2018-2022 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 @@ -74,4 +74,29 @@ class MojangMappingsProjectTest extends Specification implements GradleProjectTe where: version << STANDARD_TEST_VERSIONS } + + @Unroll + def "fail with wrong officialMojangMappings usage (gradle #version)"() { + setup: + def gradle = gradleProject(project: "minimalBase", version: version) + + gradle.buildGradle << ''' + dependencies { + minecraft "com.mojang:minecraft:1.18.2" + mappings loom.layered { + // This is the wrong method to call! + loom.officialMojangMappings() + } + } + ''' + + when: + def result = gradle.run(task: "build", expectFailure: true) + + then: + result.output.contains("Use `officialMojangMappings()` when configuring layered mappings, not the extension method `loom.officialMojangMappings()`") + + where: + version << STANDARD_TEST_VERSIONS + } }