Skip to content

Commit

Permalink
Fix Intelij download sources hook.
Browse files Browse the repository at this point in the history
  • Loading branch information
modmuss50 committed Dec 19, 2023
1 parent 6f38d5f commit 984974b
Show file tree
Hide file tree
Showing 15 changed files with 292 additions and 178 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,10 @@ private void setupMixinAp(MixinExtension mixin) {
private void configureDecompileTasks(ConfigContext configContext) {
final LoomGradleExtension extension = configContext.extension();

extension.getMinecraftJarConfiguration().get().getDecompileConfigurationBiFunction()
.apply(configContext, extension.getNamedMinecraftProvider()).afterEvaluation();
extension.getMinecraftJarConfiguration().get()
.getDecompileConfigurationBiFunction()
.apply(configContext.project(), extension.getNamedMinecraftProvider())
.afterEvaluation();
}

private Path getLockFile() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
import org.gradle.api.artifacts.ConfigurationContainer;

import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.ConfigContext;
import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJar;
import net.fabricmc.loom.configuration.providers.minecraft.mapped.MappedMinecraftProvider;
import net.fabricmc.loom.task.GenerateSourcesTask;
import net.fabricmc.loom.util.Constants;
Expand All @@ -42,13 +42,15 @@ public abstract class DecompileConfiguration<T extends MappedMinecraftProvider>
protected final LoomGradleExtension extension;
protected final MappingConfiguration mappingConfiguration;

public DecompileConfiguration(ConfigContext configContext, T minecraftProvider) {
this.project = configContext.project();
public DecompileConfiguration(Project project, T minecraftProvider) {
this.project = project;
this.minecraftProvider = minecraftProvider;
this.extension = configContext.extension();
this.extension = LoomGradleExtension.get(project);
this.mappingConfiguration = extension.getMappingConfiguration();
}

public abstract String getTaskName(MinecraftJar.Type type);

public abstract void afterEvaluation();

protected final void configureUnpick(GenerateSourcesTask task, File unpickOutputJar) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,34 @@
import java.io.File;
import java.util.List;

import org.gradle.api.Project;

import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.ConfigContext;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJar;
import net.fabricmc.loom.configuration.providers.minecraft.mapped.MappedMinecraftProvider;
import net.fabricmc.loom.task.GenerateSourcesTask;
import net.fabricmc.loom.util.Constants;

public class SingleJarDecompileConfiguration extends DecompileConfiguration<MappedMinecraftProvider> {
public SingleJarDecompileConfiguration(ConfigContext configContext, MappedMinecraftProvider minecraftProvider) {
super(configContext, minecraftProvider);
public SingleJarDecompileConfiguration(Project project, MappedMinecraftProvider minecraftProvider) {
super(project, minecraftProvider);
}

@Override
public String getTaskName(MinecraftJar.Type type) {
return "genSources";
}

@Override
public final void afterEvaluation() {
final List<MinecraftJar> minecraftJars = minecraftProvider.getMinecraftJars();
assert minecraftJars.size() == 1;
final MinecraftJar minecraftJar = minecraftJars.get(0);
final String taskBaseName = getTaskName(minecraftJar.getType());

LoomGradleExtension.get(project).getDecompilerOptions().forEach(options -> {
final String decompilerName = options.getFormattedName();
String taskName = "genSourcesWith" + decompilerName;
String taskName = "%sWith%s".formatted(taskBaseName, decompilerName);
// Decompiler will be passed to the constructor of GenerateSourcesTask
project.getTasks().register(taskName, GenerateSourcesTask.class, options).configure(task -> {
task.getInputJarName().set(minecraftJar.getName());
Expand All @@ -64,7 +71,7 @@ public final void afterEvaluation() {
});
});

project.getTasks().register("genSources", task -> {
project.getTasks().register(taskBaseName, task -> {
task.setDescription("Decompile minecraft using the default decompiler.");
task.setGroup(Constants.TaskGroup.FABRIC);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,28 @@
import java.io.File;

import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.tasks.TaskProvider;

import net.fabricmc.loom.api.decompilers.DecompilerOptions;
import net.fabricmc.loom.configuration.ConfigContext;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJar;
import net.fabricmc.loom.configuration.providers.minecraft.mapped.MappedMinecraftProvider;
import net.fabricmc.loom.task.GenerateSourcesTask;
import net.fabricmc.loom.util.Constants;

public final class SplitDecompileConfiguration extends DecompileConfiguration<MappedMinecraftProvider.Split> {
public SplitDecompileConfiguration(ConfigContext configContext, MappedMinecraftProvider.Split minecraftProvider) {
super(configContext, minecraftProvider);
public SplitDecompileConfiguration(Project project, MappedMinecraftProvider.Split minecraftProvider) {
super(project, minecraftProvider);
}

@Override
public String getTaskName(MinecraftJar.Type type) {
return switch (type) {
case COMMON -> "genCommonSources";
case CLIENT_ONLY -> "genClientSources";
default -> throw new AssertionError();
};
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 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.configuration.ide.idea;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.gradle.api.Project;
import org.gradle.api.Task;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.mods.dependency.LocalMavenHelper;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJar;
import net.fabricmc.loom.configuration.providers.minecraft.mapped.NamedMinecraftProvider;

record DownloadSourcesHook(Project project, Task task) {
public static final String INIT_SCRIPT_NAME = "ijDownloadSources";
private static final Pattern NOTATION_PATTERN = Pattern.compile("dependencyNotation = '(?<notation>.*)'");
private static final Logger LOGGER = LoggerFactory.getLogger(IdeaConfiguration.class);

/*
"Parse" the init script enough to figure out what jar we are talking about.
Intelij code: https://github.com/JetBrains/intellij-community/blob/a09b1b84ab64a699794c860bc96774766dd38958/plugins/gradle/java/src/util/GradleAttachSourcesProvider.java
*/
void tryHook() {
List<File> initScripts = project.getGradle().getStartParameter().getInitScripts();

for (File initScript : initScripts) {
if (!initScript.getName().contains(INIT_SCRIPT_NAME)) {
continue;
}

try {
final String script = Files.readString(initScript.toPath(), StandardCharsets.UTF_8);
final String notation = parseInitScript(script);

if (notation == null) {
LOGGER.debug("failed to parse init script dependency");
continue;
}

final MinecraftJar.Type jarType = getJarType(notation);

if (jarType == null) {
LOGGER.debug("init script is trying to download sources for another Minecraft jar ({}) not used by this project ({})", notation, project.getPath());
continue;
}

String sourcesTaskName = getGenSourcesTaskName(jarType);
task.dependsOn(project.getTasks().named(sourcesTaskName));

LOGGER.info("Running genSources task: {} in project: {} for {}", sourcesTaskName, project.getPath(), notation);
break;
} catch (IOException e) {
// Ignore
}
}
}

@Nullable
private String parseInitScript(String script) {
if (!script.contains("IjDownloadTask")) {
// Failed some basic sanity checks.
return null;
}

// A little gross but should do the job nicely.
final Matcher matcher = NOTATION_PATTERN.matcher(script);

if (matcher.find()) {
return matcher.group("notation");
}

return null;
}

private String getGenSourcesTaskName(MinecraftJar.Type jarType) {
LoomGradleExtension extension = LoomGradleExtension.get(project);
return extension.getMinecraftJarConfiguration().get()
.getDecompileConfigurationBiFunction()
.apply(project, extension.getNamedMinecraftProvider())
.getTaskName(jarType);
}

// Return the jar type, or null when this jar isnt used by the project
private @Nullable MinecraftJar.Type getJarType(String name) {
final LoomGradleExtension extension = LoomGradleExtension.get(project);
final NamedMinecraftProvider<?> minecraftProvider = extension.getNamedMinecraftProvider();
final List<MinecraftJar.Type> dependencyTypes = minecraftProvider.getDependencyTypes();

if (dependencyTypes.isEmpty()) {
throw new IllegalStateException();
}

for (MinecraftJar.Type type : dependencyTypes) {
final LocalMavenHelper mavenHelper = minecraftProvider.getMavenHelper(type).withClassifier("sources");

if (mavenHelper.getNotation().equals(name)) {
return type;
}
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,35 +24,23 @@

package net.fabricmc.loom.configuration.ide.idea;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.inject.Inject;

import org.gradle.StartParameter;
import org.gradle.TaskExecutionRequest;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.internal.DefaultTaskExecutionRequest;
import org.jetbrains.annotations.Nullable;

import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration;
import net.fabricmc.loom.task.LoomTasks;
import net.fabricmc.loom.util.gradle.GradleUtils;

public abstract class IdeaConfiguration implements Runnable {
private static final String INIT_SCRIPT_NAME = "ijmiscinit";
private static final Pattern NOTATION_PATTERN = Pattern.compile("'net\\.minecraft:(?<name>.*):(.*):sources'");

@Inject
protected abstract Project getProject();

Expand All @@ -65,11 +53,7 @@ public void run() {
}
});

getProject().getTasks().configureEach(task -> {
if (task.getName().equals("DownloadSources")) {
hookDownloadSources(getProject(), task);
}
});
hookDownloadSources();

if (!IdeaUtils.isIdeaSync()) {
return;
Expand All @@ -82,62 +66,23 @@ public void run() {
startParameter.setTaskRequests(taskRequests);
}

/*
"Parse" the init script enough to figure out what jar we are talking about.
Intelij code: https://github.com/JetBrains/intellij-community/blob/a09b1b84ab64a699794c860bc96774766dd38958/plugins/gradle/java/src/util/GradleAttachSourcesProvider.java
*/
private static void hookDownloadSources(Project project, Task task) {
List<File> initScripts = project.getGradle().getStartParameter().getInitScripts();

for (File initScript : initScripts) {
if (!initScript.getName().contains(INIT_SCRIPT_NAME)) {
continue;
}

try {
final String script = Files.readString(initScript.toPath(), StandardCharsets.UTF_8);
final String notation = parseInitScript(project, script);

if (notation != null) {
task.dependsOn(getGenSourcesTaskName(LoomGradleExtension.get(project), notation));
}
} catch (IOException e) {
// Ignore
}
}
}

@Nullable
private static String parseInitScript(Project project, String script) {
if (!script.contains("Attempt to download sources from")
|| !script.contains("downloadSources_")
|| !script.contains("'%s'".formatted(project.getPath()))) {
// Failed some basic sanity checks.
return null;
}

// A little gross but should do the job nicely.
final Matcher matcher = NOTATION_PATTERN.matcher(script);
private void hookDownloadSources() {
LoomGradleExtension extension = LoomGradleExtension.get(getProject());

if (matcher.find()) {
return matcher.group("name");
if (!extension.isRootProject()) {
return;
}

return null;
}

private static String getGenSourcesTaskName(LoomGradleExtension extension, String notation) {
final MinecraftJarConfiguration configuration = extension.getMinecraftJarConfiguration().get();

if (configuration == MinecraftJarConfiguration.SPLIT) {
if (notation.toLowerCase(Locale.ROOT).contains("minecraft-clientonly")) {
return "genClientOnlySources";
getProject().getTasks().configureEach(task -> {
if (task.getName().startsWith(DownloadSourcesHook.INIT_SCRIPT_NAME)) {
getProject().allprojects(subProject -> {
if (!GradleUtils.isLoomProject(subProject)) {
return;
}

new DownloadSourcesHook(subProject, task).tryHook();
});
}

return "genCommonSources";
}

return "genSources";
});
}
}
Loading

0 comments on commit 984974b

Please sign in to comment.