User: joe
Date: 10 Nov 26 01:14
Revision: ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc
Summary:
Rename "MCP" features to "Minecraft" features, except the things that really are MCP
TeamCity URL: http://ci.mcdev.io:80/viewModification.html?tab=vcsModificationFiles&modId=10690&personal=false
The following binary files were skipped:
src/main/resources/assets/icons/platform/MCP.png
src/main/resources/assets/icons/platform/MCP@2x.png
src/main/resources/assets/icons/platform/MCP@2x_dark.png
src/main/resources/assets/icons/platform/MCP_dark.png
Index: build.gradle.kts
===================================================================
--- build.gradle.kts (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ build.gradle.kts (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -298,11 +298,11 @@
}
}
-val generateAtLexer by lexer("AtLexer", "com/demonwav/mcdev/platform/mcp/at/gen")
-val generateAtParser by parser("AtParser", "com/demonwav/mcdev/platform/mcp/at/gen")
+val generateAtLexer by lexer("AtLexer", "com/demonwav/mcdev/platform/minecraft/at/gen")
+val generateAtParser by parser("AtParser", "com/demonwav/mcdev/platform/minecraft/at/gen")
-val generateCtLexer by lexer("CtLexer", "com/demonwav/mcdev/platform/mcp/ct/gen")
-val generateCtParser by parser("CtParser", "com/demonwav/mcdev/platform/mcp/ct/gen")
+val generateCtLexer by lexer("CtLexer", "com/demonwav/mcdev/platform/minecraft/ct/gen")
+val generateCtParser by parser("CtParser", "com/demonwav/mcdev/platform/minecraft/ct/gen")
val generateNbttLexer by lexer("NbttLexer", "com/demonwav/mcdev/nbt/lang/gen")
val generateNbttParser by parser("NbttParser", "com/demonwav/mcdev/nbt/lang/gen")
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModel.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModel.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModel.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,25 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling;
-
-public interface McpModel {
- String getMcpVersion();
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,28 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling;
-
-import java.util.Set;
-
-public interface McpModelFG2 extends McpModel {
- String getMinecraftVersion();
- Set getMappingFiles();
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2BuilderImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2BuilderImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2BuilderImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,85 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling;
-
-import org.gradle.api.Project;
-import org.gradle.api.Task;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.tooling.Message;
-import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext;
-import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
-
-import java.io.File;
-import java.util.HashSet;
-import java.util.Set;
-
-public final class McpModelFG2BuilderImpl implements ModelBuilderService {
-
- @Override
- public boolean canBuild(String modelName) {
- return McpModelFG2.class.getName().equals(modelName);
- }
-
- @Override
- public Object buildAll(String modelName, Project project) {
- Object extension = project.getExtensions().findByName("minecraft");
- if (extension == null) {
- return null;
- }
-
- Task genSrgs = project.getTasks().findByName("genSrgs");
- if (genSrgs == null) {
- return null;
- }
-
- try {
- String version = (String) ReflectUtil.getProperty(extension, "version");
- String mappings = (String) ReflectUtil.getProperty(extension, "mappings");
-
- Set files = genSrgs.getOutputs().getFiles().getFiles();
- Set mappingFiles = new HashSet<>();
- for (File file : files) {
- mappingFiles.add(file.getAbsolutePath());
- }
- return new McpModelFG2Impl(version, mappings, mappingFiles);
- } catch (Exception e) {
- return null;
- }
- }
-
- @Override
- public void reportErrorMessage(
- final @NotNull String modelName,
- final @NotNull Project project,
- final @NotNull ModelBuilderContext context,
- final @NotNull Exception exception
- ) {
- //noinspection UnstableApiUsage
- context.getMessageReporter().createMessage()
- .withGroup(this)
- .withKind(Message.Kind.ERROR)
- .withGroup("com.demonwav.mcdev")
- .withTitle("MinecraftDev: ForgeGradle import error")
- .withText("Unable to build MinecraftDev ForgeGradle model for project " + project.getDisplayName())
- .withException(exception)
- .reportMessage(project);
- }
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2Impl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2Impl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG2Impl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,51 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling;
-
-import java.util.Set;
-
-final class McpModelFG2Impl implements McpModelFG2, java.io.Serializable {
-
- private final String minecraftVersion;
- private final String mcpVersion;
- private final Set mappingFiles;
-
- McpModelFG2Impl(String minecraftVersion, String mcpVersion, Set mappingFiles) {
- this.minecraftVersion = minecraftVersion;
- this.mcpVersion = mcpVersion;
- this.mappingFiles = mappingFiles;
- }
-
- @Override
- public String getMinecraftVersion() {
- return minecraftVersion;
- }
-
- @Override
- public String getMcpVersion() {
- return mcpVersion;
- }
-
- @Override
- public Set getMappingFiles() {
- return mappingFiles;
- }
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,31 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling;
-
-import java.io.File;
-import java.util.List;
-
-public interface McpModelFG3 extends McpModel {
- List getMinecraftDepVersions();
- File getTaskOutputLocation();
- String getTaskName();
- List getAccessTransformers();
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3BuilderImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3BuilderImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3BuilderImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,121 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling;
-
-import org.gradle.api.Project;
-import org.gradle.api.Task;
-import org.gradle.api.artifacts.Configuration;
-import org.gradle.api.artifacts.Dependency;
-import org.gradle.api.file.FileCollection;
-import org.gradle.api.provider.Provider;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.tooling.Message;
-import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext;
-import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-public final class McpModelFG3BuilderImpl implements ModelBuilderService {
-
- @Override
- public boolean canBuild(String modelName) {
- return McpModelFG3.class.getName().equals(modelName);
- }
-
- @Override
- public Object buildAll(String modelName, Project project) {
- Object extension = project.getExtensions().findByName("minecraft");
- if (extension == null) {
- return null;
- }
-
- if (project.getPlugins().findPlugin("net.minecraftforge.gradle") == null) {
- return null;
- }
-
- List minecraftDepVersions = new ArrayList<>();
- Configuration minecraftConfig = project.getConfigurations().findByName("minecraft");
- if (minecraftConfig != null) {
- for (Dependency dep : minecraftConfig.getDependencies()) {
- minecraftDepVersions.add(dep.getVersion());
- }
- }
-
- Task task = project.getTasks().findByName("createMcpToSrg");
- if (task == null) {
- task = project.getTasks().findByName("createMcp2Srg");
- }
- if (task == null) {
- return null;
- }
-
- File taskOutput = task.getOutputs().getFiles().getSingleFile();
-
- String mappings = null;
- try {
- Object mappingsObj = ReflectUtil.getProperty(extension, "mappings");
- if (mappingsObj instanceof Provider) {
- mappingsObj = ((Provider>) mappingsObj).get();
- }
- if (mappingsObj != null) {
- mappings = mappingsObj.toString();
- }
- } catch (Exception ignored) {
- }
-
- List accessTransformers = new ArrayList<>();
- try {
- Object atObj = ReflectUtil.getProperty(extension, "accessTransformers");
- if (atObj instanceof FileCollection) {
- accessTransformers.addAll(((FileCollection) atObj).getFiles());
- } else if (atObj instanceof Iterable) {
- for (Object item : (Iterable>) atObj) {
- if (item instanceof File) {
- accessTransformers.add((File) item);
- }
- }
- }
- } catch (Exception ignored) {
- }
-
- return new McpModelFG3Impl(minecraftDepVersions, mappings, taskOutput, task.getName(), accessTransformers);
- }
-
- @Override
- public void reportErrorMessage(
- final @NotNull String modelName,
- final @NotNull Project project,
- final @NotNull ModelBuilderContext context,
- final @NotNull Exception exception
- ) {
- //noinspection UnstableApiUsage
- context.getMessageReporter().createMessage()
- .withGroup(this)
- .withKind(Message.Kind.ERROR)
- .withGroup("com.demonwav.mcdev")
- .withTitle("MinecraftDev: ForgeGradle import error")
- .withText("Unable to build MinecraftDev ForgeGradle model for project " + project.getDisplayName())
- .withException(exception)
- .reportMessage(project);
- }
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3Impl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3Impl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelFG3Impl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,72 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling;
-
-import java.io.File;
-import java.util.List;
-
-final class McpModelFG3Impl implements McpModelFG3, java.io.Serializable {
-
- private final List minecraftDepVersions;
- private final String mcpVersion;
- private final File taskOutputLocation;
- private final String taskName;
- private final List accessTransformers;
-
- McpModelFG3Impl(
- List minecraftDepVersions,
- String mcpVersion,
- File taskOutputLocation,
- String taskName,
- List accessTransformers
- ) {
- this.minecraftDepVersions = minecraftDepVersions;
- this.mcpVersion = mcpVersion;
- this.taskOutputLocation = taskOutputLocation;
- this.taskName = taskName;
- this.accessTransformers = accessTransformers;
- }
-
- @Override
- public List getMinecraftDepVersions() {
- return minecraftDepVersions;
- }
-
- @Override
- public String getMcpVersion() {
- return mcpVersion;
- }
-
- @Override
- public File getTaskOutputLocation() {
- return taskOutputLocation;
- }
-
- @Override
- public String getTaskName() {
- return taskName;
- }
-
- @Override
- public List getAccessTransformers() {
- return accessTransformers;
- }
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelNG7.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelNG7.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelNG7.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,30 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling;
-
-import java.io.File;
-import java.util.List;
-
-public interface McpModelNG7 {
- String getNeoForgeVersion();
- File getMappingsFile();
- List getAccessTransformers();
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelNMD.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelNMD.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/McpModelNMD.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,33 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling;
-
-import org.jetbrains.annotations.Nullable;
-
-import java.io.File;
-import java.util.List;
-
-public interface McpModelNMD {
- @Nullable String getNeoForgeVersion();
- @Nullable String getNeoFormVersion();
- File getMappingsFile();
- List getAccessTransformers();
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/ReflectUtil.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/ReflectUtil.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/ReflectUtil.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,155 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
-public final class ReflectUtil {
-
- private ReflectUtil() {
- }
-
- public static Object getProperty(Object obj, String name) throws Exception {
- if (obj == null) {
- return null;
- }
- Class> clazz = obj.getClass();
- String capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1);
-
- // Try getProperty()
- try {
- Method m = clazz.getMethod("get" + capitalized);
- m.setAccessible(true);
- return m.invoke(obj);
- } catch (NoSuchMethodException ignored) {
- }
-
- // Try isProperty()
- try {
- Method m = clazz.getMethod("is" + capitalized);
- m.setAccessible(true);
- return m.invoke(obj);
- } catch (NoSuchMethodException ignored) {
- }
-
- // Try property()
- try {
- Method m = clazz.getMethod(name);
- m.setAccessible(true);
- return m.invoke(obj);
- } catch (NoSuchMethodException ignored) {
- }
-
- // Try field
- try {
- Field f = clazz.getField(name);
- f.setAccessible(true);
- return f.get(obj);
- } catch (NoSuchFieldException ignored) {
- }
-
- throw new NoSuchMethodException("Could not find property or method '" + name + "' on " + clazz);
- }
-
- public static boolean hasProperty(Object obj, String name) {
- if (obj == null) {
- return false;
- }
- Class> clazz = obj.getClass();
- String capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1);
-
- try {
- clazz.getMethod("get" + capitalized);
- return true;
- } catch (NoSuchMethodException ignored) {
- }
-
- try {
- clazz.getMethod("is" + capitalized);
- return true;
- } catch (NoSuchMethodException ignored) {
- }
-
- try {
- clazz.getMethod(name);
- return true;
- } catch (NoSuchMethodException ignored) {
- }
-
- try {
- clazz.getField(name);
- return true;
- } catch (NoSuchFieldException ignored) {
- }
-
- return false;
- }
-
- public static Object callMethod(Object obj, String methodName, Object... args) throws Exception {
- if (obj == null) {
- return null;
- }
- Class> clazz = obj.getClass();
- Method bestMatch = null;
- for (Method method : clazz.getMethods()) {
- if (method.getName().equals(methodName) && method.getParameterCount() == args.length) {
- if (isCompatible(method.getParameterTypes(), args)) {
- bestMatch = method;
- break;
- }
- }
- }
- if (bestMatch == null) {
- throw new NoSuchMethodException("No compatible method " + methodName + " with " + args.length + " arguments found on " + clazz);
- }
- bestMatch.setAccessible(true);
- return bestMatch.invoke(obj, args);
- }
-
- private static boolean isCompatible(Class>[] parameterTypes, Object[] args) {
- for (int i = 0; i < parameterTypes.length; i++) {
- Object arg = args[i];
- Class> paramType = parameterTypes[i];
- if (arg == null) {
- if (paramType.isPrimitive()) {
- return false;
- }
- continue;
- }
- if (paramType.isPrimitive()) {
- if (paramType == boolean.class && arg instanceof Boolean) continue;
- if (paramType == int.class && arg instanceof Integer) continue;
- if (paramType == long.class && arg instanceof Long) continue;
- if (paramType == double.class && arg instanceof Double) continue;
- if (paramType == float.class && arg instanceof Float) continue;
- if (paramType == char.class && arg instanceof Character) continue;
- if (paramType == byte.class && arg instanceof Byte) continue;
- if (paramType == short.class && arg instanceof Short) continue;
- return false;
- }
- if (!paramType.isInstance(arg)) {
- return false;
- }
- }
- return true;
- }
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModel.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModel.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModel.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,29 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling.archloom;
-
-public interface ArchitecturyModel {
- ModuleType getModuleType();
-
- enum ModuleType {
- NONE, COMMON, PLATFORM_SPECIFIC
- }
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelBuilderImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelBuilderImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelBuilderImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,67 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling.archloom;
-
-import org.gradle.api.Project;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.tooling.Message;
-import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext;
-import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
-
-public final class ArchitecturyModelBuilderImpl implements ModelBuilderService {
-
- @Override
- public boolean canBuild(String modelName) {
- return ArchitecturyModel.class.getName().equals(modelName);
- }
-
- @Override
- public Object buildAll(String modelName, Project project) {
- ArchitecturyModel.ModuleType moduleType = ArchitecturyModel.ModuleType.NONE;
- if (project.getPluginManager().hasPlugin("architectury-plugin")) {
- if (project.getConfigurations().findByName("transformProductionFabric") != null) {
- moduleType = ArchitecturyModel.ModuleType.COMMON;
- } else {
- moduleType = ArchitecturyModel.ModuleType.PLATFORM_SPECIFIC;
- }
- }
-
- return new ArchitecturyModelImpl(moduleType);
- }
-
- @Override
- public void reportErrorMessage(
- final @NotNull String modelName,
- final @NotNull Project project,
- final @NotNull ModelBuilderContext context,
- final @NotNull Exception exception
- ) {
- //noinspection UnstableApiUsage
- context.getMessageReporter().createMessage()
- .withGroup(this)
- .withKind(Message.Kind.ERROR)
- .withGroup("com.demonwav.mcdev")
- .withTitle("MinecraftDev: ArchitecturyLoom import error")
- .withText("Unable to build MinecraftDev ArchitecturyLoom model for project " + project.getDisplayName())
- .withException(exception)
- .reportMessage(project);
- }
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/archloom/ArchitecturyModelImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,36 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling.archloom;
-
-import java.io.Serializable;
-
-final class ArchitecturyModelImpl implements ArchitecturyModel, Serializable {
- private final ModuleType moduleType;
-
- ArchitecturyModelImpl(ModuleType moduleType) {
- this.moduleType = moduleType;
- }
-
- @Override
- public ModuleType getModuleType() {
- return moduleType;
- }
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModel.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModel.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModel.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,48 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling.fabricloom;
-
-import org.jetbrains.annotations.Nullable;
-
-import java.io.File;
-import java.util.List;
-import java.util.Map;
-
-public interface FabricLoomModel {
-
- String getMinecraftVersion();
-
- @Nullable
- File getTinyMappings();
-
- Map> getDecompilers();
-
- boolean getSplitMinecraftJar();
-
- interface DecompilerModel {
-
- String getName();
-
- String getTaskName();
-
- String getSourcesPath();
- }
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelBuilderImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelBuilderImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelBuilderImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,187 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling.fabricloom;
-
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.ReflectUtil;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.gradle.api.Project;
-import org.gradle.api.provider.Provider;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.tooling.AbstractModelBuilderService;
-import org.jetbrains.plugins.gradle.tooling.Message;
-import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext;
-
-public final class FabricLoomModelBuilderImpl extends AbstractModelBuilderService {
-
- @Override
- public boolean canBuild(String modelName) {
- return FabricLoomModel.class.getName().equals(modelName);
- }
-
- @Override
- public Object buildAll(@NotNull String modelName, @NotNull Project project, @NotNull ModelBuilderContext context) {
- if (!project.getPlugins().hasPlugin("fabric-loom")) {
- return null;
- }
-
- Object loomExtension = project.getExtensions().getByName("loom");
-
- try {
- return build(project, loomExtension);
- } catch (Exception ex) {
- //noinspection UnstableApiUsage
- context.getMessageReporter().createMessage()
- .withGroup("com.demonwav.mcdev")
- .withTitle("Minecraft Dev: Loom import error")
- .withText("An error occurred while importing Loom data, falling back to legacy import")
- .withKind(Message.Kind.WARNING)
- .withStackTrace()
- .withException(ex)
- .reportMessage(project);
-
- try {
- // Must be using an older loom version, fallback.
- return buildLegacy(project, loomExtension);
- } catch (Exception fallbackEx) {
- // Return null if even legacy fallback fails
- return null;
- }
- }
- }
-
- private FabricLoomModel build(Project project, Object loomExtension) throws Exception {
- Object minecraftProvider = ReflectUtil.getProperty(loomExtension, "minecraftProvider");
- String minecraftVersion = (String) ReflectUtil.callMethod(minecraftProvider, "minecraftVersion");
-
- File tinyMappings = null;
- if (ReflectUtil.hasProperty(loomExtension, "mappingsFile")) {
- Object mappingsFileObj = ReflectUtil.getProperty(loomExtension, "mappingsFile");
- if (mappingsFileObj instanceof Provider) {
- mappingsFileObj = ((Provider>) mappingsFileObj).getOrNull();
- }
- if (mappingsFileObj instanceof File) {
- tinyMappings = (File) mappingsFileObj;
- } else if (mappingsFileObj != null) {
- tinyMappings = project.file(mappingsFileObj);
- }
- }
-
- boolean splitMinecraftJar = (Boolean) ReflectUtil.callMethod(loomExtension, "areEnvironmentSourceSetsSplit");
-
- Map> decompilers = new HashMap<>();
-
- if (splitMinecraftJar) {
- decompilers.put("common", getDecompilers(loomExtension, false));
- decompilers.put("client", getDecompilers(loomExtension, true));
- } else {
- decompilers.put("single", getDecompilers(loomExtension, false));
- }
-
- return new FabricLoomModelImpl(minecraftVersion, tinyMappings, decompilers, splitMinecraftJar);
- }
-
- private List getDecompilers(Object loomExtension, boolean client) throws Exception {
- Object decompilerOptions = ReflectUtil.getProperty(loomExtension, "decompilerOptions");
- List result = new ArrayList<>();
- if (decompilerOptions instanceof Iterable) {
- for (Object option : (Iterable>) decompilerOptions) {
- Object task = ReflectUtil.callMethod(loomExtension, "getDecompileTask", option, client);
- String sourcesPath;
- if (ReflectUtil.hasProperty(task, "outputJar")) {
- // Pre 1.8
- Object outputJar = ReflectUtil.getProperty(task, "outputJar");
- if (outputJar instanceof Provider) {
- outputJar = ((Provider>) outputJar).get();
- }
- sourcesPath = ((File) ReflectUtil.callMethod(outputJar, "getAsFile")).getAbsolutePath();
- } else {
- Object sourcesOutputJar = ReflectUtil.getProperty(task, "sourcesOutputJar");
- if (sourcesOutputJar instanceof Provider) {
- sourcesOutputJar = ((Provider>) sourcesOutputJar).get();
- }
- sourcesPath = ((File) ReflectUtil.callMethod(sourcesOutputJar, "getAsFile")).getAbsolutePath();
- }
- String name = (String) ReflectUtil.getProperty(option, "name");
- String taskName = (String) ReflectUtil.getProperty(task, "name");
- result.add(new FabricLoomModelImpl.DecompilerModelImpl(name, taskName, sourcesPath));
- }
- }
- return result;
- }
-
- private FabricLoomModel buildLegacy(Project project, Object loomExtension) throws Exception {
- Object mappingsProvider = ReflectUtil.getProperty(loomExtension, "mappingsProvider");
- Object tinyMappingsObj = ReflectUtil.getProperty(mappingsProvider, "tinyMappings");
- File tinyMappings = null;
- if (tinyMappingsObj instanceof File) {
- tinyMappings = ((File) tinyMappingsObj).getAbsoluteFile();
- } else if (tinyMappingsObj != null) {
- tinyMappings = project.file(tinyMappingsObj).getAbsoluteFile();
- }
-
- Object decompilerOptions = ReflectUtil.getProperty(loomExtension, "decompilerOptions");
- List decompilers = new ArrayList<>();
- if (decompilerOptions instanceof Iterable) {
- for (Object option : (Iterable>) decompilerOptions) {
- String optionName = (String) ReflectUtil.getProperty(option, "name");
- String capitalized = Character.toUpperCase(optionName.charAt(0)) + optionName.substring(1);
- Object task = project.getTasks().getByName("genSourcesWith" + capitalized);
-
- Object runtimeJar = ReflectUtil.getProperty(task, "runtimeJar");
- if (runtimeJar instanceof Provider) {
- runtimeJar = ((Provider>) runtimeJar).get();
- }
- File runtimeJarFile = (File) ReflectUtil.callMethod(runtimeJar, "getAsFile");
- String runtimeJarPath = runtimeJarFile.getAbsolutePath();
- String sourcesPath = runtimeJarPath.substring(0, runtimeJarPath.length() - 4) + "-sources.jar";
-
- String taskName = (String) ReflectUtil.getProperty(task, "name");
- decompilers.add(new FabricLoomModelImpl.DecompilerModelImpl(optionName, taskName, sourcesPath));
- }
- }
-
- Map> decompilersMap = new HashMap<>();
- decompilersMap.put("single", decompilers);
- return new FabricLoomModelImpl(tinyMappings, decompilersMap, false);
- }
-
- @Override
- public void reportErrorMessage(
- final @NotNull String modelName,
- final @NotNull Project project,
- final @NotNull ModelBuilderContext context,
- final @NotNull Exception exception
- ) {
- //noinspection UnstableApiUsage
- context.getMessageReporter().createMessage()
- .withGroup(this)
- .withKind(Message.Kind.ERROR)
- .withGroup("com.demonwav.mcdev")
- .withTitle("MinecraftDev: Loom import error")
- .withText("Unable to build MinecraftDev FabricLoom model for project " + project.getDisplayName())
- .withException(exception)
- .reportMessage(project);
- }
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/fabricloom/FabricLoomModelImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,104 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling.fabricloom;
-
-import org.jetbrains.annotations.Nullable;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.List;
-import java.util.Map;
-
-public final class FabricLoomModelImpl implements FabricLoomModel, Serializable {
-
- private final String minecraftVersion;
- private final File tinyMappings;
- private final Map> decompilers;
- private final boolean splitMinecraftJar;
-
- public FabricLoomModelImpl(
- String minecraftVersion,
- @Nullable File tinyMappings,
- Map> decompilers,
- boolean splitMinecraftJar
- ) {
- this.minecraftVersion = minecraftVersion;
- this.tinyMappings = tinyMappings;
- this.decompilers = decompilers;
- this.splitMinecraftJar = splitMinecraftJar;
- }
-
- public FabricLoomModelImpl(
- @Nullable File tinyMappings,
- Map> decompilers,
- boolean splitMinecraftJar
- ) {
- this(null, tinyMappings, decompilers, splitMinecraftJar);
- }
-
- @Override
- public String getMinecraftVersion() {
- return minecraftVersion;
- }
-
- @Override
- @Nullable
- public File getTinyMappings() {
- return tinyMappings;
- }
-
- @Override
- public Map> getDecompilers() {
- return decompilers;
- }
-
- @Override
- public boolean getSplitMinecraftJar() {
- return splitMinecraftJar;
- }
-
- public static final class DecompilerModelImpl implements DecompilerModel, Serializable {
- private final String name;
- private final String taskName;
- private final String sourcesPath;
-
- public DecompilerModelImpl(String name, String taskName, String sourcesPath) {
- this.name = name;
- this.taskName = taskName;
- this.sourcesPath = sourcesPath;
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public String getTaskName() {
- return taskName;
- }
-
- @Override
- public String getSourcesPath() {
- return sourcesPath;
- }
- }
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelBuilderImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelBuilderImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelBuilderImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,142 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling.neogradle;
-
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNG7;
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.ReflectUtil;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import org.gradle.api.Project;
-import org.gradle.api.Task;
-import org.gradle.api.file.FileCollection;
-import org.gradle.api.provider.Provider;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.tooling.Message;
-import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext;
-import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
-
-public final class NeoGradle7ModelBuilderImpl implements ModelBuilderService {
-
- @Override
- public boolean canBuild(String modelName) {
- return McpModelNG7.class.getName().equals(modelName);
- }
-
- @Override
- public Object buildAll(String modelName, Project project) {
- Object extension = project.getExtensions().findByName("minecraft");
- if (extension == null) {
- return null;
- }
-
- if (project.getPlugins().findPlugin("net.neoforged.gradle.userdev") == null) {
- return null;
- }
-
- Object userDevRuntime = project.getExtensions().findByName("userDevRuntime");
- if (userDevRuntime == null) {
- return null;
- }
-
- String neoforgeVersion = null;
- try {
- Object runtimesObj = ReflectUtil.getProperty(userDevRuntime, "runtimes");
- if (runtimesObj instanceof Provider) {
- runtimesObj = ((Provider>) runtimesObj).get();
- }
- if (runtimesObj instanceof Map) {
- for (Map.Entry, ?> entry : ((Map, ?>) runtimesObj).entrySet()) {
- Object val = entry.getValue();
- Object spec = ReflectUtil.getProperty(val, "specification");
- Object forgeVersion = ReflectUtil.getProperty(spec, "forgeVersion");
- if (forgeVersion != null) {
- neoforgeVersion = forgeVersion.toString();
- break;
- }
- }
- }
- } catch (Exception ignored) {
- }
-
- if (neoforgeVersion == null) {
- return null;
- }
-
- Task neoFormMergeMappings = project.getTasks().findByName("neoFormMergeMappings");
- if (neoFormMergeMappings == null) {
- return null;
- }
-
- File mappingsFile = null;
- try {
- Object output = ReflectUtil.getProperty(neoFormMergeMappings, "output");
- if (output instanceof Provider) {
- output = ((Provider>) output).get();
- }
- if (output instanceof File) {
- mappingsFile = (File) output;
- } else if (output != null) {
- mappingsFile = (File) ReflectUtil.callMethod(output, "getAsFile");
- }
- } catch (Exception ignored) {
- }
-
- List accessTransformers = new ArrayList<>();
- try {
- Object atObj = ReflectUtil.getProperty(extension, "accessTransformers");
- if (atObj instanceof FileCollection) {
- accessTransformers.addAll(((FileCollection) atObj).getFiles());
- } else if (atObj != null) {
- Object filesObj = ReflectUtil.getProperty(atObj, "files");
- if (filesObj instanceof Iterable) {
- for (Object file : (Iterable>) filesObj) {
- if (file instanceof File) {
- accessTransformers.add((File) file);
- }
- }
- }
- }
- } catch (Exception ignored) {
- }
-
- return new NeoGradle7ModelImpl(neoforgeVersion, mappingsFile, accessTransformers);
- }
-
- @Override
- public void reportErrorMessage(
- final @NotNull String modelName,
- final @NotNull Project project,
- final @NotNull ModelBuilderContext context,
- final @NotNull Exception exception
- ) {
- //noinspection UnstableApiUsage
- context.getMessageReporter().createMessage()
- .withGroup(this)
- .withKind(Message.Kind.ERROR)
- .withGroup("com.demonwav.mcdev")
- .withTitle("MinecraftDev: NeoGradle import error")
- .withText("Unable to build MinecraftDev NeoGradle model for project " + project.getDisplayName())
- .withException(exception)
- .reportMessage(project);
- }
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neogradle/NeoGradle7ModelImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,58 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling.neogradle;
-
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNG7;
-import java.io.File;
-import java.io.Serializable;
-import java.util.List;
-
-final class NeoGradle7ModelImpl implements McpModelNG7, Serializable {
-
- private final String neoForgeVersion;
- private final File mappingsFile;
- private final List accessTransformers;
-
- NeoGradle7ModelImpl(
- String neoForgeVersion,
- File mappingsFile,
- List accessTransformers
- ) {
- this.neoForgeVersion = neoForgeVersion;
- this.mappingsFile = mappingsFile;
- this.accessTransformers = accessTransformers;
- }
-
- @Override
- public String getNeoForgeVersion() {
- return neoForgeVersion;
- }
-
- @Override
- public File getMappingsFile() {
- return mappingsFile;
- }
-
- @Override
- public List getAccessTransformers() {
- return accessTransformers;
- }
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelBuilderImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelBuilderImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelBuilderImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,149 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling.neomoddev;
-
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNMD;
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.ReflectUtil;
-import java.io.File;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Stream;
-import org.gradle.api.Project;
-import org.gradle.api.file.Directory;
-import org.gradle.api.file.FileCollection;
-import org.gradle.api.provider.ListProperty;
-import org.gradle.api.provider.Provider;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.tooling.Message;
-import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext;
-import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
-
-public final class NeoModDevGradleModelBuilderImpl implements ModelBuilderService {
-
- @Override
- public boolean canBuild(String modelName) {
- return McpModelNMD.class.getName().equals(modelName);
- }
-
- @Override
- public Object buildAll(String modelName, Project project) {
- Object extension = project.getExtensions().findByName("neoForge");
- if (extension == null) {
- return null;
- }
-
- if (project.getPlugins().findPlugin("net.neoforged.moddev") == null) {
- return null;
- }
-
- String neoFormVersion = null;
- try {
- Object neoFormVersionProp = ReflectUtil.getProperty(extension, "neoFormVersion");
- if (neoFormVersionProp instanceof String) {
- neoFormVersion = (String) neoFormVersionProp;
- } else if (neoFormVersionProp instanceof Provider) {
- neoFormVersion = (String) ((Provider>) neoFormVersionProp).getOrNull();
- }
- } catch (Exception ignored) {
- // Happens when the NeoForm version is not set or throws
- }
-
- String neoforgeVersion = null;
- if (neoFormVersion == null) {
- try {
- Object neoforgeVersionProp = ReflectUtil.getProperty(extension, "version");
- if (neoforgeVersionProp instanceof String) {
- neoforgeVersion = (String) neoforgeVersionProp;
- } else if (neoforgeVersionProp instanceof Provider) {
- neoforgeVersion = (String) ((Provider>) neoforgeVersionProp).getOrNull();
- }
- } catch (Exception ignored) {
- }
- if (neoforgeVersion == null) {
- return null;
- }
- }
-
- List accessTransformers = new ArrayList<>();
- try {
- Object accessTransformersRaw = ReflectUtil.getProperty(extension, "accessTransformers");
- if (accessTransformersRaw instanceof ListProperty) {
- ListProperty> listProperty = (ListProperty>) accessTransformersRaw;
- for (Object it : listProperty.get()) {
- accessTransformers.add(project.file(it));
- }
- } else if (accessTransformersRaw instanceof FileCollection) {
- accessTransformers.addAll(((FileCollection) accessTransformersRaw).getFiles());
- } else if (accessTransformersRaw != null) {
- Object filesObj = ReflectUtil.getProperty(accessTransformersRaw, "files");
- if (filesObj instanceof Iterable) {
- for (Object file : (Iterable>) filesObj) {
- if (file instanceof File) {
- accessTransformers.add((File) file);
- }
- }
- }
- }
- } catch (Exception ignored) {
- }
-
- File mappingsFile = null;
- try {
- Directory neoformDir = project.getLayout().getBuildDirectory().dir("neoForm").getOrNull();
- if (neoformDir != null) {
- final Path neoformDirPath = neoformDir.getAsFile().toPath();
- if (Files.exists(neoformDirPath)) {
- try (Stream stream = Files.list(neoformDirPath)) {
- mappingsFile = stream
- .map(p -> p.resolve("config/joined.tsrg"))
- .filter(Files::exists)
- .findFirst()
- .map(Path::toFile)
- .orElse(null);
- }
- }
- }
- } catch (Exception ignored) {
- }
-
- return new NeoModDevGradleModelImpl(neoforgeVersion, neoFormVersion, mappingsFile, accessTransformers);
- }
-
- @Override
- public void reportErrorMessage(
- final @NotNull String modelName,
- final @NotNull Project project,
- final @NotNull ModelBuilderContext context,
- final @NotNull Exception exception
- ) {
- //noinspection UnstableApiUsage
- context.getMessageReporter().createMessage()
- .withGroup(this)
- .withKind(Message.Kind.ERROR)
- .withGroup("com.demonwav.mcdev")
- .withTitle("MinecraftDev: NeoModDev import error")
- .withText("Unable to build MinecraftDev NeoModDev model for project " + project.getDisplayName())
- .withException(exception)
- .reportMessage(project);
- }
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/neomoddev/NeoModDevGradleModelImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,70 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling.neomoddev;
-
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNMD;
-import org.jetbrains.annotations.Nullable;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.List;
-
-final class NeoModDevGradleModelImpl implements McpModelNMD, Serializable {
-
- private final String neoForgeVersion;
- private final String neoFormVersion;
- private final File mappingsFile;
- private final List accessTransformers;
-
- NeoModDevGradleModelImpl(
- String neoForgeVersion,
- String neoFormVersion,
- File mappingsFile,
- List accessTransformers
- ) {
- this.neoForgeVersion = neoForgeVersion;
- this.neoFormVersion = neoFormVersion;
- this.mappingsFile = mappingsFile;
- this.accessTransformers = accessTransformers;
- }
-
- @Override
- @Nullable
- public String getNeoForgeVersion() {
- return neoForgeVersion;
- }
-
- @Override
- @Nullable
- public String getNeoFormVersion() {
- return neoFormVersion;
- }
-
- @Override
- public File getMappingsFile() {
- return mappingsFile;
- }
-
- @Override
- public List getAccessTransformers() {
- return accessTransformers;
- }
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModel.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModel.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModel.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,26 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling.vanillagradle;
-
-public interface VanillaGradleModel {
-
- boolean hasVanillaGradle();
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelBuilderImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelBuilderImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelBuilderImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,58 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling.vanillagradle;
-
-import org.gradle.api.Project;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.tooling.Message;
-import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext;
-import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
-
-public final class VanillaGradleModelBuilderImpl implements ModelBuilderService {
-
- @Override
- public boolean canBuild(String modelName) {
- return VanillaGradleModel.class.getName().equals(modelName);
- }
-
- @Override
- public Object buildAll(String modelName, Project project) {
- return new VanillaGradleModelImpl(project.getPlugins().hasPlugin("org.spongepowered.gradle.vanilla"));
- }
-
- @Override
- public void reportErrorMessage(
- final @NotNull String modelName,
- final @NotNull Project project,
- final @NotNull ModelBuilderContext context,
- final @NotNull Exception exception
- ) {
- //noinspection UnstableApiUsage
- context.getMessageReporter().createMessage()
- .withGroup(this)
- .withKind(Message.Kind.ERROR)
- .withGroup("com.demonwav.mcdev")
- .withTitle("MinecraftDev: VanillaGradle import error")
- .withText("Unable to build MinecraftDev VanillaGradle model for project " + project.getDisplayName())
- .withException(exception)
- .reportMessage(project);
- }
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/mcp/gradle/tooling/vanillagradle/VanillaGradleModelImpl.java (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,37 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.tooling.vanillagradle;
-
-import java.io.Serializable;
-
-final class VanillaGradleModelImpl implements VanillaGradleModel, Serializable {
-
- private final boolean hasVanillaGradle;
-
- VanillaGradleModelImpl(boolean hasVanillaGradle) {
- this.hasVanillaGradle = hasVanillaGradle;
- }
-
- @Override
- public boolean hasVanillaGradle() {
- return hasVanillaGradle;
- }
-}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModel.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModel.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModel.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,25 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling;
+
+public interface MinecraftModel {
+ String getMcpVersion();
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG2.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG2.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG2.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,28 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling;
+
+import java.util.Set;
+
+public interface MinecraftModelFG2 extends MinecraftModel {
+ String getMinecraftVersion();
+ Set getMappingFiles();
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG2BuilderImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG2BuilderImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG2BuilderImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,85 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling;
+
+import org.gradle.api.Project;
+import org.gradle.api.Task;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.tooling.Message;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class MinecraftModelFG2BuilderImpl implements ModelBuilderService {
+
+ @Override
+ public boolean canBuild(String modelName) {
+ return MinecraftModelFG2.class.getName().equals(modelName);
+ }
+
+ @Override
+ public Object buildAll(String modelName, Project project) {
+ Object extension = project.getExtensions().findByName("minecraft");
+ if (extension == null) {
+ return null;
+ }
+
+ Task genSrgs = project.getTasks().findByName("genSrgs");
+ if (genSrgs == null) {
+ return null;
+ }
+
+ try {
+ String version = (String) ReflectUtil.getProperty(extension, "version");
+ String mappings = (String) ReflectUtil.getProperty(extension, "mappings");
+
+ Set files = genSrgs.getOutputs().getFiles().getFiles();
+ Set mappingFiles = new HashSet<>();
+ for (File file : files) {
+ mappingFiles.add(file.getAbsolutePath());
+ }
+ return new MinecraftModelFG2Impl(version, mappings, mappingFiles);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ @Override
+ public void reportErrorMessage(
+ final @NotNull String modelName,
+ final @NotNull Project project,
+ final @NotNull ModelBuilderContext context,
+ final @NotNull Exception exception
+ ) {
+ //noinspection UnstableApiUsage
+ context.getMessageReporter().createMessage()
+ .withGroup(this)
+ .withKind(Message.Kind.ERROR)
+ .withGroup("com.demonwav.mcdev")
+ .withTitle("MinecraftDev: ForgeGradle import error")
+ .withText("Unable to build MinecraftDev ForgeGradle model for project " + project.getDisplayName())
+ .withException(exception)
+ .reportMessage(project);
+ }
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG2Impl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG2Impl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG2Impl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,51 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling;
+
+import java.util.Set;
+
+final class MinecraftModelFG2Impl implements MinecraftModelFG2, java.io.Serializable {
+
+ private final String minecraftVersion;
+ private final String mcpVersion;
+ private final Set mappingFiles;
+
+ MinecraftModelFG2Impl(String minecraftVersion, String mcpVersion, Set mappingFiles) {
+ this.minecraftVersion = minecraftVersion;
+ this.mcpVersion = mcpVersion;
+ this.mappingFiles = mappingFiles;
+ }
+
+ @Override
+ public String getMinecraftVersion() {
+ return minecraftVersion;
+ }
+
+ @Override
+ public String getMcpVersion() {
+ return mcpVersion;
+ }
+
+ @Override
+ public Set getMappingFiles() {
+ return mappingFiles;
+ }
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG3.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG3.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG3.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,31 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling;
+
+import java.io.File;
+import java.util.List;
+
+public interface MinecraftModelFG3 extends MinecraftModel {
+ List getMinecraftDepVersions();
+ File getTaskOutputLocation();
+ String getTaskName();
+ List getAccessTransformers();
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG3BuilderImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG3BuilderImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG3BuilderImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,121 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling;
+
+import org.gradle.api.Project;
+import org.gradle.api.Task;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.provider.Provider;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.tooling.Message;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class MinecraftModelFG3BuilderImpl implements ModelBuilderService {
+
+ @Override
+ public boolean canBuild(String modelName) {
+ return MinecraftModelFG3.class.getName().equals(modelName);
+ }
+
+ @Override
+ public Object buildAll(String modelName, Project project) {
+ Object extension = project.getExtensions().findByName("minecraft");
+ if (extension == null) {
+ return null;
+ }
+
+ if (project.getPlugins().findPlugin("net.minecraftforge.gradle") == null) {
+ return null;
+ }
+
+ List minecraftDepVersions = new ArrayList<>();
+ Configuration minecraftConfig = project.getConfigurations().findByName("minecraft");
+ if (minecraftConfig != null) {
+ for (Dependency dep : minecraftConfig.getDependencies()) {
+ minecraftDepVersions.add(dep.getVersion());
+ }
+ }
+
+ Task task = project.getTasks().findByName("createMcpToSrg");
+ if (task == null) {
+ task = project.getTasks().findByName("createMcp2Srg");
+ }
+ if (task == null) {
+ return null;
+ }
+
+ File taskOutput = task.getOutputs().getFiles().getSingleFile();
+
+ String mappings = null;
+ try {
+ Object mappingsObj = ReflectUtil.getProperty(extension, "mappings");
+ if (mappingsObj instanceof Provider) {
+ mappingsObj = ((Provider>) mappingsObj).get();
+ }
+ if (mappingsObj != null) {
+ mappings = mappingsObj.toString();
+ }
+ } catch (Exception ignored) {
+ }
+
+ List accessTransformers = new ArrayList<>();
+ try {
+ Object atObj = ReflectUtil.getProperty(extension, "accessTransformers");
+ if (atObj instanceof FileCollection) {
+ accessTransformers.addAll(((FileCollection) atObj).getFiles());
+ } else if (atObj instanceof Iterable) {
+ for (Object item : (Iterable>) atObj) {
+ if (item instanceof File) {
+ accessTransformers.add((File) item);
+ }
+ }
+ }
+ } catch (Exception ignored) {
+ }
+
+ return new MinecraftModelFG3Impl(minecraftDepVersions, mappings, taskOutput, task.getName(), accessTransformers);
+ }
+
+ @Override
+ public void reportErrorMessage(
+ final @NotNull String modelName,
+ final @NotNull Project project,
+ final @NotNull ModelBuilderContext context,
+ final @NotNull Exception exception
+ ) {
+ //noinspection UnstableApiUsage
+ context.getMessageReporter().createMessage()
+ .withGroup(this)
+ .withKind(Message.Kind.ERROR)
+ .withGroup("com.demonwav.mcdev")
+ .withTitle("MinecraftDev: ForgeGradle import error")
+ .withText("Unable to build MinecraftDev ForgeGradle model for project " + project.getDisplayName())
+ .withException(exception)
+ .reportMessage(project);
+ }
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG3Impl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG3Impl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelFG3Impl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,72 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling;
+
+import java.io.File;
+import java.util.List;
+
+final class MinecraftModelFG3Impl implements MinecraftModelFG3, java.io.Serializable {
+
+ private final List minecraftDepVersions;
+ private final String mcpVersion;
+ private final File taskOutputLocation;
+ private final String taskName;
+ private final List accessTransformers;
+
+ MinecraftModelFG3Impl(
+ List minecraftDepVersions,
+ String mcpVersion,
+ File taskOutputLocation,
+ String taskName,
+ List accessTransformers
+ ) {
+ this.minecraftDepVersions = minecraftDepVersions;
+ this.mcpVersion = mcpVersion;
+ this.taskOutputLocation = taskOutputLocation;
+ this.taskName = taskName;
+ this.accessTransformers = accessTransformers;
+ }
+
+ @Override
+ public List getMinecraftDepVersions() {
+ return minecraftDepVersions;
+ }
+
+ @Override
+ public String getMcpVersion() {
+ return mcpVersion;
+ }
+
+ @Override
+ public File getTaskOutputLocation() {
+ return taskOutputLocation;
+ }
+
+ @Override
+ public String getTaskName() {
+ return taskName;
+ }
+
+ @Override
+ public List getAccessTransformers() {
+ return accessTransformers;
+ }
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelNG7.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelNG7.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelNG7.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,30 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling;
+
+import java.io.File;
+import java.util.List;
+
+public interface MinecraftModelNG7 {
+ String getNeoForgeVersion();
+ File getMappingsFile();
+ List getAccessTransformers();
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelNMD.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelNMD.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/MinecraftModelNMD.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,33 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling;
+
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.List;
+
+public interface MinecraftModelNMD {
+ @Nullable String getNeoForgeVersion();
+ @Nullable String getNeoFormVersion();
+ File getMappingsFile();
+ List getAccessTransformers();
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/ReflectUtil.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/ReflectUtil.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/ReflectUtil.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,155 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+public final class ReflectUtil {
+
+ private ReflectUtil() {
+ }
+
+ public static Object getProperty(Object obj, String name) throws Exception {
+ if (obj == null) {
+ return null;
+ }
+ Class> clazz = obj.getClass();
+ String capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1);
+
+ // Try getProperty()
+ try {
+ Method m = clazz.getMethod("get" + capitalized);
+ m.setAccessible(true);
+ return m.invoke(obj);
+ } catch (NoSuchMethodException ignored) {
+ }
+
+ // Try isProperty()
+ try {
+ Method m = clazz.getMethod("is" + capitalized);
+ m.setAccessible(true);
+ return m.invoke(obj);
+ } catch (NoSuchMethodException ignored) {
+ }
+
+ // Try property()
+ try {
+ Method m = clazz.getMethod(name);
+ m.setAccessible(true);
+ return m.invoke(obj);
+ } catch (NoSuchMethodException ignored) {
+ }
+
+ // Try field
+ try {
+ Field f = clazz.getField(name);
+ f.setAccessible(true);
+ return f.get(obj);
+ } catch (NoSuchFieldException ignored) {
+ }
+
+ throw new NoSuchMethodException("Could not find property or method '" + name + "' on " + clazz);
+ }
+
+ public static boolean hasProperty(Object obj, String name) {
+ if (obj == null) {
+ return false;
+ }
+ Class> clazz = obj.getClass();
+ String capitalized = Character.toUpperCase(name.charAt(0)) + name.substring(1);
+
+ try {
+ clazz.getMethod("get" + capitalized);
+ return true;
+ } catch (NoSuchMethodException ignored) {
+ }
+
+ try {
+ clazz.getMethod("is" + capitalized);
+ return true;
+ } catch (NoSuchMethodException ignored) {
+ }
+
+ try {
+ clazz.getMethod(name);
+ return true;
+ } catch (NoSuchMethodException ignored) {
+ }
+
+ try {
+ clazz.getField(name);
+ return true;
+ } catch (NoSuchFieldException ignored) {
+ }
+
+ return false;
+ }
+
+ public static Object callMethod(Object obj, String methodName, Object... args) throws Exception {
+ if (obj == null) {
+ return null;
+ }
+ Class> clazz = obj.getClass();
+ Method bestMatch = null;
+ for (Method method : clazz.getMethods()) {
+ if (method.getName().equals(methodName) && method.getParameterCount() == args.length) {
+ if (isCompatible(method.getParameterTypes(), args)) {
+ bestMatch = method;
+ break;
+ }
+ }
+ }
+ if (bestMatch == null) {
+ throw new NoSuchMethodException("No compatible method " + methodName + " with " + args.length + " arguments found on " + clazz);
+ }
+ bestMatch.setAccessible(true);
+ return bestMatch.invoke(obj, args);
+ }
+
+ private static boolean isCompatible(Class>[] parameterTypes, Object[] args) {
+ for (int i = 0; i < parameterTypes.length; i++) {
+ Object arg = args[i];
+ Class> paramType = parameterTypes[i];
+ if (arg == null) {
+ if (paramType.isPrimitive()) {
+ return false;
+ }
+ continue;
+ }
+ if (paramType.isPrimitive()) {
+ if (paramType == boolean.class && arg instanceof Boolean) continue;
+ if (paramType == int.class && arg instanceof Integer) continue;
+ if (paramType == long.class && arg instanceof Long) continue;
+ if (paramType == double.class && arg instanceof Double) continue;
+ if (paramType == float.class && arg instanceof Float) continue;
+ if (paramType == char.class && arg instanceof Character) continue;
+ if (paramType == byte.class && arg instanceof Byte) continue;
+ if (paramType == short.class && arg instanceof Short) continue;
+ return false;
+ }
+ if (!paramType.isInstance(arg)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/archloom/ArchitecturyModel.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/archloom/ArchitecturyModel.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/archloom/ArchitecturyModel.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,29 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling.archloom;
+
+public interface ArchitecturyModel {
+ ModuleType getModuleType();
+
+ enum ModuleType {
+ NONE, COMMON, PLATFORM_SPECIFIC
+ }
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/archloom/ArchitecturyModelBuilderImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/archloom/ArchitecturyModelBuilderImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/archloom/ArchitecturyModelBuilderImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,67 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling.archloom;
+
+import org.gradle.api.Project;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.tooling.Message;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+
+public final class ArchitecturyModelBuilderImpl implements ModelBuilderService {
+
+ @Override
+ public boolean canBuild(String modelName) {
+ return ArchitecturyModel.class.getName().equals(modelName);
+ }
+
+ @Override
+ public Object buildAll(String modelName, Project project) {
+ ArchitecturyModel.ModuleType moduleType = ArchitecturyModel.ModuleType.NONE;
+ if (project.getPluginManager().hasPlugin("architectury-plugin")) {
+ if (project.getConfigurations().findByName("transformProductionFabric") != null) {
+ moduleType = ArchitecturyModel.ModuleType.COMMON;
+ } else {
+ moduleType = ArchitecturyModel.ModuleType.PLATFORM_SPECIFIC;
+ }
+ }
+
+ return new ArchitecturyModelImpl(moduleType);
+ }
+
+ @Override
+ public void reportErrorMessage(
+ final @NotNull String modelName,
+ final @NotNull Project project,
+ final @NotNull ModelBuilderContext context,
+ final @NotNull Exception exception
+ ) {
+ //noinspection UnstableApiUsage
+ context.getMessageReporter().createMessage()
+ .withGroup(this)
+ .withKind(Message.Kind.ERROR)
+ .withGroup("com.demonwav.mcdev")
+ .withTitle("MinecraftDev: ArchitecturyLoom import error")
+ .withText("Unable to build MinecraftDev ArchitecturyLoom model for project " + project.getDisplayName())
+ .withException(exception)
+ .reportMessage(project);
+ }
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/archloom/ArchitecturyModelImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/archloom/ArchitecturyModelImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/archloom/ArchitecturyModelImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,36 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling.archloom;
+
+import java.io.Serializable;
+
+final class ArchitecturyModelImpl implements ArchitecturyModel, Serializable {
+ private final ModuleType moduleType;
+
+ ArchitecturyModelImpl(ModuleType moduleType) {
+ this.moduleType = moduleType;
+ }
+
+ @Override
+ public ModuleType getModuleType() {
+ return moduleType;
+ }
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/fabricloom/FabricLoomModel.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/fabricloom/FabricLoomModel.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/fabricloom/FabricLoomModel.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,48 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling.fabricloom;
+
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+public interface FabricLoomModel {
+
+ String getMinecraftVersion();
+
+ @Nullable
+ File getTinyMappings();
+
+ Map> getDecompilers();
+
+ boolean getSplitMinecraftJar();
+
+ interface DecompilerModel {
+
+ String getName();
+
+ String getTaskName();
+
+ String getSourcesPath();
+ }
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/fabricloom/FabricLoomModelBuilderImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/fabricloom/FabricLoomModelBuilderImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/fabricloom/FabricLoomModelBuilderImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,187 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling.fabricloom;
+
+import com.demonwav.mcdev.platform.minecraft.gradle.tooling.ReflectUtil;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.gradle.api.Project;
+import org.gradle.api.provider.Provider;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.tooling.AbstractModelBuilderService;
+import org.jetbrains.plugins.gradle.tooling.Message;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext;
+
+public final class FabricLoomModelBuilderImpl extends AbstractModelBuilderService {
+
+ @Override
+ public boolean canBuild(String modelName) {
+ return FabricLoomModel.class.getName().equals(modelName);
+ }
+
+ @Override
+ public Object buildAll(@NotNull String modelName, @NotNull Project project, @NotNull ModelBuilderContext context) {
+ if (!project.getPlugins().hasPlugin("fabric-loom")) {
+ return null;
+ }
+
+ Object loomExtension = project.getExtensions().getByName("loom");
+
+ try {
+ return build(project, loomExtension);
+ } catch (Exception ex) {
+ //noinspection UnstableApiUsage
+ context.getMessageReporter().createMessage()
+ .withGroup("com.demonwav.mcdev")
+ .withTitle("Minecraft Dev: Loom import error")
+ .withText("An error occurred while importing Loom data, falling back to legacy import")
+ .withKind(Message.Kind.WARNING)
+ .withStackTrace()
+ .withException(ex)
+ .reportMessage(project);
+
+ try {
+ // Must be using an older loom version, fallback.
+ return buildLegacy(project, loomExtension);
+ } catch (Exception fallbackEx) {
+ // Return null if even legacy fallback fails
+ return null;
+ }
+ }
+ }
+
+ private FabricLoomModel build(Project project, Object loomExtension) throws Exception {
+ Object minecraftProvider = ReflectUtil.getProperty(loomExtension, "minecraftProvider");
+ String minecraftVersion = (String) ReflectUtil.callMethod(minecraftProvider, "minecraftVersion");
+
+ File tinyMappings = null;
+ if (ReflectUtil.hasProperty(loomExtension, "mappingsFile")) {
+ Object mappingsFileObj = ReflectUtil.getProperty(loomExtension, "mappingsFile");
+ if (mappingsFileObj instanceof Provider) {
+ mappingsFileObj = ((Provider>) mappingsFileObj).getOrNull();
+ }
+ if (mappingsFileObj instanceof File) {
+ tinyMappings = (File) mappingsFileObj;
+ } else if (mappingsFileObj != null) {
+ tinyMappings = project.file(mappingsFileObj);
+ }
+ }
+
+ boolean splitMinecraftJar = (Boolean) ReflectUtil.callMethod(loomExtension, "areEnvironmentSourceSetsSplit");
+
+ Map> decompilers = new HashMap<>();
+
+ if (splitMinecraftJar) {
+ decompilers.put("common", getDecompilers(loomExtension, false));
+ decompilers.put("client", getDecompilers(loomExtension, true));
+ } else {
+ decompilers.put("single", getDecompilers(loomExtension, false));
+ }
+
+ return new FabricLoomModelImpl(minecraftVersion, tinyMappings, decompilers, splitMinecraftJar);
+ }
+
+ private List getDecompilers(Object loomExtension, boolean client) throws Exception {
+ Object decompilerOptions = ReflectUtil.getProperty(loomExtension, "decompilerOptions");
+ List result = new ArrayList<>();
+ if (decompilerOptions instanceof Iterable) {
+ for (Object option : (Iterable>) decompilerOptions) {
+ Object task = ReflectUtil.callMethod(loomExtension, "getDecompileTask", option, client);
+ String sourcesPath;
+ if (ReflectUtil.hasProperty(task, "outputJar")) {
+ // Pre 1.8
+ Object outputJar = ReflectUtil.getProperty(task, "outputJar");
+ if (outputJar instanceof Provider) {
+ outputJar = ((Provider>) outputJar).get();
+ }
+ sourcesPath = ((File) ReflectUtil.callMethod(outputJar, "getAsFile")).getAbsolutePath();
+ } else {
+ Object sourcesOutputJar = ReflectUtil.getProperty(task, "sourcesOutputJar");
+ if (sourcesOutputJar instanceof Provider) {
+ sourcesOutputJar = ((Provider>) sourcesOutputJar).get();
+ }
+ sourcesPath = ((File) ReflectUtil.callMethod(sourcesOutputJar, "getAsFile")).getAbsolutePath();
+ }
+ String name = (String) ReflectUtil.getProperty(option, "name");
+ String taskName = (String) ReflectUtil.getProperty(task, "name");
+ result.add(new FabricLoomModelImpl.DecompilerModelImpl(name, taskName, sourcesPath));
+ }
+ }
+ return result;
+ }
+
+ private FabricLoomModel buildLegacy(Project project, Object loomExtension) throws Exception {
+ Object mappingsProvider = ReflectUtil.getProperty(loomExtension, "mappingsProvider");
+ Object tinyMappingsObj = ReflectUtil.getProperty(mappingsProvider, "tinyMappings");
+ File tinyMappings = null;
+ if (tinyMappingsObj instanceof File) {
+ tinyMappings = ((File) tinyMappingsObj).getAbsoluteFile();
+ } else if (tinyMappingsObj != null) {
+ tinyMappings = project.file(tinyMappingsObj).getAbsoluteFile();
+ }
+
+ Object decompilerOptions = ReflectUtil.getProperty(loomExtension, "decompilerOptions");
+ List decompilers = new ArrayList<>();
+ if (decompilerOptions instanceof Iterable) {
+ for (Object option : (Iterable>) decompilerOptions) {
+ String optionName = (String) ReflectUtil.getProperty(option, "name");
+ String capitalized = Character.toUpperCase(optionName.charAt(0)) + optionName.substring(1);
+ Object task = project.getTasks().getByName("genSourcesWith" + capitalized);
+
+ Object runtimeJar = ReflectUtil.getProperty(task, "runtimeJar");
+ if (runtimeJar instanceof Provider) {
+ runtimeJar = ((Provider>) runtimeJar).get();
+ }
+ File runtimeJarFile = (File) ReflectUtil.callMethod(runtimeJar, "getAsFile");
+ String runtimeJarPath = runtimeJarFile.getAbsolutePath();
+ String sourcesPath = runtimeJarPath.substring(0, runtimeJarPath.length() - 4) + "-sources.jar";
+
+ String taskName = (String) ReflectUtil.getProperty(task, "name");
+ decompilers.add(new FabricLoomModelImpl.DecompilerModelImpl(optionName, taskName, sourcesPath));
+ }
+ }
+
+ Map> decompilersMap = new HashMap<>();
+ decompilersMap.put("single", decompilers);
+ return new FabricLoomModelImpl(tinyMappings, decompilersMap, false);
+ }
+
+ @Override
+ public void reportErrorMessage(
+ final @NotNull String modelName,
+ final @NotNull Project project,
+ final @NotNull ModelBuilderContext context,
+ final @NotNull Exception exception
+ ) {
+ //noinspection UnstableApiUsage
+ context.getMessageReporter().createMessage()
+ .withGroup(this)
+ .withKind(Message.Kind.ERROR)
+ .withGroup("com.demonwav.mcdev")
+ .withTitle("MinecraftDev: Loom import error")
+ .withText("Unable to build MinecraftDev FabricLoom model for project " + project.getDisplayName())
+ .withException(exception)
+ .reportMessage(project);
+ }
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/fabricloom/FabricLoomModelImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/fabricloom/FabricLoomModelImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/fabricloom/FabricLoomModelImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,104 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling.fabricloom;
+
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+public final class FabricLoomModelImpl implements FabricLoomModel, Serializable {
+
+ private final String minecraftVersion;
+ private final File tinyMappings;
+ private final Map> decompilers;
+ private final boolean splitMinecraftJar;
+
+ public FabricLoomModelImpl(
+ String minecraftVersion,
+ @Nullable File tinyMappings,
+ Map> decompilers,
+ boolean splitMinecraftJar
+ ) {
+ this.minecraftVersion = minecraftVersion;
+ this.tinyMappings = tinyMappings;
+ this.decompilers = decompilers;
+ this.splitMinecraftJar = splitMinecraftJar;
+ }
+
+ public FabricLoomModelImpl(
+ @Nullable File tinyMappings,
+ Map> decompilers,
+ boolean splitMinecraftJar
+ ) {
+ this(null, tinyMappings, decompilers, splitMinecraftJar);
+ }
+
+ @Override
+ public String getMinecraftVersion() {
+ return minecraftVersion;
+ }
+
+ @Override
+ @Nullable
+ public File getTinyMappings() {
+ return tinyMappings;
+ }
+
+ @Override
+ public Map> getDecompilers() {
+ return decompilers;
+ }
+
+ @Override
+ public boolean getSplitMinecraftJar() {
+ return splitMinecraftJar;
+ }
+
+ public static final class DecompilerModelImpl implements DecompilerModel, Serializable {
+ private final String name;
+ private final String taskName;
+ private final String sourcesPath;
+
+ public DecompilerModelImpl(String name, String taskName, String sourcesPath) {
+ this.name = name;
+ this.taskName = taskName;
+ this.sourcesPath = sourcesPath;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getTaskName() {
+ return taskName;
+ }
+
+ @Override
+ public String getSourcesPath() {
+ return sourcesPath;
+ }
+ }
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/neogradle/NeoGradle7ModelBuilderImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/neogradle/NeoGradle7ModelBuilderImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/neogradle/NeoGradle7ModelBuilderImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,142 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling.neogradle;
+
+import com.demonwav.mcdev.platform.minecraft.gradle.tooling.MinecraftModelNG7;
+import com.demonwav.mcdev.platform.minecraft.gradle.tooling.ReflectUtil;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.gradle.api.Project;
+import org.gradle.api.Task;
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.provider.Provider;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.tooling.Message;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+
+public final class NeoGradle7ModelBuilderImpl implements ModelBuilderService {
+
+ @Override
+ public boolean canBuild(String modelName) {
+ return MinecraftModelNG7.class.getName().equals(modelName);
+ }
+
+ @Override
+ public Object buildAll(String modelName, Project project) {
+ Object extension = project.getExtensions().findByName("minecraft");
+ if (extension == null) {
+ return null;
+ }
+
+ if (project.getPlugins().findPlugin("net.neoforged.gradle.userdev") == null) {
+ return null;
+ }
+
+ Object userDevRuntime = project.getExtensions().findByName("userDevRuntime");
+ if (userDevRuntime == null) {
+ return null;
+ }
+
+ String neoforgeVersion = null;
+ try {
+ Object runtimesObj = ReflectUtil.getProperty(userDevRuntime, "runtimes");
+ if (runtimesObj instanceof Provider) {
+ runtimesObj = ((Provider>) runtimesObj).get();
+ }
+ if (runtimesObj instanceof Map) {
+ for (Map.Entry, ?> entry : ((Map, ?>) runtimesObj).entrySet()) {
+ Object val = entry.getValue();
+ Object spec = ReflectUtil.getProperty(val, "specification");
+ Object forgeVersion = ReflectUtil.getProperty(spec, "forgeVersion");
+ if (forgeVersion != null) {
+ neoforgeVersion = forgeVersion.toString();
+ break;
+ }
+ }
+ }
+ } catch (Exception ignored) {
+ }
+
+ if (neoforgeVersion == null) {
+ return null;
+ }
+
+ Task neoFormMergeMappings = project.getTasks().findByName("neoFormMergeMappings");
+ if (neoFormMergeMappings == null) {
+ return null;
+ }
+
+ File mappingsFile = null;
+ try {
+ Object output = ReflectUtil.getProperty(neoFormMergeMappings, "output");
+ if (output instanceof Provider) {
+ output = ((Provider>) output).get();
+ }
+ if (output instanceof File) {
+ mappingsFile = (File) output;
+ } else if (output != null) {
+ mappingsFile = (File) ReflectUtil.callMethod(output, "getAsFile");
+ }
+ } catch (Exception ignored) {
+ }
+
+ List accessTransformers = new ArrayList<>();
+ try {
+ Object atObj = ReflectUtil.getProperty(extension, "accessTransformers");
+ if (atObj instanceof FileCollection) {
+ accessTransformers.addAll(((FileCollection) atObj).getFiles());
+ } else if (atObj != null) {
+ Object filesObj = ReflectUtil.getProperty(atObj, "files");
+ if (filesObj instanceof Iterable) {
+ for (Object file : (Iterable>) filesObj) {
+ if (file instanceof File) {
+ accessTransformers.add((File) file);
+ }
+ }
+ }
+ }
+ } catch (Exception ignored) {
+ }
+
+ return new NeoGradle7ModelImpl(neoforgeVersion, mappingsFile, accessTransformers);
+ }
+
+ @Override
+ public void reportErrorMessage(
+ final @NotNull String modelName,
+ final @NotNull Project project,
+ final @NotNull ModelBuilderContext context,
+ final @NotNull Exception exception
+ ) {
+ //noinspection UnstableApiUsage
+ context.getMessageReporter().createMessage()
+ .withGroup(this)
+ .withKind(Message.Kind.ERROR)
+ .withGroup("com.demonwav.mcdev")
+ .withTitle("MinecraftDev: NeoGradle import error")
+ .withText("Unable to build MinecraftDev NeoGradle model for project " + project.getDisplayName())
+ .withException(exception)
+ .reportMessage(project);
+ }
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/neogradle/NeoGradle7ModelImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/neogradle/NeoGradle7ModelImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/neogradle/NeoGradle7ModelImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,58 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling.neogradle;
+
+import com.demonwav.mcdev.platform.minecraft.gradle.tooling.MinecraftModelNG7;
+import java.io.File;
+import java.io.Serializable;
+import java.util.List;
+
+final class NeoGradle7ModelImpl implements MinecraftModelNG7, Serializable {
+
+ private final String neoForgeVersion;
+ private final File mappingsFile;
+ private final List accessTransformers;
+
+ NeoGradle7ModelImpl(
+ String neoForgeVersion,
+ File mappingsFile,
+ List accessTransformers
+ ) {
+ this.neoForgeVersion = neoForgeVersion;
+ this.mappingsFile = mappingsFile;
+ this.accessTransformers = accessTransformers;
+ }
+
+ @Override
+ public String getNeoForgeVersion() {
+ return neoForgeVersion;
+ }
+
+ @Override
+ public File getMappingsFile() {
+ return mappingsFile;
+ }
+
+ @Override
+ public List getAccessTransformers() {
+ return accessTransformers;
+ }
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/neomoddev/NeoModDevGradleModelBuilderImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/neomoddev/NeoModDevGradleModelBuilderImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/neomoddev/NeoModDevGradleModelBuilderImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,149 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling.neomoddev;
+
+import com.demonwav.mcdev.platform.minecraft.gradle.tooling.MinecraftModelNMD;
+import com.demonwav.mcdev.platform.minecraft.gradle.tooling.ReflectUtil;
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.gradle.api.Project;
+import org.gradle.api.file.Directory;
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.provider.ListProperty;
+import org.gradle.api.provider.Provider;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.tooling.Message;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+
+public final class NeoModDevGradleModelBuilderImpl implements ModelBuilderService {
+
+ @Override
+ public boolean canBuild(String modelName) {
+ return MinecraftModelNMD.class.getName().equals(modelName);
+ }
+
+ @Override
+ public Object buildAll(String modelName, Project project) {
+ Object extension = project.getExtensions().findByName("neoForge");
+ if (extension == null) {
+ return null;
+ }
+
+ if (project.getPlugins().findPlugin("net.neoforged.moddev") == null) {
+ return null;
+ }
+
+ String neoFormVersion = null;
+ try {
+ Object neoFormVersionProp = ReflectUtil.getProperty(extension, "neoFormVersion");
+ if (neoFormVersionProp instanceof String) {
+ neoFormVersion = (String) neoFormVersionProp;
+ } else if (neoFormVersionProp instanceof Provider) {
+ neoFormVersion = (String) ((Provider>) neoFormVersionProp).getOrNull();
+ }
+ } catch (Exception ignored) {
+ // Happens when the NeoForm version is not set or throws
+ }
+
+ String neoforgeVersion = null;
+ if (neoFormVersion == null) {
+ try {
+ Object neoforgeVersionProp = ReflectUtil.getProperty(extension, "version");
+ if (neoforgeVersionProp instanceof String) {
+ neoforgeVersion = (String) neoforgeVersionProp;
+ } else if (neoforgeVersionProp instanceof Provider) {
+ neoforgeVersion = (String) ((Provider>) neoforgeVersionProp).getOrNull();
+ }
+ } catch (Exception ignored) {
+ }
+ if (neoforgeVersion == null) {
+ return null;
+ }
+ }
+
+ List accessTransformers = new ArrayList<>();
+ try {
+ Object accessTransformersRaw = ReflectUtil.getProperty(extension, "accessTransformers");
+ if (accessTransformersRaw instanceof ListProperty) {
+ ListProperty> listProperty = (ListProperty>) accessTransformersRaw;
+ for (Object it : listProperty.get()) {
+ accessTransformers.add(project.file(it));
+ }
+ } else if (accessTransformersRaw instanceof FileCollection) {
+ accessTransformers.addAll(((FileCollection) accessTransformersRaw).getFiles());
+ } else if (accessTransformersRaw != null) {
+ Object filesObj = ReflectUtil.getProperty(accessTransformersRaw, "files");
+ if (filesObj instanceof Iterable) {
+ for (Object file : (Iterable>) filesObj) {
+ if (file instanceof File) {
+ accessTransformers.add((File) file);
+ }
+ }
+ }
+ }
+ } catch (Exception ignored) {
+ }
+
+ File mappingsFile = null;
+ try {
+ Directory neoformDir = project.getLayout().getBuildDirectory().dir("neoForm").getOrNull();
+ if (neoformDir != null) {
+ final Path neoformDirPath = neoformDir.getAsFile().toPath();
+ if (Files.exists(neoformDirPath)) {
+ try (Stream stream = Files.list(neoformDirPath)) {
+ mappingsFile = stream
+ .map(p -> p.resolve("config/joined.tsrg"))
+ .filter(Files::exists)
+ .findFirst()
+ .map(Path::toFile)
+ .orElse(null);
+ }
+ }
+ }
+ } catch (Exception ignored) {
+ }
+
+ return new NeoModDevGradleModelImpl(neoforgeVersion, neoFormVersion, mappingsFile, accessTransformers);
+ }
+
+ @Override
+ public void reportErrorMessage(
+ final @NotNull String modelName,
+ final @NotNull Project project,
+ final @NotNull ModelBuilderContext context,
+ final @NotNull Exception exception
+ ) {
+ //noinspection UnstableApiUsage
+ context.getMessageReporter().createMessage()
+ .withGroup(this)
+ .withKind(Message.Kind.ERROR)
+ .withGroup("com.demonwav.mcdev")
+ .withTitle("MinecraftDev: NeoModDev import error")
+ .withText("Unable to build MinecraftDev NeoModDev model for project " + project.getDisplayName())
+ .withException(exception)
+ .reportMessage(project);
+ }
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/neomoddev/NeoModDevGradleModelImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/neomoddev/NeoModDevGradleModelImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/neomoddev/NeoModDevGradleModelImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,70 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling.neomoddev;
+
+import com.demonwav.mcdev.platform.minecraft.gradle.tooling.MinecraftModelNMD;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.List;
+
+final class NeoModDevGradleModelImpl implements MinecraftModelNMD, Serializable {
+
+ private final String neoForgeVersion;
+ private final String neoFormVersion;
+ private final File mappingsFile;
+ private final List accessTransformers;
+
+ NeoModDevGradleModelImpl(
+ String neoForgeVersion,
+ String neoFormVersion,
+ File mappingsFile,
+ List accessTransformers
+ ) {
+ this.neoForgeVersion = neoForgeVersion;
+ this.neoFormVersion = neoFormVersion;
+ this.mappingsFile = mappingsFile;
+ this.accessTransformers = accessTransformers;
+ }
+
+ @Override
+ @Nullable
+ public String getNeoForgeVersion() {
+ return neoForgeVersion;
+ }
+
+ @Override
+ @Nullable
+ public String getNeoFormVersion() {
+ return neoFormVersion;
+ }
+
+ @Override
+ public File getMappingsFile() {
+ return mappingsFile;
+ }
+
+ @Override
+ public List getAccessTransformers() {
+ return accessTransformers;
+ }
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/vanillagradle/VanillaGradleModel.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/vanillagradle/VanillaGradleModel.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/vanillagradle/VanillaGradleModel.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,26 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling.vanillagradle;
+
+public interface VanillaGradleModel {
+
+ boolean hasVanillaGradle();
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/vanillagradle/VanillaGradleModelBuilderImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/vanillagradle/VanillaGradleModelBuilderImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/vanillagradle/VanillaGradleModelBuilderImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,58 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling.vanillagradle;
+
+import org.gradle.api.Project;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.tooling.Message;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderContext;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+
+public final class VanillaGradleModelBuilderImpl implements ModelBuilderService {
+
+ @Override
+ public boolean canBuild(String modelName) {
+ return VanillaGradleModel.class.getName().equals(modelName);
+ }
+
+ @Override
+ public Object buildAll(String modelName, Project project) {
+ return new VanillaGradleModelImpl(project.getPlugins().hasPlugin("org.spongepowered.gradle.vanilla"));
+ }
+
+ @Override
+ public void reportErrorMessage(
+ final @NotNull String modelName,
+ final @NotNull Project project,
+ final @NotNull ModelBuilderContext context,
+ final @NotNull Exception exception
+ ) {
+ //noinspection UnstableApiUsage
+ context.getMessageReporter().createMessage()
+ .withGroup(this)
+ .withKind(Message.Kind.ERROR)
+ .withGroup("com.demonwav.mcdev")
+ .withTitle("MinecraftDev: VanillaGradle import error")
+ .withText("Unable to build MinecraftDev VanillaGradle model for project " + project.getDisplayName())
+ .withException(exception)
+ .reportMessage(project);
+ }
+}
Index: src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/vanillagradle/VanillaGradleModelImpl.java
===================================================================
--- src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/vanillagradle/VanillaGradleModelImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/gradle-tooling-extension/java/com/demonwav/mcdev/platform/minecraft/gradle/tooling/vanillagradle/VanillaGradleModelImpl.java (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,37 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.gradle.tooling.vanillagradle;
+
+import java.io.Serializable;
+
+final class VanillaGradleModelImpl implements VanillaGradleModel, Serializable {
+
+ private final boolean hasVanillaGradle;
+
+ VanillaGradleModelImpl(boolean hasVanillaGradle) {
+ this.hasVanillaGradle = hasVanillaGradle;
+ }
+
+ @Override
+ public boolean hasVanillaGradle() {
+ return hasVanillaGradle;
+ }
+}
Index: src/gradle-tooling-extension/resources/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
===================================================================
--- src/gradle-tooling-extension/resources/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/gradle-tooling-extension/resources/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -1,7 +1,7 @@
-com.demonwav.mcdev.platform.mcp.gradle.tooling.archloom.ArchitecturyModelBuilderImpl
-com.demonwav.mcdev.platform.mcp.gradle.tooling.fabricloom.FabricLoomModelBuilderImpl
-com.demonwav.mcdev.platform.mcp.gradle.tooling.neogradle.NeoGradle7ModelBuilderImpl
-com.demonwav.mcdev.platform.mcp.gradle.tooling.neomoddev.NeoModDevGradleModelBuilderImpl
-com.demonwav.mcdev.platform.mcp.gradle.tooling.vanillagradle.VanillaGradleModelBuilderImpl
-com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelFG2BuilderImpl
-com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelFG3BuilderImpl
+com.demonwav.mcdev.platform.minecraft.gradle.tooling.archloom.ArchitecturyModelBuilderImpl
+com.demonwav.mcdev.platform.minecraft.gradle.tooling.fabricloom.FabricLoomModelBuilderImpl
+com.demonwav.mcdev.platform.minecraft.gradle.tooling.neogradle.NeoGradle7ModelBuilderImpl
+com.demonwav.mcdev.platform.minecraft.gradle.tooling.neomoddev.NeoModDevGradleModelBuilderImpl
+com.demonwav.mcdev.platform.minecraft.gradle.tooling.vanillagradle.VanillaGradleModelBuilderImpl
+com.demonwav.mcdev.platform.minecraft.gradle.tooling.MinecraftModelFG2BuilderImpl
+com.demonwav.mcdev.platform.minecraft.gradle.tooling.MinecraftModelFG3BuilderImpl
Index: src/main/grammars/AtLexer.flex
===================================================================
--- src/main/grammars/AtLexer.flex (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/grammars/AtLexer.flex (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -18,11 +18,11 @@
* along with this program. If not, see .
*/
-package com.demonwav.mcdev.platform.mcp.at.gen;
+package com.demonwav.mcdev.platform.minecraft.at.gen;
import com.intellij.lexer.*;
import com.intellij.psi.tree.IElementType;
-import static com.demonwav.mcdev.platform.mcp.at.gen.psi.AtTypes.*;
+import static com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtTypes.*;
import static com.intellij.psi.TokenType.*;
%%
Index: src/main/grammars/AtParser.bnf
===================================================================
--- src/main/grammars/AtParser.bnf (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/grammars/AtParser.bnf (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -19,18 +19,18 @@
*/
{
- parserClass="com.demonwav.mcdev.platform.mcp.at.gen.parser.AtParser"
+ parserClass="com.demonwav.mcdev.platform.minecraft.at.gen.parser.AtParser"
extends="com.intellij.extapi.psi.ASTWrapperPsiElement"
psiClassPrefix="At"
psiImplClassSuffix="Impl"
- psiPackage="com.demonwav.mcdev.platform.mcp.at.gen.psi"
- psiImplPackage="com.demonwav.mcdev.platform.mcp.at.gen.psi.impl"
+ psiPackage="com.demonwav.mcdev.platform.minecraft.at.gen.psi"
+ psiImplPackage="com.demonwav.mcdev.platform.minecraft.at.gen.psi.impl"
- elementTypeHolderClass="com.demonwav.mcdev.platform.mcp.at.gen.psi.AtTypes"
- elementTypeClass="com.demonwav.mcdev.platform.mcp.at.psi.AtElementType"
- tokenTypeClass="com.demonwav.mcdev.platform.mcp.at.psi.AtTokenType"
+ elementTypeHolderClass="com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtTypes"
+ elementTypeClass="com.demonwav.mcdev.platform.minecraft.at.psi.AtElementType"
+ tokenTypeClass="com.demonwav.mcdev.platform.minecraft.at.psi.AtTokenType"
consumeTokenMethod="consumeTokenFast"
}
@@ -41,8 +41,8 @@
private end_line ::= CRLF | <>
entry ::= keyword class_name line_value? {
- mixin="com.demonwav.mcdev.platform.mcp.at.psi.mixins.impl.AtEntryImplMixin"
- implements="com.demonwav.mcdev.platform.mcp.at.psi.mixins.AtEntryMixin"
+ mixin="com.demonwav.mcdev.platform.minecraft.at.psi.mixins.impl.AtEntryImplMixin"
+ implements="com.demonwav.mcdev.platform.minecraft.at.psi.mixins.AtEntryMixin"
pin = 1
recoverWhile = line_recover
}
@@ -51,49 +51,49 @@
private line_value ::= function | field_name | asterisk
asterisk ::= ASTERISK_ELEMENT {
- implements="com.demonwav.mcdev.platform.mcp.at.psi.AtElement"
+ implements="com.demonwav.mcdev.platform.minecraft.at.psi.AtElement"
}
keyword ::= KEYWORD_ELEMENT {
- mixin="com.demonwav.mcdev.platform.mcp.at.psi.mixins.impl.AtKeywordImplMixin"
- implements="com.demonwav.mcdev.platform.mcp.at.psi.mixins.AtKeywordMixin"
+ mixin="com.demonwav.mcdev.platform.minecraft.at.psi.mixins.impl.AtKeywordImplMixin"
+ implements="com.demonwav.mcdev.platform.minecraft.at.psi.mixins.AtKeywordMixin"
methods=[
keywordElement="KEYWORD_ELEMENT"
]
}
class_name ::= CLASS_NAME_ELEMENT {
- mixin="com.demonwav.mcdev.platform.mcp.at.psi.mixins.impl.AtClassNameImplMixin"
- implements="com.demonwav.mcdev.platform.mcp.at.psi.mixins.AtClassNameMixin"
+ mixin="com.demonwav.mcdev.platform.minecraft.at.psi.mixins.impl.AtClassNameImplMixin"
+ implements="com.demonwav.mcdev.platform.minecraft.at.psi.mixins.AtClassNameMixin"
methods=[
classNameElement="CLASS_NAME_ELEMENT"
]
}
field_name ::= NAME_ELEMENT {
- mixin= "com.demonwav.mcdev.platform.mcp.at.psi.mixins.impl.AtFieldNameImplMixin"
- implements="com.demonwav.mcdev.platform.mcp.at.psi.mixins.AtFieldNameMixin"
+ mixin= "com.demonwav.mcdev.platform.minecraft.at.psi.mixins.impl.AtFieldNameImplMixin"
+ implements="com.demonwav.mcdev.platform.minecraft.at.psi.mixins.AtFieldNameMixin"
methods=[
nameElement="NAME_ELEMENT"
]
}
function ::= func_name OPEN_PAREN argument* CLOSE_PAREN return_value {
- mixin= "com.demonwav.mcdev.platform.mcp.at.psi.mixins.impl.AtFunctionImplMixin"
- implements= "com.demonwav.mcdev.platform.mcp.at.psi.mixins.AtFunctionMixin"
+ mixin= "com.demonwav.mcdev.platform.minecraft.at.psi.mixins.impl.AtFunctionImplMixin"
+ implements= "com.demonwav.mcdev.platform.minecraft.at.psi.mixins.AtFunctionMixin"
}
func_name ::= NAME_ELEMENT {
- mixin="com.demonwav.mcdev.platform.mcp.at.psi.mixins.impl.AtFuncNameImplMixin"
- implements="com.demonwav.mcdev.platform.mcp.at.psi.mixins.AtFuncNameMixin"
+ mixin="com.demonwav.mcdev.platform.minecraft.at.psi.mixins.impl.AtFuncNameImplMixin"
+ implements="com.demonwav.mcdev.platform.minecraft.at.psi.mixins.AtFuncNameMixin"
methods=[
nameElement="NAME_ELEMENT"
]
}
argument ::= PRIMITIVE | CLASS_VALUE {
- mixin="com.demonwav.mcdev.platform.mcp.at.psi.mixins.impl.AtArgumentImplMixin"
- implements="com.demonwav.mcdev.platform.mcp.at.psi.mixins.AtArgumentMixin"
+ mixin="com.demonwav.mcdev.platform.minecraft.at.psi.mixins.impl.AtArgumentImplMixin"
+ implements="com.demonwav.mcdev.platform.minecraft.at.psi.mixins.AtArgumentMixin"
methods=[
primitive="PRIMITIVE"
classValue="CLASS_VALUE"
@@ -101,8 +101,8 @@
}
return_value ::= PRIMITIVE | CLASS_VALUE {
- mixin="com.demonwav.mcdev.platform.mcp.at.psi.mixins.impl.AtReturnValueImplMixin"
- implements="com.demonwav.mcdev.platform.mcp.at.psi.mixins.AtReturnValueMixin"
+ mixin="com.demonwav.mcdev.platform.minecraft.at.psi.mixins.impl.AtReturnValueImplMixin"
+ implements="com.demonwav.mcdev.platform.minecraft.at.psi.mixins.AtReturnValueMixin"
methods=[
primitive="PRIMITIVE"
classValue="CLASS_VALUE"
Index: src/main/grammars/CtLexer.flex
===================================================================
--- src/main/grammars/CtLexer.flex (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/grammars/CtLexer.flex (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -18,11 +18,11 @@
* along with this program. If not, see .
*/
-package com.demonwav.mcdev.platform.mcp.ct.gen;
+package com.demonwav.mcdev.platform.minecraft.ct.gen;
import com.intellij.lexer.*;
import com.intellij.psi.tree.IElementType;
-import static com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtTypes.*;
+import static com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtTypes.*;
import static com.intellij.psi.TokenType.*;
%%
Index: src/main/grammars/CtParser.bnf
===================================================================
--- src/main/grammars/CtParser.bnf (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/grammars/CtParser.bnf (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -19,18 +19,18 @@
*/
{
- parserClass="com.demonwav.mcdev.platform.mcp.ct.gen.parser.CtParser"
+ parserClass="com.demonwav.mcdev.platform.minecraft.ct.gen.parser.CtParser"
extends="com.intellij.extapi.psi.ASTWrapperPsiElement"
psiClassPrefix="Ct"
psiImplClassSuffix="Impl"
- psiPackage="com.demonwav.mcdev.platform.mcp.ct.gen.psi"
- psiImplPackage="com.demonwav.mcdev.platform.mcp.ct.gen.psi.impl"
+ psiPackage="com.demonwav.mcdev.platform.minecraft.ct.gen.psi"
+ psiImplPackage="com.demonwav.mcdev.platform.minecraft.ct.gen.psi.impl"
- elementTypeHolderClass="com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtTypes"
- elementTypeClass="com.demonwav.mcdev.platform.mcp.ct.psi.CtElementType"
- tokenTypeClass="com.demonwav.mcdev.platform.mcp.ct.psi.CtTokenType"
+ elementTypeHolderClass="com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtTypes"
+ elementTypeClass="com.demonwav.mcdev.platform.minecraft.ct.psi.CtElementType"
+ tokenTypeClass="com.demonwav.mcdev.platform.minecraft.ct.psi.CtTokenType"
}
aw_file ::= header_line line*
@@ -41,8 +41,8 @@
private end_line ::= crlf | <>
header ::= HEADER_NAME HEADER_VERSION_ELEMENT HEADER_NAMESPACE_ELEMENT {
- mixin="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl.CtHeaderImplMixin"
- implements="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtHeaderMixin"
+ mixin="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl.CtHeaderImplMixin"
+ implements="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtHeaderMixin"
methods=[
namespaceElement="HEADER_NAMESPACE_ELEMENT"
]
@@ -51,43 +51,43 @@
private entry ::= aw_entry | itf_entry | extend_enum_entry {
name="ClassTweaker Entry"
- mixin="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl.CtEntryImplMixin"
- implements="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl.CtEntryMixin"
+ mixin="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl.CtEntryImplMixin"
+ implements="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl.CtEntryMixin"
recoverWhile = line_recover
}
private aw_entry ::= aw_class_entry | aw_method_entry | aw_field_entry {
- mixin="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl.CtAwEntryImplMixin"
- implements="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtAwEntryMixin"
+ mixin="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl.CtAwEntryImplMixin"
+ implements="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtAwEntryMixin"
}
aw_class_entry ::= access class_literal class_name {
- mixin="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl.CtAwClassEntryImplMixin"
- implements="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtAwClassEntryMixin"
+ mixin="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl.CtAwClassEntryImplMixin"
+ implements="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtAwClassEntryMixin"
pin = 2
}
aw_method_entry ::= access method_literal class_name member_name method_desc {
- mixin="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl.CtAwMethodEntryImplMixin"
- implements="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtAwMethodEntryMixin"
+ mixin="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl.CtAwMethodEntryImplMixin"
+ implements="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtAwMethodEntryMixin"
pin = 2
}
aw_field_entry ::= access field_literal class_name member_name field_desc {
- mixin="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl.CtAwFieldEntryImplMixin"
- implements="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtAwFieldEntryMixin"
+ mixin="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl.CtAwFieldEntryImplMixin"
+ implements="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtAwFieldEntryMixin"
pin = 2
}
itf_entry ::= INJECT_INTERFACE_ELEMENT class_name signature {
- mixin="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl.CtItfEntryImplMixin"
- implements="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtItfEntryMixin"
+ mixin="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl.CtItfEntryImplMixin"
+ implements="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtItfEntryMixin"
pin = 1
}
extend_enum_entry ::= EXTEND_ENUM_ELEMENT class_name member_name {
- mixin="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl.CtExtendEnumEntryImplMixin"
- implements="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtExtendEnumEntryMixin"
+ mixin="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl.CtExtendEnumEntryImplMixin"
+ implements="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtExtendEnumEntryMixin"
pin = 1
}
@@ -106,16 +106,16 @@
field_literal ::= FIELD_ELEMENT
class_name ::= CLASS_NAME_ELEMENT {
- mixin="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl.CtAwClassNameImplMixin"
- implements="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtAwClassNameMixin"
+ mixin="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl.CtAwClassNameImplMixin"
+ implements="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtAwClassNameMixin"
methods=[
classNameElement="CLASS_NAME_ELEMENT"
]
}
member_name ::= NAME_ELEMENT {
- mixin= "com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl.CtAwMemberNameImplMixin"
- implements="com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtAwMemberNameMixin"
+ mixin= "com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl.CtAwMemberNameImplMixin"
+ implements="com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtAwMemberNameMixin"
methods=[
nameElement="NAME_ELEMENT"
]
@@ -126,8 +126,8 @@
field_desc ::= desc_element
desc_element ::= OPEN_BRACKET* (PRIMITIVE | CLASS_VALUE) {
- mixin= "com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl.CtAwDescElementImplMixin"
- implements= "com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtAwDescElementMixin"
+ mixin= "com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl.CtAwDescElementImplMixin"
+ implements= "com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtAwDescElementMixin"
methods=[
primitive="PRIMITIVE"
classValue="CLASS_VALUE"
Index: src/main/kotlin/asset/PlatformAssets.kt
===================================================================
--- src/main/kotlin/asset/PlatformAssets.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/asset/PlatformAssets.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -66,9 +66,4 @@
val NEOFORGE_ICON = IconUtil.scale(loadIcon("/assets/icons/platform/NeoForge.png"), null, 0.125f)
val NEOFORGE_ICON_2X = IconUtil.scale(loadIcon("/assets/icons/platform/NeoForge.png"), null, 0.25f)
-
- val MCP_ICON = loadIcon("/assets/icons/platform/MCP.png")
- val MCP_ICON_2X = loadIcon("/assets/icons/platform/MCP@2x.png")
- val MCP_ICON_DARK = loadIcon("/assets/icons/platform/MCP_dark.png")
- val MCP_ICON_2X_DARK = loadIcon("/assets/icons/platform/MCP@2x_dark.png")
}
Index: src/main/kotlin/facet/MinecraftFacetDetector.kt
===================================================================
--- src/main/kotlin/facet/MinecraftFacetDetector.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/facet/MinecraftFacetDetector.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -24,7 +24,7 @@
import com.demonwav.mcdev.platform.architectury.framework.ARCHITECTURY_LIBRARY_KIND
import com.demonwav.mcdev.platform.architectury.framework.ArchitecturyGradleData
import com.demonwav.mcdev.platform.fabric.framework.FABRIC_LIBRARY_KIND
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.archloom.ArchitecturyModel
+import com.demonwav.mcdev.platform.minecraft.gradle.tooling.archloom.ArchitecturyModel
import com.demonwav.mcdev.platform.sponge.framework.SPONGE_LIBRARY_KIND
import com.demonwav.mcdev.util.ifEmpty
import com.demonwav.mcdev.util.runWriteTaskLater
@@ -169,9 +169,9 @@
types.addAll(platforms)
if (facet.configuration.state.forgePatcher) {
- // make sure Forge and MCP are present
+ // make sure Forge and Minecraft are present
types.add(PlatformType.FORGE)
- types.add(PlatformType.MCP)
+ types.add(PlatformType.MINECRAFT)
}
facet.refresh()
Index: src/main/kotlin/facet/MinecraftFacetEditorTabV2.kt
===================================================================
--- src/main/kotlin/facet/MinecraftFacetEditorTabV2.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/facet/MinecraftFacetEditorTabV2.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -52,7 +52,7 @@
val neoforge = platformState(PlatformType.NEOFORGE)
val fabric = platformState(PlatformType.FABRIC)
val architectury = platformState(PlatformType.ARCHITECTURY)
- val mcp = platformState(PlatformType.MCP)
+ val minecraft = platformState(PlatformType.MINECRAFT)
val mixin = platformState(PlatformType.MIXIN)
val velocity = platformState(PlatformType.VELOCITY)
val bungeecord = platformState(PlatformType.BUNGEECORD)
@@ -93,7 +93,7 @@
forge, "Forge", PlatformAssets.FORGE_ICON_2X,
{
afterChange { _ ->
- also(this, mcp.enabled)
+ also(this, minecraft.enabled)
unique(this, architectury.enabled)
}
},
@@ -110,7 +110,7 @@
fabric, "Fabric", PlatformAssets.FABRIC_ICON_2X,
{
afterChange { _ ->
- also(this, mixin.enabled, mcp.enabled)
+ also(this, mixin.enabled, minecraft.enabled)
unique(this, architectury.enabled)
}
},
@@ -131,13 +131,12 @@
},
)
- val mcpIcon = if (isDarkMode) PlatformAssets.MCP_ICON_2X_DARK else PlatformAssets.MCP_ICON_2X
- createRow(mcp, "MCP", mcpIcon)
+ createRow(minecraft, "Minecraft", PlatformAssets.MINECRAFT_ICON_2X)
val mixinIcon = if (isDarkMode) PlatformAssets.MIXIN_ICON_2X_DARK else PlatformAssets.MIXIN_ICON_2X
createRow(
mixin, "Mixin", mixinIcon,
- { afterChange { _ -> also(this, mcp.enabled) } }
+ { afterChange { _ -> also(this, minecraft.enabled) } }
)
createRow(velocity, "Velocity", PlatformAssets.VELOCITY_ICON_2X)
Index: src/main/kotlin/facet/MinecraftLibraryKinds.kt
===================================================================
--- src/main/kotlin/facet/MinecraftLibraryKinds.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/facet/MinecraftLibraryKinds.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -29,7 +29,7 @@
import com.demonwav.mcdev.platform.bungeecord.framework.WATERFALL_LIBRARY_KIND
import com.demonwav.mcdev.platform.fabric.framework.FABRIC_LIBRARY_KIND
import com.demonwav.mcdev.platform.forge.framework.FORGE_LIBRARY_KIND
-import com.demonwav.mcdev.platform.mcp.framework.MCP_LIBRARY_KIND
+import com.demonwav.mcdev.platform.minecraft.framework.MINECRAFT_LIBRARY_KIND
import com.demonwav.mcdev.platform.mixin.framework.MIXIN_LIBRARY_KIND
import com.demonwav.mcdev.platform.neoforge.framework.NEOFORGE_LIBRARY_KIND
import com.demonwav.mcdev.platform.sponge.framework.SPONGE_LIBRARY_KIND
@@ -45,7 +45,7 @@
NEOFORGE_LIBRARY_KIND,
FABRIC_LIBRARY_KIND,
ARCHITECTURY_LIBRARY_KIND,
- MCP_LIBRARY_KIND,
+ MINECRAFT_LIBRARY_KIND,
MIXIN_LIBRARY_KIND,
BUNGEECORD_LIBRARY_KIND,
WATERFALL_LIBRARY_KIND,
Index: src/main/kotlin/insight/PluginLineMarkerProvider.kt
===================================================================
--- src/main/kotlin/insight/PluginLineMarkerProvider.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/insight/PluginLineMarkerProvider.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -71,7 +71,7 @@
PlatformType.WATERFALL -> ThreeState.NO
PlatformType.VELOCITY -> ThreeState.NO
PlatformType.MIXIN -> ThreeState.YES
- PlatformType.MCP -> ThreeState.YES
+ PlatformType.MINECRAFT -> ThreeState.YES
PlatformType.ADVENTURE -> ThreeState.UNSURE
}
}
Index: src/main/kotlin/insight/generation/MinecraftClassCreateAction.kt
===================================================================
--- src/main/kotlin/insight/generation/MinecraftClassCreateAction.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/insight/generation/MinecraftClassCreateAction.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -26,7 +26,7 @@
import com.demonwav.mcdev.facet.MinecraftFacet
import com.demonwav.mcdev.platform.fabric.FabricModuleType
import com.demonwav.mcdev.platform.forge.ForgeModuleType
-import com.demonwav.mcdev.platform.mcp.McpModuleType
+import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType
import com.demonwav.mcdev.platform.neoforge.NeoForgeModuleType
import com.demonwav.mcdev.util.MinecraftTemplates
import com.demonwav.mcdev.util.MinecraftVersions
@@ -70,7 +70,7 @@
val isNeoForge = MinecraftFacet.getInstance(module, NeoForgeModuleType) != null
val isFabric = MinecraftFacet.getInstance(module, FabricModuleType) != null
- val mcVersion = MinecraftFacet.getInstance(module, McpModuleType)?.getSettings()
+ val mcVersion = MinecraftFacet.getInstance(module, MinecraftModuleType)?.getSettings()
?.minecraftVersion?.let(SemanticVersion::parse)
if (isForge && mcVersion != null) {
@@ -131,7 +131,7 @@
val isFabricMod = MinecraftFacet.getInstance(module, FabricModuleType) != null
val isForgeMod = MinecraftFacet.getInstance(module, ForgeModuleType) != null
val isNeoForgeMod = MinecraftFacet.getInstance(module, NeoForgeModuleType) != null
- val hasMcVersion = MinecraftFacet.getInstance(module, McpModuleType)?.getSettings()?.minecraftVersion != null
+ val hasMcVersion = MinecraftFacet.getInstance(module, MinecraftModuleType)?.getSettings()?.minecraftVersion != null
return (isFabricMod || isNeoForgeMod || isForgeMod && hasMcVersion) && super.isAvailable(dataContext)
}
Index: src/main/kotlin/platform/PlatformType.kt
===================================================================
--- src/main/kotlin/platform/PlatformType.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/PlatformType.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -38,8 +38,8 @@
import com.demonwav.mcdev.platform.fabric.framework.FABRIC_LIBRARY_KIND
import com.demonwav.mcdev.platform.forge.ForgeModuleType
import com.demonwav.mcdev.platform.forge.framework.FORGE_LIBRARY_KIND
-import com.demonwav.mcdev.platform.mcp.McpModuleType
-import com.demonwav.mcdev.platform.mcp.framework.MCP_LIBRARY_KIND
+import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType
+import com.demonwav.mcdev.platform.minecraft.framework.MINECRAFT_LIBRARY_KIND
import com.demonwav.mcdev.platform.mixin.MixinModuleType
import com.demonwav.mcdev.platform.mixin.framework.MIXIN_LIBRARY_KIND
import com.demonwav.mcdev.platform.neoforge.NeoForgeModuleType
@@ -68,7 +68,7 @@
VELOCITY(VelocityModuleType, "velocity.json"),
MIXIN(MixinModuleType),
NEOFORGE(NeoForgeModuleType),
- MCP(McpModuleType),
+ MINECRAFT(MinecraftModuleType),
ADVENTURE(AdventureModuleType),
;
@@ -98,7 +98,7 @@
ARCHITECTURY_LIBRARY_KIND -> ARCHITECTURY
FORGE_LIBRARY_KIND -> FORGE
FABRIC_LIBRARY_KIND -> FABRIC
- MCP_LIBRARY_KIND -> MCP
+ MINECRAFT_LIBRARY_KIND -> MINECRAFT
MIXIN_LIBRARY_KIND -> MIXIN
BUNGEECORD_LIBRARY_KIND -> BUNGEECORD
WATERFALL_LIBRARY_KIND -> WATERFALL
Index: src/main/kotlin/platform/architectury/framework/ArchitecturyGradleData.kt
===================================================================
--- src/main/kotlin/platform/architectury/framework/ArchitecturyGradleData.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/architectury/framework/ArchitecturyGradleData.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -20,7 +20,7 @@
package com.demonwav.mcdev.platform.architectury.framework
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.archloom.ArchitecturyModel
+import com.demonwav.mcdev.platform.minecraft.gradle.tooling.archloom.ArchitecturyModel
import com.intellij.openapi.externalSystem.model.Key
import com.intellij.openapi.externalSystem.model.ProjectKeys
import com.intellij.openapi.externalSystem.model.project.AbstractExternalEntityData
Index: src/main/kotlin/platform/architectury/framework/ArchitecturyProjectResolverExtension.kt
===================================================================
--- src/main/kotlin/platform/architectury/framework/ArchitecturyProjectResolverExtension.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/architectury/framework/ArchitecturyProjectResolverExtension.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -20,7 +20,7 @@
package com.demonwav.mcdev.platform.architectury.framework
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.archloom.ArchitecturyModel
+import com.demonwav.mcdev.platform.minecraft.gradle.tooling.archloom.ArchitecturyModel
import com.intellij.openapi.externalSystem.model.DataNode
import com.intellij.openapi.externalSystem.model.project.ModuleData
import org.gradle.tooling.model.idea.IdeaModule
Index: src/main/kotlin/platform/fabric/FabricModule.kt
===================================================================
--- src/main/kotlin/platform/fabric/FabricModule.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/fabric/FabricModule.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -26,10 +26,10 @@
import com.demonwav.mcdev.platform.PlatformType
import com.demonwav.mcdev.platform.fabric.reference.EntryPointReference
import com.demonwav.mcdev.platform.fabric.util.FabricConstants
-import com.demonwav.mcdev.platform.mcp.fabricloom.FabricLoomData
-import com.demonwav.mcdev.platform.mcp.mappings.HardcodedYarnToMojmap
-import com.demonwav.mcdev.platform.mcp.mappings.HasCustomNamedMappings
-import com.demonwav.mcdev.platform.mcp.mappings.MappingsManager
+import com.demonwav.mcdev.platform.minecraft.fabricloom.FabricLoomData
+import com.demonwav.mcdev.platform.minecraft.mappings.HardcodedYarnToMojmap
+import com.demonwav.mcdev.platform.minecraft.mappings.HasCustomNamedMappings
+import com.demonwav.mcdev.platform.minecraft.mappings.MappingsManager
import com.demonwav.mcdev.util.SourceType
import com.demonwav.mcdev.util.nullable
import com.demonwav.mcdev.util.runCatchingKtIdeaExceptions
Index: src/main/kotlin/platform/fabric/reference/FabricClientUseScopeEnlarger.kt
===================================================================
--- src/main/kotlin/platform/fabric/reference/FabricClientUseScopeEnlarger.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/fabric/reference/FabricClientUseScopeEnlarger.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -21,7 +21,7 @@
package com.demonwav.mcdev.platform.fabric.reference
import com.demonwav.mcdev.platform.fabric.util.FabricConstants
-import com.demonwav.mcdev.platform.mcp.fabricloom.FabricLoomData
+import com.demonwav.mcdev.platform.minecraft.fabricloom.FabricLoomData
import com.demonwav.mcdev.util.findModule
import com.intellij.openapi.application.ReadAction
import com.intellij.openapi.vfs.VirtualFile
Index: src/main/kotlin/platform/forge/ForgeModule.kt
===================================================================
--- src/main/kotlin/platform/forge/ForgeModule.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/forge/ForgeModule.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -28,7 +28,7 @@
import com.demonwav.mcdev.platform.PlatformType
import com.demonwav.mcdev.platform.forge.inspections.sideonly.SidedProxyAnnotator
import com.demonwav.mcdev.platform.forge.util.ForgeConstants
-import com.demonwav.mcdev.platform.mcp.McpModuleSettings
+import com.demonwav.mcdev.platform.minecraft.MinecraftModuleSettings
import com.demonwav.mcdev.toml.stringValue
import com.demonwav.mcdev.util.SemanticVersion
import com.demonwav.mcdev.util.SourceType
@@ -127,7 +127,7 @@
}
override fun writeErrorMessageForEventParameter(eventClass: PsiClass, method: PsiMethod): String {
- val mcVersion = McpModuleSettings.getInstance(module).state.minecraftVersion
+ val mcVersion = MinecraftModuleSettings.getInstance(module).state.minecraftVersion
?.let { SemanticVersion.parse(it) }
if (mcVersion != null && mcVersion >= ForgeModuleType.FG3_MC_VERSION) {
return formatWrongEventMessage(
Index: src/main/kotlin/platform/forge/reflection/reference/ReflectedFieldReference.kt
===================================================================
--- src/main/kotlin/platform/forge/reflection/reference/ReflectedFieldReference.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/forge/reflection/reference/ReflectedFieldReference.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -21,7 +21,7 @@
package com.demonwav.mcdev.platform.forge.reflection.reference
import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.mcp.McpModuleType
+import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType
import com.demonwav.mcdev.util.constantStringValue
import com.demonwav.mcdev.util.findModule
import com.demonwav.mcdev.util.simpleQualifiedMemberReference
@@ -67,7 +67,7 @@
?: return@withInsertHandler
val srgManager = literal.findModule()?.let { MinecraftFacet.getInstance(it) }
- ?.getModuleOfType(McpModuleType)?.mappingsManager
+ ?.getModuleOfType(MinecraftModuleType)?.mappingsManager
val srgMap = srgManager?.mappingsNow
val srgField = srgMap?.getIntermediaryField(field.simpleQualifiedMemberReference)
?: return@withInsertHandler
Index: src/main/kotlin/platform/forge/reflection/reference/ReflectedMemberReferenceBasePoly.kt
===================================================================
--- src/main/kotlin/platform/forge/reflection/reference/ReflectedMemberReferenceBasePoly.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/forge/reflection/reference/ReflectedMemberReferenceBasePoly.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -21,7 +21,7 @@
package com.demonwav.mcdev.platform.forge.reflection.reference
import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.mcp.McpModuleType
+import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType
import com.demonwav.mcdev.util.findModule
import com.demonwav.mcdev.util.toTypedArray
import com.intellij.psi.PsiClass
@@ -49,7 +49,7 @@
val name = memberName
val srgManager = element.findModule()?.let { MinecraftFacet.getInstance(it) }
- ?.getModuleOfType(McpModuleType)?.mappingsManager
+ ?.getModuleOfType(MinecraftModuleType)?.mappingsManager
val srgMap = srgManager?.mappingsNow
val mcpName = srgMap?.mapIntermediaryToMapped(name) ?: name
Index: src/main/kotlin/platform/forge/reflection/reference/ReflectedMethodReference.kt
===================================================================
--- src/main/kotlin/platform/forge/reflection/reference/ReflectedMethodReference.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/forge/reflection/reference/ReflectedMethodReference.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -21,7 +21,7 @@
package com.demonwav.mcdev.platform.forge.reflection.reference
import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.mcp.McpModuleType
+import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType
import com.demonwav.mcdev.util.constantStringValue
import com.demonwav.mcdev.util.findModule
import com.demonwav.mcdev.util.qualifiedMemberReference
@@ -74,7 +74,7 @@
?: return@withInsertHandler
val params = literal.parent as? PsiExpressionList ?: return@withInsertHandler
val srgManager = literal.findModule()?.let { MinecraftFacet.getInstance(it) }
- ?.getModuleOfType(McpModuleType)?.mappingsManager
+ ?.getModuleOfType(MinecraftModuleType)?.mappingsManager
val srgMap = srgManager?.mappingsNow
val signature = method.getSignature(PsiSubstitutor.EMPTY)
Index: src/main/kotlin/platform/mcp/McpModule.kt
===================================================================
--- src/main/kotlin/platform/mcp/McpModule.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/McpModule.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,120 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp
-
-import com.demonwav.mcdev.MinecraftSettings
-import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.AbstractModule
-import com.demonwav.mcdev.platform.PlatformType
-import com.demonwav.mcdev.platform.mcp.mappings.MappingsManager
-import com.demonwav.mcdev.platform.mcp.util.McpConstants
-import com.demonwav.mcdev.translations.TranslationFileListener
-import com.demonwav.mcdev.util.runWriteTaskLater
-import com.intellij.json.JsonFileType
-import com.intellij.openapi.application.ApplicationManager
-import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder
-import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
-import com.intellij.openapi.fileTypes.FileTypeManager
-import com.intellij.openapi.vfs.VirtualFile
-import com.intellij.openapi.vfs.VirtualFileManager
-import com.intellij.psi.PsiClass
-import com.intellij.psi.PsiMethod
-import com.intellij.util.messages.MessageBusConnection
-import javax.swing.Icon
-import org.jetbrains.plugins.gradle.settings.GradleSettings
-import org.jetbrains.plugins.gradle.util.GradleConstants
-
-class McpModule(facet: MinecraftFacet) : AbstractModule(facet) {
-
- private lateinit var connection: MessageBusConnection
-
- private val settings: McpModuleSettings = McpModuleSettings.getInstance(module)
- val accessTransformers = mutableSetOf()
-
- var mappingsManager: MappingsManager? = null
- private set
-
- override fun init() {
- initSrg()
- connection = project.messageBus.connect()
- connection.subscribe(VirtualFileManager.VFS_CHANGES, TranslationFileListener)
-
- runWriteTaskLater {
- FileTypeManager.getInstance().associatePattern(JsonFileType.INSTANCE, McpConstants.PNG_MCMETA)
- }
-
- if (MinecraftSettings.instance.forceExternalAnnotations) {
- // Force enable external annotations so that ours are provided
- var requiresRefresh = false
- for (settings in GradleSettings.getInstance(project).linkedProjectsSettings) {
- if (!settings.isResolveExternalAnnotations) {
- settings.isResolveExternalAnnotations = true
- requiresRefresh = true
- }
- }
-
- if (requiresRefresh) {
- // Schedule Gradle project refresh outside write lock
- ApplicationManager.getApplication().invokeLater {
- ExternalSystemUtil.refreshProjects(ImportSpecBuilder(project, GradleConstants.SYSTEM_ID))
- }
- }
- }
- }
-
- private fun initSrg() {
- val settings = getSettings()
- val file = settings.mappingFile ?: return
- val srgType = settings.srgType ?: return
-
- mappingsManager = MappingsManager.getInstance(file, srgType)
- mappingsManager?.parse()
- }
-
- override val moduleType = McpModuleType
- override val type = PlatformType.MCP
- override val icon: Icon? = null
-
- override fun writeErrorMessageForEventParameter(eventClass: PsiClass, method: PsiMethod) = ""
-
- fun getSettings() = settings.state
-
- fun updateSettings(data: McpModuleSettings.State) {
- this.settings.loadState(data)
- val mappingFile = data.mappingFile ?: return
- val srgType = data.srgType ?: return
-
- mappingsManager = MappingsManager.getInstance(mappingFile, srgType)
- mappingsManager?.parse()
- }
-
- fun addAccessTransformerFile(file: VirtualFile) {
- accessTransformers.add(file)
- }
-
- override fun dispose() {
- super.dispose()
-
- connection.disconnect()
- accessTransformers.clear()
- mappingsManager = null
- }
-}
Index: src/main/kotlin/platform/mcp/McpModuleSettings.kt
===================================================================
--- src/main/kotlin/platform/mcp/McpModuleSettings.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/McpModuleSettings.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,71 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp
-
-import com.demonwav.mcdev.platform.mcp.srg.SrgType
-import com.intellij.openapi.components.PersistentStateComponent
-import com.intellij.openapi.components.State
-import com.intellij.openapi.components.Storage
-import com.intellij.openapi.components.StoragePathMacros
-import com.intellij.openapi.module.Module
-import com.intellij.openapi.module.ModuleManager
-
-@State(name = "McpModuleSettings", storages = [Storage(StoragePathMacros.MODULE_FILE)])
-class McpModuleSettings : PersistentStateComponent {
-
- data class State(
- var minecraftVersion: String? = null,
- var mcpVersion: String? = null,
- var mappingFile: String? = null,
- var srgType: SrgType? = null,
- var platformVersion: String? = null,
- )
-
- private var state: State = State(srgType = SrgType.SRG)
-
- override fun getState(): State = state
-
- override fun loadState(state: State) {
- this.state = state
- }
-
- companion object {
- fun getInstance(module: Module): McpModuleSettings {
- // TODO: Migrate these to the facet's settings
-
- val settings = module.getService(McpModuleSettings::class.java) as McpModuleSettings
- if (settings.getState().minecraftVersion != null) {
- return settings
- }
-
- // Attempt to find settings on the parent module
- val manager = ModuleManager.getInstance(module.project)
- val path = manager.getModuleGroupPath(module) ?: return settings
- val parent = manager.findModuleByName(path.last()) ?: return settings
-
- val newSettings = parent.getService(McpModuleSettings::class.java) as McpModuleSettings
- if (newSettings.getState().minecraftVersion == null) {
- return settings
- }
- return newSettings
- }
- }
-}
Index: src/main/kotlin/platform/mcp/McpModuleType.kt
===================================================================
--- src/main/kotlin/platform/mcp/McpModuleType.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/McpModuleType.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,60 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp
-
-import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.AbstractModuleType
-import com.demonwav.mcdev.platform.PlatformType
-import com.demonwav.mcdev.platform.mcp.mappings.getMappedClass
-import com.demonwav.mcdev.platform.mcp.mappings.getMappedField
-import com.demonwav.mcdev.platform.mcp.util.McpConstants
-import com.demonwav.mcdev.util.CommonColors
-import com.intellij.openapi.module.Module
-import java.awt.Color
-import javax.swing.Icon
-
-object McpModuleType : AbstractModuleType("", "") {
-
- private const val ID = "MCP_MODULE_TYPE"
-
- init {
- CommonColors.applyStandardColors(colorMap, McpConstants.CHAT_FORMATTING)
- CommonColors.applyStandardColors(colorMap, McpConstants.TEXT_COLOR)
- }
-
- override fun classToColorMappings(module: Module): Map {
- return colorMap.mapKeys { key ->
- val parts = key.key.split('.')
- val className = parts.dropLast(1).joinToString(".")
- val fieldName = parts.last()
- "${module.getMappedClass(className)}.${module.getMappedField(className, fieldName)}"
- }
- }
-
- override val platformType = PlatformType.MCP
- override val icon: Icon? = null
- override val id = ID
- override val ignoredAnnotations = emptyList()
- override val listenerAnnotations = emptyList()
- override val hasIcon = false
-
- override fun generateModule(facet: MinecraftFacet) = McpModule(facet)
-}
Index: src/main/kotlin/platform/mcp/actions/CopyAtAction.kt
===================================================================
--- src/main/kotlin/platform/mcp/actions/CopyAtAction.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/actions/CopyAtAction.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,115 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.actions
-
-import com.demonwav.mcdev.platform.mcp.mappings.Mappings
-import com.demonwav.mcdev.util.ActionData
-import com.demonwav.mcdev.util.descriptor
-import com.demonwav.mcdev.util.fullQualifiedName
-import com.demonwav.mcdev.util.internalName
-import com.demonwav.mcdev.util.showBalloon
-import com.demonwav.mcdev.util.showSuccessBalloon
-import com.intellij.openapi.actionSystem.AnActionEvent
-import com.intellij.openapi.editor.Editor
-import com.intellij.psi.PsiClass
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiField
-import com.intellij.psi.PsiMethod
-import java.awt.Toolkit
-import java.awt.datatransfer.StringSelection
-
-class CopyAtAction : SrgActionBase() {
- override fun withSrgTarget(parent: PsiElement, srgMap: Mappings?, e: AnActionEvent, data: ActionData) {
- if (srgMap == null) {
- when (parent) {
- is PsiField -> {
- val className = parent.containingClass?.fullQualifiedName ?: return showBalloon(
- e,
- "No containing class found"
- )
- copyToClipboard(
- data.editor,
- data.element,
- className + " " + parent.name,
- )
- }
- is PsiMethod -> {
- val className = parent.containingClass?.fullQualifiedName ?: return showBalloon(
- e,
- "No containing class found"
- )
- copyToClipboard(
- data.editor,
- data.element,
- className + " " + parent.internalName + parent.descriptor,
- )
- }
- is PsiClass -> {
- val className = parent.fullQualifiedName ?: return showBalloon(e, "Could not get FQN")
- copyToClipboard(
- data.editor,
- data.element,
- className,
- )
- }
- }
- } else {
- when (parent) {
- is PsiField -> {
- val containing = parent.containingClass ?: return showBalloon(e, "No SRG name found")
- val classSrg = srgMap.getIntermediaryClass(containing) ?: return showBalloon(e, "No SRG name found")
- val srg = srgMap.getIntermediaryField(parent) ?: return showBalloon(e, "No SRG name found")
- copyToClipboard(
- data.editor,
- data.element,
- classSrg + " " + srg.name + " # " + parent.name,
- )
- }
-
- is PsiMethod -> {
- val containing = parent.containingClass ?: return showBalloon(e, "No SRG name found")
- val classSrg = srgMap.getIntermediaryClass(containing) ?: return showBalloon(e, "No SRG name found")
- val srg = srgMap.getIntermediaryMethod(parent) ?: return showBalloon(e, "No SRG name found")
- copyToClipboard(
- data.editor,
- data.element,
- classSrg + " " + srg.name + srg.descriptor + " # " + parent.name,
- )
- }
-
- is PsiClass -> {
- val classMcpToSrg =
- srgMap.getIntermediaryClass(parent) ?: return showBalloon(e, "No SRG name found")
- copyToClipboard(data.editor, data.element, classMcpToSrg)
- }
-
- else -> showBalloon(e, "Not a valid element")
- }
- }
- }
-
- private fun copyToClipboard(editor: Editor, element: PsiElement, text: String) {
- val stringSelection = StringSelection(text)
- val clpbrd = Toolkit.getDefaultToolkit().systemClipboard
- clpbrd.setContents(stringSelection, null)
- showSuccessBalloon(editor, element, "Copied $text")
- }
-}
Index: src/main/kotlin/platform/mcp/actions/CopyAwAction.kt
===================================================================
--- src/main/kotlin/platform/mcp/actions/CopyAwAction.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/actions/CopyAwAction.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,102 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.actions
-
-import com.demonwav.mcdev.util.descriptor
-import com.demonwav.mcdev.util.getDataFromActionEvent
-import com.demonwav.mcdev.util.internalName
-import com.demonwav.mcdev.util.showBalloon
-import com.demonwav.mcdev.util.showSuccessBalloon
-import com.intellij.openapi.actionSystem.AnAction
-import com.intellij.openapi.actionSystem.AnActionEvent
-import com.intellij.openapi.editor.Editor
-import com.intellij.psi.PsiClass
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiField
-import com.intellij.psi.PsiIdentifier
-import com.intellij.psi.PsiMember
-import com.intellij.psi.PsiMethod
-import com.intellij.psi.PsiReference
-import java.awt.Toolkit
-import java.awt.datatransfer.StringSelection
-
-class CopyAwAction : AnAction() {
-
- override fun actionPerformed(e: AnActionEvent) {
- val data = getDataFromActionEvent(e) ?: return showBalloon(e, "Unknown failure")
- val editor = data.editor
-
- val element = data.element
- if (element !is PsiIdentifier) {
- showBalloon(e, "Invalid element")
- return
- }
-
- val target = when (val parent = element.parent) {
- is PsiMember -> parent
- is PsiReference -> parent.resolve()
- else -> null
- } ?: return showBalloon(e, "Invalid element")
-
- Util.doCopy(target, element, editor, e)
- }
-
- object Util {
- fun doCopy(target: PsiElement, element: PsiElement, editor: Editor?, e: AnActionEvent?) {
- when (target) {
- is PsiClass -> {
- val text = "accessible class ${target.internalName}"
- copyToClipboard(editor, element, text)
- }
- is PsiField -> {
- val containing = target.containingClass?.internalName
- ?: return maybeShow(e, "Could not get owner of field")
- val desc = target.type.descriptor
- val text = "accessible field $containing ${target.name} $desc"
- copyToClipboard(editor, element, text)
- }
- is PsiMethod -> {
- val containing = target.containingClass?.internalName
- ?: return maybeShow(e, "Could not get owner of method")
- val desc = target.descriptor ?: return maybeShow(e, "Could not get descriptor of method")
- val text = "accessible method $containing ${target.internalName} $desc"
- copyToClipboard(editor, element, text)
- }
- else -> maybeShow(e, "Invalid element")
- }
- }
-
- private fun copyToClipboard(editor: Editor?, element: PsiElement, text: String) {
- val stringSelection = StringSelection(text)
- val clpbrd = Toolkit.getDefaultToolkit().systemClipboard
- clpbrd.setContents(stringSelection, null)
- if (editor != null) {
- showSuccessBalloon(editor, element, "Copied: \"$text\"")
- }
- }
-
- private fun maybeShow(e: AnActionEvent?, text: String) {
- if (e != null) {
- showBalloon(e, text)
- }
- }
- }
-}
Index: src/main/kotlin/platform/mcp/actions/CopyCoremodTargetAction.kt
===================================================================
--- src/main/kotlin/platform/mcp/actions/CopyCoremodTargetAction.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/actions/CopyCoremodTargetAction.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,102 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.actions
-
-import com.demonwav.mcdev.platform.mcp.mappings.Mappings
-import com.demonwav.mcdev.util.ActionData
-import com.demonwav.mcdev.util.descriptor
-import com.demonwav.mcdev.util.fullQualifiedName
-import com.demonwav.mcdev.util.showBalloon
-import com.demonwav.mcdev.util.showSuccessBalloon
-import com.intellij.openapi.actionSystem.AnActionEvent
-import com.intellij.openapi.editor.Editor
-import com.intellij.psi.PsiClass
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiField
-import com.intellij.psi.PsiMethod
-import java.awt.Toolkit
-import java.awt.datatransfer.StringSelection
-import kotlinx.serialization.json.JsonObject
-import kotlinx.serialization.json.JsonPrimitive
-
-class CopyCoremodTargetAction : SrgActionBase() {
- override fun withSrgTarget(parent: PsiElement, srgMap: Mappings?, e: AnActionEvent, data: ActionData) {
- when (parent) {
- is PsiField -> {
- val containing = parent.containingClass ?: return showBalloon(e, "No containing class")
- val classSrg = srgMap?.getIntermediaryClass(containing) ?: containing.fullQualifiedName ?: return showBalloon(
- e,
- "No containing class found"
- )
- val srg = srgMap?.getIntermediaryField(parent)?.name ?: parent.name
- copyToClipboard(
- data.editor,
- data.element,
- Pair("target", "FIELD"),
- Pair("class", classSrg),
- Pair("fieldName", srg),
- )
- }
- is PsiMethod -> {
- val containing = parent.containingClass ?: return showBalloon(e, "No containing class")
- val classSrg = srgMap?.getIntermediaryClass(containing) ?: containing.fullQualifiedName ?: return showBalloon(
- e,
- "No containing class found"
- )
- val (srgName, srgDescriptor) = srgMap?.getIntermediaryMethod(parent)?.let {
- it.name to it.descriptor
- } ?: (parent.name to parent.descriptor)
- if (srgDescriptor == null) {
- return showBalloon(e, "No method descriptor found")
- }
- copyToClipboard(
- data.editor,
- data.element,
- Pair("target", "METHOD"),
- Pair("class", classSrg),
- Pair("methodName", srgName),
- Pair("methodDesc", srgDescriptor),
- )
- }
- is PsiClass -> {
- val classSrg = srgMap?.getIntermediaryClass(parent) ?: parent.fullQualifiedName ?: return showBalloon(
- e,
- "No FQN found"
- )
- copyToClipboard(
- data.editor,
- data.element,
- Pair("target", "CLASS"),
- Pair("name", classSrg),
- )
- }
- else -> showBalloon(e, "Not a valid element")
- }
- }
-
- private fun copyToClipboard(editor: Editor, element: PsiElement, vararg keys: Pair) {
- val text = JsonObject(keys.toMap().mapValues { JsonPrimitive(it.value) }).toString()
- val stringSelection = StringSelection(text)
- val clpbrd = Toolkit.getDefaultToolkit().systemClipboard
- clpbrd.setContents(stringSelection, null)
- showSuccessBalloon(editor, element, "Copied Coremod Target Reference")
- }
-}
Index: src/main/kotlin/platform/mcp/actions/FindSrgMappingAction.kt
===================================================================
--- src/main/kotlin/platform/mcp/actions/FindSrgMappingAction.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/actions/FindSrgMappingAction.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,56 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.actions
-
-import com.demonwav.mcdev.platform.mcp.mappings.Mappings
-import com.demonwav.mcdev.util.ActionData
-import com.demonwav.mcdev.util.showBalloon
-import com.demonwav.mcdev.util.showSuccessBalloon
-import com.intellij.openapi.actionSystem.AnActionEvent
-import com.intellij.psi.PsiClass
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiField
-import com.intellij.psi.PsiMethod
-
-class FindSrgMappingAction : SrgActionBase() {
-
- override fun withSrgTarget(parent: PsiElement, srgMap: Mappings?, e: AnActionEvent, data: ActionData) {
- if (srgMap == null) {
- return showBalloon(e, "No mappings found")
- }
-
- when (parent) {
- is PsiField -> {
- val srg = srgMap.getIntermediaryField(parent) ?: return showBalloon(e, "No SRG name found")
- showSuccessBalloon(data.editor, data.element, "SRG name: " + srg.name)
- }
- is PsiMethod -> {
- val srg = srgMap.getIntermediaryMethod(parent) ?: return showBalloon(e, "No SRG name found")
- showSuccessBalloon(data.editor, data.element, "SRG name: " + srg.name + srg.descriptor)
- }
- is PsiClass -> {
- val classMcpToSrg = srgMap.getIntermediaryClass(parent) ?: return showBalloon(e, "No SRG name found")
- showSuccessBalloon(data.editor, data.element, "SRG name: $classMcpToSrg")
- }
- else -> showBalloon(e, "Not a valid element")
- }
- }
-}
Index: src/main/kotlin/platform/mcp/actions/GotoAtEntryAction.kt
===================================================================
--- src/main/kotlin/platform/mcp/actions/GotoAtEntryAction.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/actions/GotoAtEntryAction.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,117 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.actions
-
-import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.mcp.McpModuleType
-import com.demonwav.mcdev.platform.mcp.mappings.MappingsManager
-import com.demonwav.mcdev.platform.mixin.handlers.ShadowHandler
-import com.demonwav.mcdev.util.ActionData
-import com.demonwav.mcdev.util.getDataFromActionEvent
-import com.demonwav.mcdev.util.gotoTargetElement
-import com.demonwav.mcdev.util.qualifiedMemberReference
-import com.demonwav.mcdev.util.showBalloon
-import com.demonwav.mcdev.util.simpleQualifiedMemberReference
-import com.intellij.openapi.actionSystem.AnAction
-import com.intellij.openapi.actionSystem.AnActionEvent
-import com.intellij.openapi.module.ModuleManager
-import com.intellij.psi.PsiField
-import com.intellij.psi.PsiIdentifier
-import com.intellij.psi.PsiManager
-import com.intellij.psi.PsiMember
-import com.intellij.psi.PsiMethod
-import com.intellij.psi.search.LocalSearchScope
-import com.intellij.psi.search.PsiSearchHelper
-import com.intellij.psi.search.UsageSearchContext
-
-class GotoAtEntryAction : AnAction() {
- override fun actionPerformed(e: AnActionEvent) {
- val data = getDataFromActionEvent(e) ?: return showBalloon(e)
-
- if (data.element !is PsiIdentifier) {
- showBalloon(e)
- return
- }
-
- val mappingsManager = data.instance.getModuleOfType(McpModuleType)?.mappingsManager
- // Not all ATs are in MCP modules, fallback to this if possible
- // TODO try to find SRG references for all modules if current module isn't found?
- ?: MappingsManager.findAnyInstance(data.project) ?: return showBalloon(e)
-
- mappingsManager.mappings.onSuccess { srgMap ->
- var parent = data.element.parent
-
- if (parent is PsiMember) {
- val shadowTarget = ShadowHandler.Util.getInstance()?.findFirstShadowTargetForNavigation(parent)?.element
- if (shadowTarget != null) {
- parent = shadowTarget
- }
- }
-
- when (parent) {
- is PsiField -> {
- val reference = srgMap.getIntermediaryField(parent) ?: parent.simpleQualifiedMemberReference
- searchForText(e, data, reference.name)
- }
- is PsiMethod -> {
- val reference = srgMap.getIntermediaryMethod(parent) ?: parent.qualifiedMemberReference
- searchForText(e, data, reference.name + reference.descriptor)
- }
- else ->
- showBalloon(e)
- }
- }
- }
-
- private fun searchForText(e: AnActionEvent, data: ActionData, text: String) {
- val manager = ModuleManager.getInstance(data.project)
- manager.modules.asSequence()
- .mapNotNull { MinecraftFacet.getInstance(it, McpModuleType) }
- .flatMap { it.accessTransformers.asSequence() }
- .forEach { virtualFile ->
- val file = PsiManager.getInstance(data.project).findFile(virtualFile) ?: return@forEach
-
- var found = false
- PsiSearchHelper.getInstance(data.project)
- .processElementsWithWord(
- { element, _ ->
- gotoTargetElement(element, data.editor, data.file)
- found = true
- false
- },
- LocalSearchScope(file),
- text,
- UsageSearchContext.ANY,
- true,
- )
-
- if (found) {
- return
- }
- }
-
- showBalloon(e)
- }
-
- private fun showBalloon(e: AnActionEvent) {
- showBalloon(e, "No access transformer entry found")
- }
-}
Index: src/main/kotlin/platform/mcp/actions/LookupMemberAction.kt
===================================================================
--- src/main/kotlin/platform/mcp/actions/LookupMemberAction.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/actions/LookupMemberAction.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,30 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.actions
-
-import com.intellij.openapi.actionSystem.AnAction
-import com.intellij.openapi.actionSystem.AnActionEvent
-
-class LookupMemberAction : AnAction() {
- override fun actionPerformed(e: AnActionEvent) {
- // TODO
- }
-}
Index: src/main/kotlin/platform/mcp/actions/SrgActionBase.kt
===================================================================
--- src/main/kotlin/platform/mcp/actions/SrgActionBase.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/actions/SrgActionBase.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,79 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.actions
-
-import com.demonwav.mcdev.platform.mcp.McpModuleType
-import com.demonwav.mcdev.platform.mcp.mappings.Mappings
-import com.demonwav.mcdev.platform.mixin.handlers.ShadowHandler
-import com.demonwav.mcdev.util.ActionData
-import com.demonwav.mcdev.util.getDataFromActionEvent
-import com.demonwav.mcdev.util.showBalloon
-import com.intellij.openapi.actionSystem.AnAction
-import com.intellij.openapi.actionSystem.AnActionEvent
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiIdentifier
-import com.intellij.psi.PsiMember
-import com.intellij.psi.PsiReference
-
-abstract class SrgActionBase : AnAction() {
-
- override fun actionPerformed(e: AnActionEvent) {
- val data = getDataFromActionEvent(e) ?: return showBalloon(e, "Unknown failure")
-
- if (data.element !is PsiIdentifier) {
- showBalloon(e, "Not a valid element")
- return
- }
-
- val mcpModule = data.instance.getModuleOfType(McpModuleType)
-
- val mappingsManager = mcpModule?.mappingsManager ?: return performWithMappings(e, data, data.element, null)
- mappingsManager.mappings.onSuccess { srgMap ->
- performWithMappings(e, data, data.element, srgMap)
- }.onError {
- showBalloon(e, it.message ?: "No MCP data available")
- }
- }
-
- private fun performWithMappings(
- e: AnActionEvent,
- data: ActionData,
- element: PsiIdentifier,
- srgMap: Mappings?,
- ) {
- var parent = element.parent ?: return showBalloon(e, "Not a valid element")
-
- if (parent is PsiMember) {
- val shadowTarget = ShadowHandler.Util.getInstance()?.findFirstShadowTargetForReference(parent)?.element
- if (shadowTarget != null) {
- parent = shadowTarget
- }
- }
-
- if (parent is PsiReference) {
- parent = parent.resolve() ?: return showBalloon(e, "Not a valid element")
- }
-
- withSrgTarget(parent, srgMap, e, data)
- }
-
- abstract fun withSrgTarget(parent: PsiElement, srgMap: Mappings?, e: AnActionEvent, data: ActionData)
-}
Index: src/main/kotlin/platform/mcp/at/AtAnnotator.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/AtAnnotator.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/AtAnnotator.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,91 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at
-
-import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.mcp.McpModuleType
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtEntry
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtFieldName
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtFunction
-import com.demonwav.mcdev.platform.mcp.at.psi.AtElement
-import com.intellij.lang.annotation.AnnotationHolder
-import com.intellij.lang.annotation.Annotator
-import com.intellij.lang.annotation.HighlightSeverity
-import com.intellij.openapi.editor.markup.EffectType
-import com.intellij.openapi.editor.markup.TextAttributes
-import com.intellij.openapi.module.ModuleUtilCore
-import com.intellij.psi.PsiElement
-import java.awt.Font
-
-class AtAnnotator : Annotator {
-
- override fun annotate(element: PsiElement, holder: AnnotationHolder) {
- if (element !is AtEntry) {
- return
- }
-
- val member = element.function ?: element.fieldName ?: return
-
- val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return
- val facet = MinecraftFacet.getInstance(module) ?: return
- val mcpModule = facet.getModuleOfType(McpModuleType) ?: return
- val srgMap = mcpModule.mappingsManager?.mappingsNow ?: return
-
- val reference = AtMemberReference.get(element, member) ?: return
-
- // We can resolve this without checking the srg map
- if (reference.resolveMember(element.project) != null) {
- if (member is AtFunction) {
- underline(member.funcName, holder)
- } else {
- underline(member, holder)
- }
- return
- }
-
- // We need to check the srg map, or it can't be resolved (and no underline)
- when (member) {
- is AtFieldName -> {
- srgMap.tryGetMappedField(reference)?.resolveMember(element.project) ?: return
- underline(member, holder)
- }
- is AtFunction -> {
- srgMap.tryGetMappedMethod(reference)?.resolveMember(element.project) ?: return
- underline(member.funcName, holder)
- }
- }
- }
-
- private fun underline(element: AtElement, holder: AnnotationHolder) {
- holder.newSilentAnnotation(HighlightSeverity.INFORMATION)
- .range(element)
- .enforcedTextAttributes(
- TextAttributes(
- null,
- null,
- AtSyntaxHighlighter.ELEMENT_NAME.defaultAttributes.foregroundColor,
- EffectType.BOLD_LINE_UNDERSCORE,
- Font.PLAIN,
- ),
- )
- .create()
- }
-}
Index: src/main/kotlin/platform/mcp/at/AtColorSettingsPage.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/AtColorSettingsPage.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/AtColorSettingsPage.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,62 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at
-
-import com.demonwav.mcdev.asset.PlatformAssets
-import com.intellij.openapi.editor.colors.TextAttributesKey
-import com.intellij.openapi.options.colors.AttributesDescriptor
-import com.intellij.openapi.options.colors.ColorDescriptor
-import com.intellij.openapi.options.colors.ColorSettingsPage
-
-class AtColorSettingsPage : ColorSettingsPage {
-
- override fun getIcon() = PlatformAssets.MCP_ICON
- override fun getHighlighter() = AtSyntaxHighlighter()
- override fun getDemoText() =
- $$"""
- # Minecraft
-
- public net.minecraft.block.BlockFlowerPot func_149928_a(Lnet/minecraft/block/Block;I)Z # canNotContain
- private-f net.minecraft.inventory.ContainerChest field_7515F4_f # numRows
- protected net.minecraft.block.state.BlockStateContainer$StateImplementation
- public-f net.minecraft.item.Item func_77656_e(I)Lnet/minecraft/item/Item; # setMaxDamage
- public+f net.minecraft.server.management.UserList *
- default+f net.minecraft.item.Item *()
- public net.minecraft.world.demo.DemoWorldServer func_175680_a(IIZ)Z # isChunkLoaded
- """.trimIndent()
-
- override fun getAdditionalHighlightingTagToDescriptorMap(): Map? = null
- override fun getAttributeDescriptors() = Constants.DESCRIPTORS
- override fun getColorDescriptors(): Array = ColorDescriptor.EMPTY_ARRAY
- override fun getDisplayName() = "Access Transformers"
-
- private object Constants {
- val DESCRIPTORS = arrayOf(
- AttributesDescriptor("Keyword", AtSyntaxHighlighter.KEYWORD),
- AttributesDescriptor("Class name", AtSyntaxHighlighter.CLASS_NAME),
- AttributesDescriptor("Class value", AtSyntaxHighlighter.CLASS_VALUE),
- AttributesDescriptor("Primitive value", AtSyntaxHighlighter.PRIMITIVE),
- AttributesDescriptor("Element name", AtSyntaxHighlighter.ELEMENT_NAME),
- AttributesDescriptor("Asterisk", AtSyntaxHighlighter.ASTERISK),
- AttributesDescriptor("Comment", AtSyntaxHighlighter.COMMENT),
- )
- }
-}
Index: src/main/kotlin/platform/mcp/at/AtCommenter.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/AtCommenter.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/AtCommenter.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,32 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at
-
-import com.intellij.lang.Commenter
-
-class AtCommenter : Commenter {
-
- override fun getLineCommentPrefix() = "#"
- override fun getBlockCommentPrefix(): String? = null
- override fun getBlockCommentSuffix(): String? = null
- override fun getCommentedBlockCommentPrefix(): String? = null
- override fun getCommentedBlockCommentSuffix(): String? = null
-}
Index: src/main/kotlin/platform/mcp/at/AtElementFactory.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/AtElementFactory.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/AtElementFactory.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,137 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-@file:Suppress("unused") // this file represents an API
-
-package com.demonwav.mcdev.platform.mcp.at
-
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtArgument
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtAsterisk
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtClassName
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtEntry
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtFieldName
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtFuncName
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtFunction
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtKeyword
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtReturnValue
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtTypes
-import com.intellij.openapi.project.Project
-import com.intellij.psi.PsiComment
-import com.intellij.psi.PsiFileFactory
-
-object AtElementFactory {
-
- fun createFile(project: Project, text: String): AtFile {
- return PsiFileFactory.getInstance(project).createFileFromText("name", AtFileType, text) as AtFile
- }
-
- fun createArgument(project: Project, text: String): AtArgument {
- val line = "public c.c f($text)V"
- val file = createFile(project, line)
-
- return file.firstChild.node.findChildByType(AtTypes.FUNCTION)!!
- .findChildByType(AtTypes.ARGUMENT)!!.psi as AtArgument
- }
-
- fun createClassName(project: Project, name: String): AtClassName {
- val line = "public $name f(Z)V"
- val file = createFile(project, line)
-
- return file.firstChild.node.findChildByType(AtTypes.CLASS_NAME)!!.psi as AtClassName
- }
-
- fun createEntry(project: Project, entry: String): AtEntry {
- val file = createFile(project, entry)
- return file.firstChild as AtEntry
- }
-
- fun createFieldName(project: Project, name: String): AtFieldName {
- val line = "public c.c $name"
- val file = createFile(project, line)
-
- return file.firstChild.node.findChildByType(AtTypes.FIELD_NAME)!!.psi as AtFieldName
- }
-
- fun createFuncName(project: Project, name: String): AtFuncName {
- val line = "public c.c $name(Z)V"
- val file = createFile(project, line)
-
- return file.firstChild.node.findChildByType(AtTypes.FUNCTION)!!
- .findChildByType(AtTypes.FUNC_NAME)!!.psi as AtFuncName
- }
-
- fun createFunction(project: Project, function: String): AtFunction {
- val line = "public c.c $function"
- val file = createFile(project, line)
-
- return file.firstChild.node.findChildByType(AtTypes.FUNCTION)!!.psi as AtFunction
- }
-
- fun createAsterisk(project: Project): AtAsterisk {
- val line = "public c.c *"
- val file = createFile(project, line)
-
- return file.firstChild.node.findChildByType(AtTypes.FUNCTION)!!
- .findChildByType(AtTypes.ASTERISK)!!.psi as AtAsterisk
- }
-
- fun createKeyword(project: Project, keyword: Keyword): AtKeyword {
- val line = "${keyword.text} c.c f(Z)V"
- val file = createFile(project, line)
-
- return file.firstChild.node.findChildByType(AtTypes.KEYWORD)!!.psi as AtKeyword
- }
-
- fun createReturnValue(project: Project, returnValue: String): AtReturnValue {
- val line = "public c.c f(Z)$returnValue"
- val file = createFile(project, line)
-
- return file.firstChild.node.findChildByType(AtTypes.FUNCTION)!!
- .findChildByType(AtTypes.RETURN_VALUE)!!.psi as AtReturnValue
- }
-
- fun createComment(project: Project, comment: String): PsiComment {
- val line = "# $comment"
- val file = createFile(project, line)
-
- return file.node.findChildByType(AtTypes.COMMENT)!!.psi as PsiComment
- }
-
- enum class Keyword(val text: String) {
- PRIVATE("private"),
- PRIVATE_MINUS_F("private-f"),
- PRIVATE_PLUS_F("private+f"),
- PROTECTED("protected"),
- PROTECTED_MINUS_F("protected-f"),
- PROTECTED_PLUS_F("protected+f"),
- PUBLIC("public"),
- PUBLIC_MINUS_F("public-f"),
- PUBLIC_PLUS_F("public+f"),
- DEFAULT("default"),
- DEFAULT_MINUS_F("default-f"),
- DEFAULT_PLUS_F("default+f"),
- ;
-
- companion object {
- fun match(s: String) = entries.firstOrNull { it.text == s }
- fun softMatch(s: String) = entries.filter { it.text.contains(s) }
- }
- }
-}
Index: src/main/kotlin/platform/mcp/at/AtFile.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/AtFile.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/AtFile.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,52 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at
-
-import com.demonwav.mcdev.asset.PlatformAssets
-import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.mcp.McpModuleType
-import com.intellij.extapi.psi.PsiFileBase
-import com.intellij.openapi.application.ApplicationManager
-import com.intellij.openapi.module.ModuleUtilCore
-import com.intellij.psi.FileViewProvider
-
-class AtFile(viewProvider: FileViewProvider) : PsiFileBase(viewProvider, AtLanguage) {
-
- init {
- setup()
- }
-
- private fun setup() {
- if (ApplicationManager.getApplication().isUnitTestMode) {
- return
- }
-
- val vFile = viewProvider.virtualFile
-
- val module = ModuleUtilCore.findModuleForFile(vFile, project) ?: return
- val mcpModule = MinecraftFacet.getInstance(module, McpModuleType) ?: return
- mcpModule.addAccessTransformerFile(vFile)
- }
-
- override fun getFileType() = AtFileType
- override fun toString() = AtFileType.description
- override fun getIcon(flags: Int) = PlatformAssets.MCP_ICON
-}
Index: src/main/kotlin/platform/mcp/at/AtFileType.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/AtFileType.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/AtFileType.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,32 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at
-
-import com.demonwav.mcdev.asset.PlatformAssets
-import com.intellij.openapi.fileTypes.LanguageFileType
-
-object AtFileType : LanguageFileType(AtLanguage) {
-
- override fun getName() = "Access Transformers"
- override fun getDescription() = "Access transformers"
- override fun getDefaultExtension() = ""
- override fun getIcon() = PlatformAssets.MCP_ICON
-}
Index: src/main/kotlin/platform/mcp/at/AtGotoDeclarationHandler.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/AtGotoDeclarationHandler.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/AtGotoDeclarationHandler.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,110 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at
-
-import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.mcp.McpModuleType
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtClassName
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtEntry
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtFieldName
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtFuncName
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtFunction
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtTypes
-import com.demonwav.mcdev.util.findQualifiedClass
-import com.demonwav.mcdev.util.getPrimitiveType
-import com.demonwav.mcdev.util.parseClassDescriptor
-import com.intellij.codeInsight.navigation.actions.GotoDeclarationHandler
-import com.intellij.openapi.actionSystem.DataContext
-import com.intellij.openapi.editor.Editor
-import com.intellij.openapi.module.ModuleUtilCore
-import com.intellij.psi.JavaPsiFacade
-import com.intellij.psi.PsiElement
-import com.intellij.psi.search.GlobalSearchScope
-
-class AtGotoDeclarationHandler : GotoDeclarationHandler {
- override fun getGotoDeclarationTargets(
- sourceElement: PsiElement?,
- offset: Int,
- editor: Editor,
- ): Array? {
- if (sourceElement?.language !== AtLanguage) {
- return null
- }
-
- val module = ModuleUtilCore.findModuleForPsiElement(sourceElement) ?: return null
-
- val instance = MinecraftFacet.getInstance(module) ?: return null
-
- val mcpModule = instance.getModuleOfType(McpModuleType) ?: return null
-
- val srgMap = mcpModule.mappingsManager?.mappingsNow ?: return null
-
- return when {
- sourceElement.node.treeParent.elementType === AtTypes.CLASS_NAME -> {
- val className = sourceElement.parent as AtClassName
- val classSrgToMcp = srgMap.getMappedClass(className.classNameText)
- val psiClass = findQualifiedClass(sourceElement.project, classSrgToMcp) ?: return null
- arrayOf(psiClass)
- }
- sourceElement.node.treeParent.elementType === AtTypes.FUNC_NAME -> {
- val funcName = sourceElement.parent as AtFuncName
- val function = funcName.parent as AtFunction
- val entry = function.parent as AtEntry
-
- val reference = srgMap.getMappedMethod(AtMemberReference.get(entry, function) ?: return null)
- val member = reference.resolveMember(sourceElement.project) ?: return null
- arrayOf(member)
- }
- sourceElement.node.treeParent.elementType === AtTypes.FIELD_NAME -> {
- val fieldName = sourceElement.parent as AtFieldName
- val entry = fieldName.parent as AtEntry
-
- val reference = srgMap.getMappedField(AtMemberReference.get(entry, fieldName) ?: return null)
- val member = reference.resolveMember(sourceElement.project) ?: return null
- arrayOf(member)
- }
- sourceElement.node.elementType === AtTypes.CLASS_VALUE -> {
- val className = srgMap.getMappedClass(parseClassDescriptor(sourceElement.text))
- val psiClass = findQualifiedClass(sourceElement.project, className) ?: return null
- arrayOf(psiClass)
- }
- sourceElement.node.elementType === AtTypes.PRIMITIVE -> {
- val text = sourceElement.text
- if (text.length != 1) {
- return null
- }
-
- val type = getPrimitiveType(text[0]) ?: return null
-
- val boxedType = type.boxedTypeName ?: return null
-
- val psiClass = JavaPsiFacade.getInstance(sourceElement.project).findClass(
- boxedType,
- GlobalSearchScope.allScope(sourceElement.project),
- ) ?: return null
- arrayOf(psiClass)
- }
- else -> null
- }
- }
-
- override fun getActionText(context: DataContext): String? = null
-}
Index: src/main/kotlin/platform/mcp/at/AtLanguage.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/AtLanguage.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/AtLanguage.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,29 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at
-
-import com.intellij.lang.Language
-import java.io.Serial
-
-object AtLanguage : Language("Access Transformers") {
- @Serial
- private fun readResolve(): Any = AtLanguage
-}
Index: src/main/kotlin/platform/mcp/at/AtLexerAdapter.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/AtLexerAdapter.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/AtLexerAdapter.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,26 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at
-
-import com.demonwav.mcdev.platform.mcp.at.gen.AtLexer
-import com.intellij.lexer.FlexAdapter
-
-class AtLexerAdapter : FlexAdapter(AtLexer())
Index: src/main/kotlin/platform/mcp/at/AtMemberReference.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/AtMemberReference.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/AtMemberReference.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,41 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at
-
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtEntry
-import com.demonwav.mcdev.util.MemberReference
-import com.intellij.psi.PsiElement
-
-object AtMemberReference {
-
- fun get(entry: AtEntry, member: PsiElement): MemberReference? {
- val memberText = member.text
-
- val owner = entry.className?.text ?: return null
-
- val pos = memberText.indexOf('(')
- return if (pos != -1) {
- MemberReference(memberText.substring(0, pos), memberText.substring(pos), owner)
- } else {
- MemberReference(memberText, null, owner)
- }
- }
-}
Index: src/main/kotlin/platform/mcp/at/AtParserDefinition.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/AtParserDefinition.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/AtParserDefinition.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,66 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at
-
-import com.demonwav.mcdev.platform.mcp.at.gen.parser.AtParser
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtTypes
-import com.intellij.lang.ASTNode
-import com.intellij.lang.Language
-import com.intellij.lang.ParserDefinition
-import com.intellij.openapi.project.Project
-import com.intellij.psi.FileViewProvider
-import com.intellij.psi.PsiElement
-import com.intellij.psi.tree.IElementType
-import com.intellij.psi.tree.IFileElementType
-import com.intellij.psi.tree.TokenSet
-
-class AtParserDefinition : ParserDefinition {
-
- override fun createLexer(project: Project) = AtLexerAdapter()
- override fun getCommentTokens() = TokenSets.COMMENTS
- override fun getStringLiteralElements(): TokenSet = TokenSet.EMPTY
- override fun createParser(project: Project) = AtParser()
- override fun getFileNodeType() = TokenSets.FILE
- override fun createFile(viewProvider: FileViewProvider) = AtFile(viewProvider)
- override fun createElement(node: ASTNode): PsiElement = AtTypes.Factory.createElement(node)
-
- override fun spaceExistenceTypeBetweenTokens(left: ASTNode, right: ASTNode) =
- TokenSets.MAP.entries.firstOrNull { e -> left.elementType == e.key.first || right.elementType == e.key.second }?.value
- ?: ParserDefinition.SpaceRequirements.MUST_NOT
-
- object TokenSets {
- val COMMENTS = TokenSet.create(AtTypes.COMMENT)
-
- val FILE = IFileElementType(Language.findInstance(AtLanguage::class.java))
-
- val MAP: Map, ParserDefinition.SpaceRequirements> = mapOf(
- (AtTypes.KEYWORD to AtTypes.CLASS_NAME) to ParserDefinition.SpaceRequirements.MUST,
- (AtTypes.CLASS_NAME to AtTypes.FIELD_NAME) to ParserDefinition.SpaceRequirements.MUST,
- (AtTypes.CLASS_NAME to AtTypes.FUNCTION) to ParserDefinition.SpaceRequirements.MUST,
- (AtTypes.CLASS_NAME to AtTypes.ASTERISK) to ParserDefinition.SpaceRequirements.MUST,
- (AtTypes.FIELD_NAME to AtTypes.COMMENT) to ParserDefinition.SpaceRequirements.MUST,
- (AtTypes.ASTERISK to AtTypes.COMMENT) to ParserDefinition.SpaceRequirements.MUST,
- (AtTypes.COMMENT to AtTypes.KEYWORD) to ParserDefinition.SpaceRequirements.MUST_LINE_BREAK,
- (AtTypes.COMMENT to AtTypes.COMMENT) to ParserDefinition.SpaceRequirements.MUST_LINE_BREAK,
- (AtTypes.FUNCTION to AtTypes.COMMENT) to ParserDefinition.SpaceRequirements.MUST,
- )
- }
-}
Index: src/main/kotlin/platform/mcp/at/AtSyntaxHighlighter.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/AtSyntaxHighlighter.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/AtSyntaxHighlighter.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,74 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at
-
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtTypes
-import com.intellij.openapi.editor.DefaultLanguageHighlighterColors
-import com.intellij.openapi.editor.HighlighterColors
-import com.intellij.openapi.editor.colors.TextAttributesKey
-import com.intellij.openapi.fileTypes.SyntaxHighlighterBase
-import com.intellij.psi.TokenType
-import com.intellij.psi.tree.IElementType
-
-class AtSyntaxHighlighter : SyntaxHighlighterBase() {
-
- override fun getHighlightingLexer() = AtLexerAdapter()
-
- override fun getTokenHighlights(tokenType: IElementType?): Array =
- when (tokenType) {
- AtTypes.KEYWORD_ELEMENT -> KEYWORD_KEYS
- AtTypes.CLASS_NAME_ELEMENT -> CLASS_NAME_KEYS
- AtTypes.CLASS_VALUE -> CLASS_VALUE_KEYS
- AtTypes.NAME_ELEMENT -> ELEMENT_NAME_KEYS
- AtTypes.ASTERISK_ELEMENT -> ASTERISK_KEYS
- AtTypes.PRIMITIVE -> PRIMITIVE_KEYS
- AtTypes.COMMENT -> COMMENT_KEYS
- TokenType.BAD_CHARACTER -> BAD_CHARACTER_KEYS
- else -> TextAttributesKey.EMPTY_ARRAY
- }
-
- companion object {
- val KEYWORD = TextAttributesKey.createTextAttributesKey("AT_KEYWORD", DefaultLanguageHighlighterColors.KEYWORD)
- val CLASS_NAME =
- TextAttributesKey.createTextAttributesKey("AT_CLASS_NAME", DefaultLanguageHighlighterColors.STRING)
- val CLASS_VALUE =
- TextAttributesKey.createTextAttributesKey("AT_CLASS_VALUE", DefaultLanguageHighlighterColors.STATIC_METHOD)
- val ELEMENT_NAME =
- TextAttributesKey.createTextAttributesKey("AT_ELEMENT_NAME", DefaultLanguageHighlighterColors.STATIC_FIELD)
- val ASTERISK =
- TextAttributesKey.createTextAttributesKey("AT_ASTERISK", DefaultLanguageHighlighterColors.KEYWORD)
- val PRIMITIVE =
- TextAttributesKey.createTextAttributesKey("AT_PRIMITIVE", DefaultLanguageHighlighterColors.NUMBER)
- val COMMENT =
- TextAttributesKey.createTextAttributesKey("AT_COMMENT", DefaultLanguageHighlighterColors.LINE_COMMENT)
- val BAD_CHARACTER =
- TextAttributesKey.createTextAttributesKey("AT_BAD_CHARACTER", HighlighterColors.BAD_CHARACTER)
-
- private val KEYWORD_KEYS = arrayOf(KEYWORD)
- private val CLASS_NAME_KEYS = arrayOf(CLASS_NAME)
- private val CLASS_VALUE_KEYS = arrayOf(CLASS_VALUE)
- private val ELEMENT_NAME_KEYS = arrayOf(ELEMENT_NAME)
- private val ASTERISK_KEYS = arrayOf(ASTERISK)
- private val PRIMITIVE_KEYS = arrayOf(PRIMITIVE)
- private val COMMENT_KEYS = arrayOf(COMMENT)
- private val BAD_CHARACTER_KEYS = arrayOf(BAD_CHARACTER)
- }
-}
Index: src/main/kotlin/platform/mcp/at/AtSyntaxHighlighterFactory.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/AtSyntaxHighlighterFactory.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/AtSyntaxHighlighterFactory.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,29 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at
-
-import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory
-import com.intellij.openapi.project.Project
-import com.intellij.openapi.vfs.VirtualFile
-
-class AtSyntaxHighlighterFactory : SyntaxHighlighterFactory() {
- override fun getSyntaxHighlighter(project: Project?, virtualFile: VirtualFile?) = AtSyntaxHighlighter()
-}
Index: src/main/kotlin/platform/mcp/at/AtUsageInspection.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/AtUsageInspection.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/AtUsageInspection.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,80 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at
-
-import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.mcp.McpModuleType
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtEntry
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtFieldName
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtFunction
-import com.intellij.codeInspection.LocalInspectionTool
-import com.intellij.codeInspection.ProblemHighlightType
-import com.intellij.codeInspection.ProblemsHolder
-import com.intellij.openapi.module.ModuleUtilCore
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiElementVisitor
-import com.intellij.psi.search.GlobalSearchScope
-import com.intellij.psi.search.searches.ReferencesSearch
-
-class AtUsageInspection : LocalInspectionTool() {
-
- override fun getStaticDescription(): String {
- return "The declared access transformer is never used"
- }
-
- override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
- return object : PsiElementVisitor() {
- override fun visitElement(element: PsiElement) {
- if (element !is AtEntry) {
- return
- }
-
- val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return
- val instance = MinecraftFacet.getInstance(module) ?: return
- val mcpModule = instance.getModuleOfType(McpModuleType) ?: return
- val srgMap = mcpModule.mappingsManager?.mappingsNow ?: return
-
- val member = element.function ?: element.fieldName ?: return
- val reference = AtMemberReference.get(element, member) ?: return
-
- val psi = when (member) {
- is AtFunction ->
- reference.resolveMember(element.project) ?: srgMap.tryGetMappedMethod(reference)?.resolveMember(
- element.project,
- ) ?: return
- is AtFieldName ->
- reference.resolveMember(element.project)
- ?: srgMap.tryGetMappedField(reference)?.resolveMember(element.project) ?: return
- else ->
- return
- }
-
- val query = ReferencesSearch.search(psi, GlobalSearchScope.projectScope(element.project))
- query.findFirst()
- ?: holder.registerProblem(
- element,
- "Access Transformer entry is never used",
- ProblemHighlightType.LIKE_UNUSED_SYMBOL,
- )
- }
- }
- }
-}
Index: src/main/kotlin/platform/mcp/at/completion/AtCompletionContributor.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/completion/AtCompletionContributor.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/completion/AtCompletionContributor.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,356 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.completion
-
-import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.mcp.McpModuleType
-import com.demonwav.mcdev.platform.mcp.at.AtElementFactory
-import com.demonwav.mcdev.platform.mcp.at.AtLanguage
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtEntry
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtFieldName
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtFunction
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtTypes
-import com.demonwav.mcdev.util.anonymousClasses
-import com.demonwav.mcdev.util.fullQualifiedName
-import com.demonwav.mcdev.util.getSimilarity
-import com.demonwav.mcdev.util.localClasses
-import com.demonwav.mcdev.util.nameAndParameterTypes
-import com.demonwav.mcdev.util.qualifiedMemberReference
-import com.demonwav.mcdev.util.simpleQualifiedMemberReference
-import com.intellij.codeInsight.completion.CompletionContributor
-import com.intellij.codeInsight.completion.CompletionParameters
-import com.intellij.codeInsight.completion.CompletionResultSet
-import com.intellij.codeInsight.completion.CompletionType
-import com.intellij.codeInsight.completion.CompletionUtil
-import com.intellij.codeInsight.completion.PrioritizedLookupElement
-import com.intellij.codeInsight.lookup.LookupElementBuilder
-import com.intellij.openapi.module.ModuleUtilCore
-import com.intellij.patterns.PlatformPatterns.elementType
-import com.intellij.patterns.PlatformPatterns.psiElement
-import com.intellij.patterns.PsiElementPattern
-import com.intellij.psi.JavaPsiFacade
-import com.intellij.psi.PsiDocumentManager
-import com.intellij.psi.PsiElement
-import com.intellij.psi.search.GlobalSearchScope
-import com.intellij.psi.search.PsiShortNamesCache
-import com.intellij.psi.tree.IElementType
-import com.intellij.psi.tree.TokenSet
-import com.intellij.psi.util.PsiUtilCore
-import com.intellij.util.PlatformIcons
-
-class AtCompletionContributor : CompletionContributor() {
-
- override fun fillCompletionVariants(parameters: CompletionParameters, result: CompletionResultSet) {
- if (parameters.completionType != CompletionType.BASIC) {
- return
- }
-
- val position = parameters.position
- if (!PsiUtilCore.findLanguageFromElement(position).isKindOf(AtLanguage)) {
- return
- }
-
- val parent = position.parent
-
- val parentText = parent.text ?: return
- if (parentText.length < CompletionUtil.DUMMY_IDENTIFIER.length) {
- return
- }
- val text = parentText.substring(0, parentText.length - CompletionUtil.DUMMY_IDENTIFIER.length)
-
- when {
- Const.AFTER_KEYWORD.accepts(parent) -> handleAtClassName(text, parent, result)
- Const.AFTER_CLASS_NAME.accepts(parent) -> handleAtName(text, parent, result)
- Const.AFTER_NEWLINE.accepts(parent) -> handleNewLine(text, result)
- }
- }
-
- private fun handleAtClassName(text: String, element: PsiElement, result: CompletionResultSet) {
- if (text.isEmpty()) {
- return
- }
-
- val currentPackage = text.substringBeforeLast('.', "")
- val beginning = text.substringAfterLast('.', "")
-
- if (currentPackage == "" || beginning == "") {
- return
- }
-
- val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return
- val scope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module)
- val project = module.project
-
- // Short name completion
- if (!text.contains('.')) {
- val kindResult = result.withPrefixMatcher(KindPrefixMatcher(text))
- val cache = PsiShortNamesCache.getInstance(project)
-
- var counter = 0
- for (className in cache.allClassNames) {
- if (!className.contains(beginning, ignoreCase = true)) {
- continue
- }
-
- if (counter++ > 1000) {
- break // Prevent insane CPU usage
- }
-
- val classesByName = cache.getClassesByName(className, scope)
- for (classByName in classesByName) {
- val name = classByName.fullQualifiedName ?: continue
- kindResult.addElement(
- PrioritizedLookupElement.withPriority(
- LookupElementBuilder.create(name).withIcon(PlatformIcons.CLASS_ICON),
- 1.0 + name.getValue(beginning),
- ),
- )
- }
- }
- }
-
- // Anonymous and inner class completion
- if (text.contains('$')) {
- val currentClass =
- JavaPsiFacade.getInstance(project).findClass(text.substringBeforeLast('$'), scope) ?: return
-
- for (innerClass in currentClass.allInnerClasses) {
- if (innerClass.name?.contains(beginning.substringAfterLast('$'), ignoreCase = true) != true) {
- continue
- }
-
- val name = innerClass.fullQualifiedName ?: continue
- result.addElement(
- PrioritizedLookupElement.withPriority(
- LookupElementBuilder.create(name).withIcon(PlatformIcons.CLASS_ICON),
- 1.0,
- ),
- )
- }
-
- for (anonClass in currentClass.anonymousClasses) {
- val name = anonClass.fullQualifiedName ?: continue
- result.addElement(
- PrioritizedLookupElement.withPriority(
- LookupElementBuilder.create(name).withIcon(PlatformIcons.CLASS_ICON),
- 1.0,
- ),
- )
- }
-
- for (localClass in currentClass.localClasses) {
- val name = localClass.fullQualifiedName ?: continue
- result.addElement(
- PrioritizedLookupElement.withPriority(
- LookupElementBuilder.create(name).withIcon(PlatformIcons.CLASS_ICON),
- 1.0,
- ),
- )
- }
-
- return
- }
-
- val psiPackage = JavaPsiFacade.getInstance(project).findPackage(currentPackage) ?: return
-
- // Classes in package completion
- val used = mutableSetOf()
- for (psiClass in psiPackage.classes) {
- if (psiClass.name == null) {
- continue
- }
-
- if (!psiClass.name!!.contains(beginning, ignoreCase = true) || psiClass.name == "package-info") {
- continue
- }
-
- if (!used.add(psiClass.name!!)) {
- continue
- }
-
- val name = psiClass.fullQualifiedName ?: continue
- result.addElement(
- PrioritizedLookupElement.withPriority(
- LookupElementBuilder.create(name).withIcon(PlatformIcons.CLASS_ICON),
- 1.0,
- ),
- )
- }
- used.clear() // help GC
-
- // Packages in package completion
- for (subPackage in psiPackage.subPackages) {
- if (subPackage.name == null) {
- continue
- }
-
- if (!subPackage.name!!.contains(beginning, ignoreCase = true)) {
- continue
- }
-
- val name = subPackage.qualifiedName
- result.addElement(
- PrioritizedLookupElement.withPriority(
- LookupElementBuilder.create(name).withIcon(PlatformIcons.PACKAGE_ICON),
- 0.0,
- ),
- )
- }
- }
-
- private fun handleAtName(text: String, memberName: PsiElement, result: CompletionResultSet) {
- if (memberName !is AtFieldName) {
- return
- }
-
- val entry = memberName.parent as? AtEntry ?: return
-
- val entryClass = entry.className?.classNameValue ?: return
-
- val module = ModuleUtilCore.findModuleForPsiElement(memberName) ?: return
- val project = module.project
-
- val mcpModule = MinecraftFacet.getInstance(module)?.getModuleOfType(McpModuleType) ?: return
-
- val srgMap = mcpModule.mappingsManager?.mappingsNow ?: return
-
- val srgResult = result.withPrefixMatcher(SrgPrefixMatcher(text))
-
- for (field in entryClass.fields) {
- if (!field.name.contains(text, ignoreCase = true)) {
- continue
- }
-
- val memberReference = srgMap.getIntermediaryField(field) ?: field.simpleQualifiedMemberReference
- srgResult.addElement(
- PrioritizedLookupElement.withPriority(
- LookupElementBuilder
- .create(field.name)
- .withIcon(PlatformIcons.FIELD_ICON)
- .withTailText(" (${memberReference.name})", true)
- .withInsertHandler handler@{ context, _ ->
- val currentElement = context.file.findElementAt(context.startOffset) ?: return@handler
- currentElement.replace(
- AtElementFactory.createFieldName(
- context.project,
- memberReference.name,
- ),
- )
-
- // TODO: Fix visibility decrease
- PsiDocumentManager.getInstance(context.project)
- .doPostponedOperationsAndUnblockDocument(context.document)
- val comment = " # ${field.name}"
- context.document.insertString(context.editor.caretModel.offset, comment)
- context.editor.caretModel.moveCaretRelatively(comment.length, 0, false, false, false)
- },
- 1.0,
- ),
- )
- }
-
- for (method in entryClass.methods) {
- if (!method.name.contains(text, ignoreCase = true)) {
- continue
- }
-
- val memberReference = srgMap.getIntermediaryMethod(method) ?: method.qualifiedMemberReference
- srgResult.addElement(
- PrioritizedLookupElement.withPriority(
- LookupElementBuilder.create(method.nameAndParameterTypes)
- .withIcon(PlatformIcons.METHOD_ICON)
- .withTailText(" (${memberReference.name})", true)
- .withInsertHandler handler@{ context, _ ->
- var currentElement = context.file.findElementAt(context.startOffset) ?: return@handler
- var counter = 0
- while (currentElement !is AtFieldName && currentElement !is AtFunction) {
- currentElement = currentElement.parent
- if (counter++ > 3) {
- break
- }
- }
-
- // Hopefully this won't happen lol
- if (currentElement !is AtFieldName && currentElement !is AtFunction) {
- return@handler
- }
-
- if (currentElement is AtFieldName) {
- // get rid of the bad parameters
- val parent = currentElement.parent
- val children =
- parent.node.getChildren(TokenSet.create(AtTypes.OPEN_PAREN, AtTypes.CLOSE_PAREN))
- if (children.size == 2) {
- parent.node.removeRange(children[0], children[1].treeNext)
- }
- }
-
- currentElement.replace(
- AtElementFactory.createFunction(
- project,
- memberReference.name + memberReference.descriptor,
- ),
- )
-
- // TODO: Fix visibility decreases
- PsiDocumentManager.getInstance(context.project)
- .doPostponedOperationsAndUnblockDocument(context.document)
- val comment = " # ${method.name}"
- context.document.insertString(context.editor.caretModel.offset, comment)
- context.editor.caretModel.moveCaretRelatively(comment.length, 0, false, false, false)
- },
- 0.0,
- ),
- )
- }
- }
-
- private fun handleNewLine(text: String, result: CompletionResultSet) {
- for (keyword in AtElementFactory.Keyword.softMatch(text)) {
- result.addElement(LookupElementBuilder.create(keyword.text))
- }
- }
-
- /**
- * This helps order the (hopefully) most relevant entries in the short name completion
- */
- private fun String?.getValue(text: String): Int {
- if (this == null) {
- return 0
- }
-
- // Push net.minecraft{forge} classes up to the top
- val packageBonus = if (this.startsWith("net.minecraft")) 10_000 else 0
-
- val thisName = this.substringAfterLast('.')
-
- return thisName.getSimilarity(text, packageBonus)
- }
-
- object Const {
- private fun after(type: IElementType): PsiElementPattern.Capture =
- psiElement().afterSibling(psiElement().withElementType(elementType().oneOf(type)))
-
- val AFTER_KEYWORD = after(AtTypes.KEYWORD)
- val AFTER_CLASS_NAME = after(AtTypes.CLASS_NAME)
- val AFTER_NEWLINE = after(AtTypes.CRLF)
- }
-}
Index: src/main/kotlin/platform/mcp/at/completion/AtTypedHandlerDelegate.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/completion/AtTypedHandlerDelegate.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/completion/AtTypedHandlerDelegate.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,36 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.completion
-
-import com.demonwav.mcdev.platform.mcp.at.AtLanguage
-import com.intellij.codeInsight.editorActions.TypedHandlerDelegate
-import com.intellij.openapi.editor.Editor
-import com.intellij.openapi.project.Project
-import com.intellij.psi.PsiFile
-
-class AtTypedHandlerDelegate : TypedHandlerDelegate() {
- override fun checkAutoPopup(charTyped: Char, project: Project, editor: Editor, file: PsiFile): Result {
- if (file.language == AtLanguage && charTyped == '$') {
- return Result.CONTINUE
- }
- return super.checkAutoPopup(charTyped, project, editor, file)
- }
-}
Index: src/main/kotlin/platform/mcp/at/completion/KindPrefixMatcher.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/completion/KindPrefixMatcher.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/completion/KindPrefixMatcher.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,32 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.completion
-
-import com.intellij.codeInsight.completion.PrefixMatcher
-import com.intellij.codeInsight.lookup.LookupElement
-
-class KindPrefixMatcher(prefix: String) : PrefixMatcher(prefix) {
- override fun prefixMatches(name: String) = true
- override fun cloneWithPrefix(prefix: String) = KindPrefixMatcher(prefix)
-
- override fun prefixMatches(element: LookupElement) =
- element.lookupString.contains(prefix, ignoreCase = true)
-}
Index: src/main/kotlin/platform/mcp/at/completion/SrgPrefixMatcher.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/completion/SrgPrefixMatcher.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/completion/SrgPrefixMatcher.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,33 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.completion
-
-import com.intellij.codeInsight.completion.PrefixMatcher
-import com.intellij.codeInsight.lookup.LookupElement
-
-class SrgPrefixMatcher(prefix: String) : PrefixMatcher(prefix) {
- override fun prefixMatches(name: String) = true
- override fun cloneWithPrefix(prefix: String) = SrgPrefixMatcher(prefix)
-
- override fun prefixMatches(element: LookupElement): Boolean {
- return element.lookupString.contains(myPrefix, ignoreCase = true)
- }
-}
Index: src/main/kotlin/platform/mcp/at/psi/AtElement.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/AtElement.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/AtElement.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,25 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi
-
-import com.intellij.psi.PsiElement
-
-interface AtElement : PsiElement
Index: src/main/kotlin/platform/mcp/at/psi/AtElementType.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/AtElementType.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/AtElementType.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,27 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi
-
-import com.demonwav.mcdev.platform.mcp.at.AtLanguage
-import com.intellij.psi.tree.IElementType
-import org.jetbrains.annotations.NonNls
-
-class AtElementType(@NonNls debugName: String) : IElementType(debugName, AtLanguage)
Index: src/main/kotlin/platform/mcp/at/psi/AtMixinUtil.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/AtMixinUtil.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/AtMixinUtil.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,50 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi
-
-import com.demonwav.mcdev.util.findQualifiedClass
-import com.demonwav.mcdev.util.getPrimitiveWrapperClass
-import com.demonwav.mcdev.util.parseClassDescriptor
-import com.intellij.openapi.project.Project
-import com.intellij.psi.PsiClass
-import com.intellij.psi.search.GlobalSearchScope
-
-private val bracket = Regex("\\[")
-
-fun getClassFromString(text: String?, project: Project): PsiClass? {
- var newText = text ?: return null
-
- // We don't care about arrays
- newText = newText.replace(bracket, "")
-
- val scope = GlobalSearchScope.allScope(project)
-
- if (newText.startsWith("L")) {
- val finalText = parseClassDescriptor(newText)
- return findQualifiedClass(project, finalText, scope)
- }
-
- if (newText.length != 1 || !"BCDFIJSZ".contains(newText[0])) {
- return null
- }
-
- return getPrimitiveWrapperClass(newText[0], project)
-}
Index: src/main/kotlin/platform/mcp/at/psi/AtTokenType.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/AtTokenType.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/AtTokenType.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,27 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi
-
-import com.demonwav.mcdev.platform.mcp.at.AtLanguage
-import com.intellij.psi.tree.IElementType
-import org.jetbrains.annotations.NonNls
-
-class AtTokenType(@NonNls debugName: String) : IElementType(debugName, AtLanguage)
Index: src/main/kotlin/platform/mcp/at/psi/mixins/AtArgumentMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/mixins/AtArgumentMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/mixins/AtArgumentMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,35 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi.mixins
-
-import com.demonwav.mcdev.platform.mcp.at.psi.AtElement
-import com.intellij.psi.PsiClass
-import com.intellij.psi.PsiElement
-
-interface AtArgumentMixin : AtElement {
-
- val classValue: PsiElement?
- val primitive: PsiElement?
- val argumentClass: PsiClass?
- val argumentText: String
-
- fun setArgument(argument: String)
-}
Index: src/main/kotlin/platform/mcp/at/psi/mixins/AtClassNameMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/mixins/AtClassNameMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/mixins/AtClassNameMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,34 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi.mixins
-
-import com.demonwav.mcdev.platform.mcp.at.psi.AtElement
-import com.intellij.psi.PsiClass
-import com.intellij.psi.PsiElement
-
-interface AtClassNameMixin : AtElement {
-
- val classNameElement: PsiElement
- val classNameValue: PsiClass?
- val classNameText: String
-
- fun setClassName(className: String)
-}
Index: src/main/kotlin/platform/mcp/at/psi/mixins/AtEntryMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/mixins/AtEntryMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/mixins/AtEntryMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,55 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi.mixins
-
-import com.demonwav.mcdev.platform.mcp.at.AtElementFactory
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtAsterisk
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtClassName
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtFieldName
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtFunction
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtKeyword
-import com.demonwav.mcdev.platform.mcp.at.psi.AtElement
-
-interface AtEntryMixin : AtElement {
-
- val asterisk: AtAsterisk?
- val className: AtClassName
- val fieldName: AtFieldName?
- val function: AtFunction?
- val keyword: AtKeyword
-
- fun setEntry(entry: String)
- fun setKeyword(keyword: AtElementFactory.Keyword)
- fun setClassName(className: String)
- fun setFieldName(fieldName: String)
- fun setFunction(function: String)
- fun setAsterisk()
-
- fun replaceMember(element: AtElement) {
- // One of these must be true
- when {
- fieldName != null -> fieldName!!.replace(element)
- function != null -> function!!.replace(element)
- asterisk != null -> asterisk!!.replace(element)
- else -> addAfter(className, element)
- }
- }
-}
Index: src/main/kotlin/platform/mcp/at/psi/mixins/AtFieldNameMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/mixins/AtFieldNameMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/mixins/AtFieldNameMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,32 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi.mixins
-
-import com.demonwav.mcdev.platform.mcp.at.psi.AtElement
-import com.intellij.psi.PsiElement
-
-interface AtFieldNameMixin : AtElement {
-
- val nameElement: PsiElement
- val fieldNameText: String
-
- fun setFieldName(fieldName: String)
-}
Index: src/main/kotlin/platform/mcp/at/psi/mixins/AtFuncNameMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/mixins/AtFuncNameMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/mixins/AtFuncNameMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,32 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi.mixins
-
-import com.demonwav.mcdev.platform.mcp.at.psi.AtElement
-import com.intellij.psi.PsiElement
-
-interface AtFuncNameMixin : AtElement {
-
- val nameElement: PsiElement
- val funcNameText: String
-
- fun setFuncName(funcName: String)
-}
Index: src/main/kotlin/platform/mcp/at/psi/mixins/AtFunctionMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/mixins/AtFunctionMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/mixins/AtFunctionMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,37 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi.mixins
-
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtArgument
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtFuncName
-import com.demonwav.mcdev.platform.mcp.at.gen.psi.AtReturnValue
-import com.demonwav.mcdev.platform.mcp.at.psi.AtElement
-
-interface AtFunctionMixin : AtElement {
-
- val argumentList: List
- val funcName: AtFuncName
- val returnValue: AtReturnValue
-
- fun setArgumentList(argumentList: String)
- fun setReturnValue(returnValue: String)
- fun setFunction(function: String)
-}
Index: src/main/kotlin/platform/mcp/at/psi/mixins/AtKeywordMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/mixins/AtKeywordMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/mixins/AtKeywordMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,33 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi.mixins
-
-import com.demonwav.mcdev.platform.mcp.at.AtElementFactory
-import com.demonwav.mcdev.platform.mcp.at.psi.AtElement
-import com.intellij.psi.PsiElement
-
-interface AtKeywordMixin : AtElement {
-
- val keywordElement: PsiElement
- val keywordValue: AtElementFactory.Keyword
-
- fun setKeyword(keyword: AtElementFactory.Keyword)
-}
Index: src/main/kotlin/platform/mcp/at/psi/mixins/AtReturnValueMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/mixins/AtReturnValueMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/mixins/AtReturnValueMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,35 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi.mixins
-
-import com.demonwav.mcdev.platform.mcp.at.psi.AtElement
-import com.intellij.psi.PsiClass
-import com.intellij.psi.PsiElement
-
-interface AtReturnValueMixin : AtElement {
-
- val classValue: PsiElement?
- val primitive: PsiElement?
- val returnValueClass: PsiClass?
- val returnValueText: String
-
- fun setReturnValue(returnValue: String)
-}
Index: src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtArgumentImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtArgumentImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtArgumentImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,40 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.at.AtElementFactory
-import com.demonwav.mcdev.platform.mcp.at.psi.getClassFromString
-import com.demonwav.mcdev.platform.mcp.at.psi.mixins.AtArgumentMixin
-import com.intellij.extapi.psi.ASTWrapperPsiElement
-import com.intellij.lang.ASTNode
-
-abstract class AtArgumentImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), AtArgumentMixin {
-
- override val argumentClass
- get() = getClassFromString(argumentText, project)
-
- override val argumentText: String
- get() = classValue?.text ?: primitive!!.text
-
- override fun setArgument(argument: String) {
- replace(AtElementFactory.createArgument(project, argument))
- }
-}
Index: src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtClassNameImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtClassNameImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtClassNameImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,40 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.at.AtElementFactory
-import com.demonwav.mcdev.platform.mcp.at.psi.mixins.AtClassNameMixin
-import com.demonwav.mcdev.util.findQualifiedClass
-import com.intellij.extapi.psi.ASTWrapperPsiElement
-import com.intellij.lang.ASTNode
-
-abstract class AtClassNameImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), AtClassNameMixin {
-
- override val classNameValue
- get() = findQualifiedClass(project, classNameText)
-
- override val classNameText: String
- get() = classNameElement.text
-
- override fun setClassName(className: String) {
- replace(AtElementFactory.createClassName(project, className))
- }
-}
Index: src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtEntryImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtEntryImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtEntryImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,56 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.at.AtElementFactory
-import com.demonwav.mcdev.platform.mcp.at.psi.mixins.AtEntryMixin
-import com.intellij.extapi.psi.ASTWrapperPsiElement
-import com.intellij.lang.ASTNode
-
-abstract class AtEntryImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), AtEntryMixin {
-
- override fun setEntry(entry: String) {
- replace(AtElementFactory.createEntry(project, entry))
- }
-
- override fun setKeyword(keyword: AtElementFactory.Keyword) {
- this.keyword.replace(AtElementFactory.createKeyword(project, keyword))
- }
-
- override fun setClassName(className: String) {
- this.className.replace(AtElementFactory.createClassName(project, className))
- }
-
- override fun setFieldName(fieldName: String) {
- val newField = AtElementFactory.createFieldName(project, fieldName)
- replaceMember(newField)
- }
-
- override fun setFunction(function: String) {
- val atFunction = AtElementFactory.createFunction(project, function)
- replaceMember(atFunction)
- }
-
- override fun setAsterisk() {
- val asterisk = AtElementFactory.createAsterisk(project)
- replaceMember(asterisk)
- }
-}
Index: src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtFieldNameImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtFieldNameImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtFieldNameImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,36 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.at.AtElementFactory
-import com.demonwav.mcdev.platform.mcp.at.psi.mixins.AtFieldNameMixin
-import com.intellij.extapi.psi.ASTWrapperPsiElement
-import com.intellij.lang.ASTNode
-
-abstract class AtFieldNameImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), AtFieldNameMixin {
-
- override fun setFieldName(fieldName: String) {
- replace(AtElementFactory.createFieldName(project, fieldName))
- }
-
- override val fieldNameText: String
- get() = nameElement.text
-}
Index: src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtFuncNameImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtFuncNameImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtFuncNameImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,36 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.at.AtElementFactory
-import com.demonwav.mcdev.platform.mcp.at.psi.mixins.AtFuncNameMixin
-import com.intellij.extapi.psi.ASTWrapperPsiElement
-import com.intellij.lang.ASTNode
-
-abstract class AtFuncNameImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), AtFuncNameMixin {
-
- override fun setFuncName(funcName: String) {
- replace(AtElementFactory.createFuncName(project, funcName))
- }
-
- override val funcNameText: String
- get() = nameElement.text
-}
Index: src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtFunctionImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtFunctionImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtFunctionImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,45 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.at.AtElementFactory
-import com.demonwav.mcdev.platform.mcp.at.psi.mixins.AtFunctionMixin
-import com.intellij.extapi.psi.ASTWrapperPsiElement
-import com.intellij.lang.ASTNode
-
-abstract class AtFunctionImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), AtFunctionMixin {
-
- override fun setArgumentList(argumentList: String) {
- val funcName = funcName.nameElement.text
- this.argumentList.forEach { it.delete() }
-
- val returnValue = returnValue.classValue!!.text
- replace(AtElementFactory.createFunction(project, "$funcName($argumentList)$returnValue"))
- }
-
- override fun setReturnValue(returnValue: String) {
- this.returnValue.replace(AtElementFactory.createReturnValue(project, returnValue))
- }
-
- override fun setFunction(function: String) {
- replace(AtElementFactory.createFunction(project, function))
- }
-}
Index: src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtKeywordImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtKeywordImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtKeywordImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,36 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.at.AtElementFactory
-import com.demonwav.mcdev.platform.mcp.at.psi.mixins.AtKeywordMixin
-import com.intellij.extapi.psi.ASTWrapperPsiElement
-import com.intellij.lang.ASTNode
-
-abstract class AtKeywordImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), AtKeywordMixin {
-
- override val keywordValue
- get() = AtElementFactory.Keyword.match(keywordElement.text)!!
-
- override fun setKeyword(keyword: AtElementFactory.Keyword) {
- replace(AtElementFactory.createKeyword(project, keyword))
- }
-}
Index: src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtReturnValueImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtReturnValueImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/at/psi/mixins/impl/AtReturnValueImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,41 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.at.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.at.AtElementFactory
-import com.demonwav.mcdev.platform.mcp.at.psi.getClassFromString
-import com.demonwav.mcdev.platform.mcp.at.psi.mixins.AtReturnValueMixin
-import com.intellij.extapi.psi.ASTWrapperPsiElement
-import com.intellij.lang.ASTNode
-import com.intellij.psi.PsiClass
-
-abstract class AtReturnValueImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), AtReturnValueMixin {
-
- override val returnValueClass: PsiClass?
- get() = getClassFromString(returnValueText, project)
-
- override val returnValueText: String
- get() = primitive?.text ?: classValue!!.text
-
- override fun setReturnValue(returnValue: String) {
- replace(AtElementFactory.createReturnValue(project, returnValue))
- }
-}
Index: src/main/kotlin/platform/mcp/ct/CtAnnotator.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/CtAnnotator.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/CtAnnotator.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,112 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct
-
-import com.demonwav.mcdev.platform.fabric.util.FabricConstants
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtAccess
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtClassLiteral
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtExtendEnumEntry
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtFieldLiteral
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtHeader
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtItfEntry
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtMethodLiteral
-import com.demonwav.mcdev.util.childOfType
-import com.google.common.collect.HashMultimap
-import com.google.common.collect.Multimaps
-import com.intellij.lang.annotation.AnnotationHolder
-import com.intellij.lang.annotation.Annotator
-import com.intellij.lang.annotation.HighlightSeverity
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiWhiteSpace
-import com.intellij.psi.util.PsiTreeUtil
-
-class CtAnnotator : Annotator {
-
- override fun annotate(element: PsiElement, holder: AnnotationHolder) {
- val effectiveVersion by lazy { element.containingFile?.childOfType()?.effectiveVersion ?: 1 }
-
- when (element) {
- is CtAccess -> {
- val access = element.text
- val target = PsiTreeUtil.skipSiblingsForward(element, PsiWhiteSpace::class.java)?.text
- if (!TokenSets.compatibleByAccessMap.get(access).contains(target)) {
- holder.newAnnotation(HighlightSeverity.ERROR, "Access '$access' cannot be used on '$target'").create()
- }
-
- if (element.accessElement.text.startsWith("transitive-") && effectiveVersion < 2) {
- holder.newAnnotation(HighlightSeverity.ERROR, "Transitive accesses were introduced in v2").create()
- }
- }
- is CtItfEntry -> {
- if (effectiveVersion < 3) {
- holder.newAnnotation(HighlightSeverity.ERROR, "Interface injection was introduced in ClassTweaker v1")
- .range(element.firstChild)
- .create()
- }
- }
- is CtExtendEnumEntry -> {
- if (effectiveVersion < 4) {
- holder.newAnnotation(HighlightSeverity.ERROR, "Enum extension was introduced in ClassTweaker v2")
- .range(element.firstChild)
- .create()
- }
- }
- is CtFieldLiteral, is CtMethodLiteral, is CtClassLiteral -> {
- val target = element.text
- val access = PsiTreeUtil.skipSiblingsBackward(element, PsiWhiteSpace::class.java)?.text
- if (!TokenSets.compatibleByTargetMap.get(target).contains(access)) {
- holder.newAnnotation(HighlightSeverity.ERROR, "'$target' cannot be used with '$access'").create()
- }
- }
- is CtHeader -> {
- val version = element.effectiveVersion
- val versionElement = element.versionElement ?: return
- when (element.nameString) {
- "accessWidener" -> {
- if (version == null || version < 1 || version > 2) {
- holder.newAnnotation(HighlightSeverity.ERROR, "Unrecognized access widener version").range(versionElement).create()
- }
- }
- "classTweaker" -> {
- if (version == null || version < 3 || version > FabricConstants.CLASS_TWEAKER_VERSION) {
- holder.newAnnotation(HighlightSeverity.ERROR, "Unrecognized class tweaker version").range(versionElement).create()
- }
- }
- }
- }
- }
- }
-
- object TokenSets {
- val compatibleByAccessMap = HashMultimap.create()
- val compatibleByTargetMap = HashMultimap.create()
-
- init {
- compatibleByAccessMap.putAll("accessible", setOf("class", "method", "field"))
- compatibleByAccessMap.putAll("transitive-accessible", setOf("class", "method", "field"))
- compatibleByAccessMap.putAll("extendable", setOf("class", "method"))
- compatibleByAccessMap.putAll("transitive-extendable", setOf("class", "method"))
- compatibleByAccessMap.putAll("mutable", setOf("field"))
- compatibleByAccessMap.putAll("transitive-mutable", setOf("field"))
- Multimaps.invertFrom(compatibleByAccessMap, compatibleByTargetMap)
- }
- }
-}
Index: src/main/kotlin/platform/mcp/ct/CtColorSettingsPage.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/CtColorSettingsPage.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/CtColorSettingsPage.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,75 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct
-
-import com.demonwav.mcdev.asset.PlatformAssets
-import com.intellij.openapi.editor.colors.TextAttributesKey
-import com.intellij.openapi.options.colors.AttributesDescriptor
-import com.intellij.openapi.options.colors.ColorDescriptor
-import com.intellij.openapi.options.colors.ColorSettingsPage
-
-class CtColorSettingsPage : ColorSettingsPage {
-
- override fun getIcon() = PlatformAssets.MCP_ICON
- override fun getHighlighter() = CtSyntaxHighlighter()
- override fun getDemoText() =
- $$"""
- classTweaker v2 named
-
- # https://docs.fabricmc.net/develop/class-tweakers/
-
- extendable class net/minecraft/world/item/crafting/Ingredient
- transitive-extendable class net/minecraft/world/item/crafting/Ingredient
- accessible class net/minecraft/world/entity/monster/Phantom$AttackPhase
- transitive-accessible class net/minecraft/world/entity/monster/Phantom$AttackPhase
- extendable method net/minecraft/server/players/IpBanList getIpFromAddress (Ljava/net/SocketAddress;)Ljava/lang/String;
- extendable method net/minecraft/world/item/crafting/Ingredient (Ljava/util/stream/Stream;)V
- accessible field net/minecraft/world/item/crafting/Ingredient values [Lnet/minecraft/world/item/crafting/Ingredient$Value;
- inject-interface net/minecraft/world/level/block/Block com/example/MyBlockInterface
- transitive-inject-interface net/minecraft/world/level/block/Block com/example/MyTransitiveBlockInterface
- extend-enum net/minecraft/client/gui/Gui$HeartType MYMOD_HEART_TYPE
- transitive-extend-enum net/minecraft/client/gui/Gui$HeartType MYMOD_TRANSITIVE_HEART_TYPE
- """.trimIndent()
-
- override fun getAdditionalHighlightingTagToDescriptorMap(): Map? = null
- override fun getAttributeDescriptors() = Const.DESCRIPTORS
- override fun getColorDescriptors(): Array = ColorDescriptor.EMPTY_ARRAY
- override fun getDisplayName() = "Class Tweakers"
-
- private object Const {
- val DESCRIPTORS = arrayOf(
- AttributesDescriptor("Header name", CtSyntaxHighlighter.HEADER_NAME),
- AttributesDescriptor("Header namespace", CtSyntaxHighlighter.HEADER_NAMESPACE),
- AttributesDescriptor("Access", CtSyntaxHighlighter.ACCESS),
- AttributesDescriptor("Inject interface", CtSyntaxHighlighter.INJECT_INTERFACE),
- AttributesDescriptor("Extend enum", CtSyntaxHighlighter.EXTEND_ENUM),
- AttributesDescriptor("Class element", CtSyntaxHighlighter.CLASS_ELEMENT),
- AttributesDescriptor("Method element", CtSyntaxHighlighter.METHOD_ELEMENT),
- AttributesDescriptor("Field element", CtSyntaxHighlighter.FIELD_ELEMENT),
- AttributesDescriptor("Class name", CtSyntaxHighlighter.CLASS_NAME),
- AttributesDescriptor("Member name", CtSyntaxHighlighter.MEMBER_NAME),
- AttributesDescriptor("Class value", CtSyntaxHighlighter.CLASS_VALUE),
- AttributesDescriptor("Primitive", CtSyntaxHighlighter.PRIMITIVE),
- AttributesDescriptor("Type variable", CtSyntaxHighlighter.TYPE_VARIABLE),
- AttributesDescriptor("Comment", CtSyntaxHighlighter.COMMENT),
- )
- }
-}
Index: src/main/kotlin/platform/mcp/ct/CtCommenter.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/CtCommenter.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/CtCommenter.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,36 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct
-
-import com.intellij.lang.Commenter
-
-class CtCommenter : Commenter {
-
- override fun getLineCommentPrefix() = "#"
-
- override fun getBlockCommentPrefix(): String? = null
-
- override fun getBlockCommentSuffix(): String? = null
-
- override fun getCommentedBlockCommentPrefix(): String? = null
-
- override fun getCommentedBlockCommentSuffix(): String? = null
-}
Index: src/main/kotlin/platform/mcp/ct/CtCompletionContributor.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/CtCompletionContributor.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/CtCompletionContributor.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,149 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct
-
-import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.fabric.FabricModuleType
-import com.demonwav.mcdev.platform.fabric.util.FabricConstants
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtTypes
-import com.demonwav.mcdev.util.findModule
-import com.intellij.codeInsight.completion.CodeCompletionHandlerBase
-import com.intellij.codeInsight.completion.CompletionContributor
-import com.intellij.codeInsight.completion.CompletionParameters
-import com.intellij.codeInsight.completion.CompletionProvider
-import com.intellij.codeInsight.completion.CompletionResultSet
-import com.intellij.codeInsight.completion.CompletionType
-import com.intellij.codeInsight.completion.InsertionContext
-import com.intellij.codeInsight.completion.PrioritizedLookupElement
-import com.intellij.codeInsight.lookup.LookupElementBuilder
-import com.intellij.openapi.application.runReadAction
-import com.intellij.patterns.PlatformPatterns
-import com.intellij.psi.PsiDocumentManager
-import com.intellij.psi.TokenType
-import com.intellij.psi.util.elementType
-import com.intellij.psi.util.prevLeaf
-import com.intellij.util.ProcessingContext
-
-class CtCompletionContributor : CompletionContributor() {
- init {
- extend(null, PlatformPatterns.psiElement(), CtHeaderCompletionProvider)
- val whitespace = PlatformPatterns.psiElement(TokenType.WHITE_SPACE)
- val namespacePattern = PlatformPatterns.psiElement()
- .afterLeafSkipping(whitespace, PlatformPatterns.psiElement(CtTypes.HEADER_VERSION_ELEMENT))
- extend(null, namespacePattern, CtNamespaceCompletionProvider)
- val entryStartPattern = PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement(CtTypes.CRLF))
- extend(null, entryStartPattern, CtEntryStartCompletionProvider)
- val awTargetPattern = PlatformPatterns.psiElement()
- .afterLeafSkipping(whitespace, PlatformPatterns.psiElement(CtTypes.ACCESS_ELEMENT))
- extend(null, awTargetPattern, CtAwTargetCompletionProvider)
- }
-}
-
-private fun insertWhitespace(context: InsertionContext) {
- PsiDocumentManager.getInstance(context.project)
- .doPostponedOperationsAndUnblockDocument(context.document)
- context.document.insertString(context.editor.caretModel.offset, " ")
- context.editor.caretModel.moveCaretRelatively(1, 0, false, false, false)
- context.setLaterRunnable {
- runReadAction {
- CodeCompletionHandlerBase.createHandler(CompletionType.BASIC)
- .invokeCompletion(context.project, context.editor)
- }
- }
-}
-
-private val ADDITIONAL_NAMESPACE_PRIORITY = mapOf(
- "named" to 0.2,
- "official" to 0.1,
-)
-
-object CtHeaderCompletionProvider : CompletionProvider() {
-
- override fun addCompletions(
- parameters: CompletionParameters,
- context: ProcessingContext,
- result: CompletionResultSet,
- ) {
- if (parameters.position.prevLeaf(true) == null) {
- val module = parameters.originalFile.findModule() ?: return
- val fabricModule = MinecraftFacet.getInstance(module, FabricModuleType) ?: return
- for (mappingNamespace in fabricModule.mappingNamespaces) {
- val additionalPriority = ADDITIONAL_NAMESPACE_PRIORITY[mappingNamespace] ?: 0.0
- result.addElement(PrioritizedLookupElement.withPriority(LookupElementBuilder.create("accessWidener v1 $mappingNamespace"), 1.0 + additionalPriority))
- result.addElement(PrioritizedLookupElement.withPriority(LookupElementBuilder.create("accessWidener v2 $mappingNamespace"), 2.0 + additionalPriority))
- for (ctVersion in 1..FabricConstants.CLASS_TWEAKER_VERSION - 2) {
- result.addElement(PrioritizedLookupElement.withPriority(LookupElementBuilder.create("classTweaker v$ctVersion $mappingNamespace"), 2.0 + ctVersion + additionalPriority))
- }
- }
- }
- }
-}
-
-object CtNamespaceCompletionProvider : CompletionProvider() {
-
- override fun addCompletions(
- parameters: CompletionParameters,
- context: ProcessingContext,
- result: CompletionResultSet,
- ) {
- val module = parameters.originalFile.findModule() ?: return
- val fabricModule = MinecraftFacet.getInstance(module, FabricModuleType) ?: return
- result.addAllElements(fabricModule.mappingNamespaces.map(LookupElementBuilder::create))
- }
-}
-
-object CtEntryStartCompletionProvider : CompletionProvider() {
-
- override fun addCompletions(
- parameters: CompletionParameters,
- context: ProcessingContext,
- result: CompletionResultSet,
- ) {
- val elements = listOf(
- "accessible",
- "transitive-accessible",
- "extendable",
- "transitive-extendable",
- "mutable",
- "transitive-mutable",
- "inject-interface",
- "transitive-inject-interface",
- "extend-enum",
- "transitive-extend-enum",
- ).map { LookupElementBuilder.create(it).withInsertHandler { ctx, _ -> insertWhitespace(ctx) } }
- result.addAllElements(elements)
- }
-}
-
-object CtAwTargetCompletionProvider : CompletionProvider() {
-
- override fun addCompletions(
- parameters: CompletionParameters,
- context: ProcessingContext,
- result: CompletionResultSet,
- ) {
- val text = parameters.position
- .prevLeaf { it.elementType == CtTypes.ACCESS_ELEMENT || it.elementType == CtTypes.CRLF }?.text ?: return
- val elements = CtAnnotator.TokenSets.compatibleByAccessMap.get(text)
- .map { LookupElementBuilder.create(it).withInsertHandler { ctx, _ -> insertWhitespace(ctx) } }
- result.addAllElements(elements)
- }
-}
Index: src/main/kotlin/platform/mcp/ct/CtFile.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/CtFile.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/CtFile.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,41 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct
-
-import com.demonwav.mcdev.asset.PlatformAssets
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtHeader
-import com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtEntryMixin
-import com.demonwav.mcdev.util.childrenOfType
-import com.intellij.extapi.psi.PsiFileBase
-import com.intellij.psi.FileViewProvider
-
-class CtFile(viewProvider: FileViewProvider) : PsiFileBase(viewProvider, CtLanguage) {
-
- val header: CtHeader?
- get() = children.first { it is CtHeader } as? CtHeader
-
- val entries: Collection
- get() = childrenOfType()
-
- override fun getFileType() = CtFileType
- override fun toString() = "Class Tweaker File"
- override fun getIcon(flags: Int) = PlatformAssets.MCP_ICON
-}
Index: src/main/kotlin/platform/mcp/ct/CtFileType.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/CtFileType.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/CtFileType.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,35 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct
-
-import com.demonwav.mcdev.asset.PlatformAssets
-import com.intellij.openapi.fileTypes.LanguageFileType
-
-object CtFileType : LanguageFileType(CtLanguage) {
-
- override fun getName() = "Class Tweaker"
-
- override fun getDescription() = "Class tweaker"
-
- override fun getDefaultExtension() = "classtweaker"
-
- override fun getIcon() = PlatformAssets.MCP_ICON
-}
Index: src/main/kotlin/platform/mcp/ct/CtLanguage.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/CtLanguage.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/CtLanguage.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,29 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct
-
-import com.intellij.lang.Language
-import java.io.Serial
-
-object CtLanguage : Language("Class Tweaker") {
- @Serial
- private fun readResolve(): Any = CtLanguage
-}
Index: src/main/kotlin/platform/mcp/ct/CtLexerAdapter.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/CtLexerAdapter.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/CtLexerAdapter.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,26 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct
-
-import com.demonwav.mcdev.platform.mcp.ct.gen.CtLexer
-import com.intellij.lexer.FlexAdapter
-
-class CtLexerAdapter : FlexAdapter(CtLexer())
Index: src/main/kotlin/platform/mcp/ct/CtParserDefinition.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/CtParserDefinition.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/CtParserDefinition.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,60 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct
-
-import com.demonwav.mcdev.platform.mcp.ct.gen.parser.CtParser
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtTypes
-import com.intellij.lang.ASTNode
-import com.intellij.lang.Language
-import com.intellij.lang.LanguageUtil
-import com.intellij.lang.ParserDefinition
-import com.intellij.lang.PsiParser
-import com.intellij.lexer.Lexer
-import com.intellij.openapi.project.Project
-import com.intellij.psi.FileViewProvider
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiFile
-import com.intellij.psi.TokenType
-import com.intellij.psi.tree.IFileElementType
-import com.intellij.psi.tree.TokenSet
-
-class CtParserDefinition : ParserDefinition {
-
- override fun createLexer(project: Project): Lexer = CtLexerAdapter()
- override fun createParser(project: Project): PsiParser = CtParser()
- override fun getFileNodeType(): IFileElementType = TokenSets.FILE
- override fun getWhitespaceTokens(): TokenSet = TokenSets.WHITE_SPACES
- override fun getCommentTokens(): TokenSet = TokenSets.COMMENTS
- override fun getStringLiteralElements(): TokenSet = TokenSet.EMPTY
- override fun createElement(node: ASTNode): PsiElement = CtTypes.Factory.createElement(node)
- override fun createFile(viewProvider: FileViewProvider): PsiFile = CtFile(viewProvider)
-
- override fun spaceExistenceTypeBetweenTokens(left: ASTNode, right: ASTNode): ParserDefinition.SpaceRequirements {
- return LanguageUtil.canStickTokensTogetherByLexer(left, right, CtLexerAdapter())
- }
-
- object TokenSets {
- val WHITE_SPACES = TokenSet.create(TokenType.WHITE_SPACE)
- val COMMENTS = TokenSet.create(CtTypes.COMMENT)
-
- val FILE = IFileElementType(Language.findInstance(CtLanguage::class.java))
- }
-}
Index: src/main/kotlin/platform/mcp/ct/CtSyntaxHighlighter.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/CtSyntaxHighlighter.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/CtSyntaxHighlighter.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,104 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct
-
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtTypes
-import com.intellij.openapi.editor.DefaultLanguageHighlighterColors
-import com.intellij.openapi.editor.HighlighterColors
-import com.intellij.openapi.editor.colors.TextAttributesKey
-import com.intellij.openapi.fileTypes.SyntaxHighlighterBase
-import com.intellij.psi.TokenType
-import com.intellij.psi.tree.IElementType
-
-class CtSyntaxHighlighter : SyntaxHighlighterBase() {
-
- override fun getHighlightingLexer() = CtLexerAdapter()
-
- override fun getTokenHighlights(tokenType: IElementType) =
- when (tokenType) {
- CtTypes.HEADER_NAME -> HEADER_NAME_KEYS
- CtTypes.HEADER_NAMESPACE_ELEMENT -> HEADER_NAMESPACE_KEYS
- CtTypes.ACCESS_ELEMENT -> ACCESS_KEYS
- CtTypes.INJECT_INTERFACE_ELEMENT -> INJECT_INTERFACE_KEYS
- CtTypes.EXTEND_ENUM_ELEMENT -> EXTEND_ENUM_KEYS
- CtTypes.CLASS_ELEMENT -> CLASS_ELEMENT_KEYS
- CtTypes.METHOD_ELEMENT -> METHOD_ELEMENT_KEYS
- CtTypes.FIELD_ELEMENT -> FIELD_ELEMENT_KEYS
- CtTypes.CLASS_NAME_ELEMENT -> CLASS_NAME_KEYS
- CtTypes.NAME_ELEMENT -> MEMBER_NAME_KEYS
- CtTypes.CLASS_VALUE, CtTypes.SIGNATURE_CLASS_VALUE_START, CtTypes.SIGNATURE_CLASS_VALUE_END -> CLASS_VALUE_KEYS
- CtTypes.PRIMITIVE -> PRIMITIVE_KEYS
- CtTypes.TYPE_VARIABLE -> TYPE_VARIABLE_KEYS
- CtTypes.COMMENT -> COMMENT_KEYS
- TokenType.BAD_CHARACTER -> BAD_CHARACTER_KEYS
- else -> EMPTY_KEYS
- }
-
- companion object {
- val HEADER_NAME =
- TextAttributesKey.createTextAttributesKey("CT_HEADER_NAME", DefaultLanguageHighlighterColors.KEYWORD)
- val HEADER_NAMESPACE =
- TextAttributesKey.createTextAttributesKey("CT_HEADER_NAMESPACE", DefaultLanguageHighlighterColors.CLASS_REFERENCE)
- val ACCESS =
- TextAttributesKey.createTextAttributesKey("CT_ACCESS", DefaultLanguageHighlighterColors.KEYWORD)
- val INJECT_INTERFACE =
- TextAttributesKey.createTextAttributesKey("CT_INJECT_INTERFACE", DefaultLanguageHighlighterColors.KEYWORD)
- val EXTEND_ENUM =
- TextAttributesKey.createTextAttributesKey("CT_EXTEND_ENUM", DefaultLanguageHighlighterColors.KEYWORD)
- val CLASS_ELEMENT =
- TextAttributesKey.createTextAttributesKey("CT_CLASS_ELEMENT", DefaultLanguageHighlighterColors.KEYWORD)
- val METHOD_ELEMENT =
- TextAttributesKey.createTextAttributesKey("CT_METHOD_ELEMENT", DefaultLanguageHighlighterColors.KEYWORD)
- val FIELD_ELEMENT =
- TextAttributesKey.createTextAttributesKey("CT_FIELD_ELEMENT", DefaultLanguageHighlighterColors.KEYWORD)
- val CLASS_NAME =
- TextAttributesKey.createTextAttributesKey("CT_CLASS_NAME", DefaultLanguageHighlighterColors.STRING)
- val MEMBER_NAME =
- TextAttributesKey.createTextAttributesKey("CT_MEMBER_NAME", DefaultLanguageHighlighterColors.STATIC_FIELD)
- val CLASS_VALUE =
- TextAttributesKey.createTextAttributesKey("CT_CLASS_VALUE", DefaultLanguageHighlighterColors.STATIC_METHOD)
- val PRIMITIVE =
- TextAttributesKey.createTextAttributesKey("CT_PRIMITIVE", DefaultLanguageHighlighterColors.NUMBER)
- val TYPE_VARIABLE =
- TextAttributesKey.createTextAttributesKey("CT_TYPE_VARIABLE", DefaultLanguageHighlighterColors.STATIC_METHOD)
- val COMMENT =
- TextAttributesKey.createTextAttributesKey("CT_COMMENT", DefaultLanguageHighlighterColors.LINE_COMMENT)
- val BAD_CHARACTER =
- TextAttributesKey.createTextAttributesKey("CT_BAD_CHARACTER", HighlighterColors.BAD_CHARACTER)
-
- private val HEADER_NAME_KEYS = arrayOf(HEADER_NAME)
- private val HEADER_NAMESPACE_KEYS = arrayOf(HEADER_NAMESPACE)
- private val ACCESS_KEYS = arrayOf(ACCESS)
- private val INJECT_INTERFACE_KEYS = arrayOf(INJECT_INTERFACE)
- private val EXTEND_ENUM_KEYS = arrayOf(EXTEND_ENUM)
- private val CLASS_ELEMENT_KEYS = arrayOf(CLASS_ELEMENT)
- private val METHOD_ELEMENT_KEYS = arrayOf(METHOD_ELEMENT)
- private val FIELD_ELEMENT_KEYS = arrayOf(FIELD_ELEMENT)
- private val CLASS_NAME_KEYS = arrayOf(CLASS_NAME)
- private val MEMBER_NAME_KEYS = arrayOf(MEMBER_NAME)
- private val CLASS_VALUE_KEYS = arrayOf(CLASS_VALUE)
- private val PRIMITIVE_KEYS = arrayOf(PRIMITIVE)
- private val TYPE_VARIABLE_KEYS = arrayOf(TYPE_VARIABLE)
- private val COMMENT_KEYS = arrayOf(COMMENT)
- private val BAD_CHARACTER_KEYS = arrayOf(BAD_CHARACTER)
- private val EMPTY_KEYS = emptyArray()
- }
-}
Index: src/main/kotlin/platform/mcp/ct/CtSyntaxHighlighterFactory.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/CtSyntaxHighlighterFactory.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/CtSyntaxHighlighterFactory.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,29 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct
-
-import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory
-import com.intellij.openapi.project.Project
-import com.intellij.openapi.vfs.VirtualFile
-
-class CtSyntaxHighlighterFactory : SyntaxHighlighterFactory() {
- override fun getSyntaxHighlighter(project: Project?, virtualFile: VirtualFile?) = CtSyntaxHighlighter()
-}
Index: src/main/kotlin/platform/mcp/ct/fixes/CopyAwAccessibleEntryFix.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/fixes/CopyAwAccessibleEntryFix.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/fixes/CopyAwAccessibleEntryFix.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,69 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.fixes
-
-import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.fabric.FabricModuleType
-import com.demonwav.mcdev.platform.mcp.actions.CopyAwAction
-import com.demonwav.mcdev.platform.sponge.SpongeModuleType
-import com.demonwav.mcdev.util.findModule
-import com.intellij.codeInsight.daemon.QuickFixActionRegistrar
-import com.intellij.codeInsight.intention.IntentionAction
-import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider
-import com.intellij.openapi.editor.Editor
-import com.intellij.openapi.project.Project
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiFile
-import com.intellij.psi.PsiJavaCodeReferenceElement
-
-class CopyAwAccessibleEntryFix(val target: PsiElement, val element: PsiElement) : IntentionAction {
-
- class Provider : UnresolvedReferenceQuickFixProvider() {
-
- override fun registerFixes(ref: PsiJavaCodeReferenceElement, registrar: QuickFixActionRegistrar) {
- val module = ref.findModule() ?: return
- val isApplicable = MinecraftFacet.getInstance(module, FabricModuleType, SpongeModuleType) != null
- if (!isApplicable) {
- return
- }
-
- val resolve = ref.advancedResolve(true)
- val target = resolve.element
- if (target != null && !resolve.isAccessible) {
- registrar.register(CopyAwAccessibleEntryFix(target, ref))
- }
- }
-
- override fun getReferenceClass(): Class = PsiJavaCodeReferenceElement::class.java
- }
-
- override fun startInWriteAction(): Boolean = false
-
- override fun getText(): String = "Copy AW entry"
-
- override fun getFamilyName(): String = "Copy AW entry for inaccessible element"
-
- override fun isAvailable(project: Project, editor: Editor?, file: PsiFile?): Boolean = true
-
- override fun invoke(project: Project, editor: Editor?, file: PsiFile?) {
- CopyAwAction.Util.doCopy(target, element, editor, null)
- }
-}
Index: src/main/kotlin/platform/mcp/ct/inspections/DuplicateAwEntryInspection.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/inspections/DuplicateAwEntryInspection.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/inspections/DuplicateAwEntryInspection.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,81 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.inspections
-
-import com.demonwav.mcdev.platform.mcp.ct.CtFile
-import com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtAwEntryMixin
-import com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtAwMemberNameMixin
-import com.demonwav.mcdev.util.childOfType
-import com.intellij.codeInspection.InspectionManager
-import com.intellij.codeInspection.LocalInspectionTool
-import com.intellij.codeInspection.ProblemDescriptor
-import com.intellij.codeInspection.ProblemHighlightType
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiFile
-import com.intellij.psi.PsiNamedElement
-import com.jetbrains.rd.util.getOrCreate
-import org.jetbrains.plugins.groovy.codeInspection.fixes.RemoveElementQuickFix
-
-class DuplicateAwEntryInspection : LocalInspectionTool() {
-
- override fun checkFile(file: PsiFile, manager: InspectionManager, isOnTheFly: Boolean): Array? {
- if (file !is CtFile) {
- return null
- }
- val collected = HashMap, MutableList>()
- file.entries.filterIsInstance().forEach {
- val target = it.childOfType()?.resolve()
- val accessKind = it.accessKind
- if (target != null && accessKind != null) {
- (collected.getOrCreate(Pair(target, accessKind)) { ArrayList() }) += it
- }
- }
- val problems = ArrayList()
- collected.forEach { (sort, matches) ->
- if (sort.first is PsiNamedElement) {
- if (matches.size > 1) {
- for (match in matches)
- problems += manager.createProblemDescriptor(
- match,
- "Duplicate entry for \"${sort.second} ${(sort.first as PsiNamedElement).name}\"",
- RemoveElementQuickFix("Remove duplicate"),
- ProblemHighlightType.WARNING,
- isOnTheFly,
- )
- }
- }
- }
- return problems.toTypedArray()
- }
-
- override fun runForWholeFile(): Boolean {
- return true
- }
-
- override fun getDisplayName(): String {
- return "Duplicate AW entry"
- }
-
- override fun getStaticDescription(): String {
- return "Warns when the same element has its accessibility, mutability, " +
- "or extensibility changed multiple times in one file."
- }
-}
Index: src/main/kotlin/platform/mcp/ct/inspections/UnknownCtNamespaceInspection.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/inspections/UnknownCtNamespaceInspection.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/inspections/UnknownCtNamespaceInspection.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,51 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.inspections
-
-import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.fabric.FabricModuleType
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtHeader
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtVisitor
-import com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtHeaderMixin
-import com.demonwav.mcdev.util.findModule
-import com.intellij.codeInspection.LocalInspectionTool
-import com.intellij.codeInspection.ProblemsHolder
-
-class UnknownCtNamespaceInspection : LocalInspectionTool() {
- override fun getDisplayName() = "Unknown CT namespace"
- override fun getStaticDescription() = "Reports an unknown namespace in a ClassTweaker header"
-
- override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = object : CtVisitor() {
- override fun visitHeaderMixin(header: CtHeaderMixin) {
- val namespace = header.namespaceString ?: return
-
- val module = header.findModule() ?: return
- val fabricModule = MinecraftFacet.getInstance(module, FabricModuleType) ?: return
-
- if (namespace !in fabricModule.mappingNamespaces) {
- holder.registerProblem(
- (header as CtHeader).namespaceElement ?: header,
- "Unrecognized namespace"
- )
- }
- }
- }
-}
Index: src/main/kotlin/platform/mcp/ct/psi/CtElement.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/CtElement.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/CtElement.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,25 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi
-
-import com.intellij.psi.PsiElement
-
-interface CtElement : PsiElement
Index: src/main/kotlin/platform/mcp/ct/psi/CtElementType.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/CtElementType.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/CtElementType.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,27 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi
-
-import com.demonwav.mcdev.platform.mcp.ct.CtLanguage
-import com.intellij.psi.tree.IElementType
-import org.jetbrains.annotations.NonNls
-
-class CtElementType(@NonNls debugName: String) : IElementType(debugName, CtLanguage)
Index: src/main/kotlin/platform/mcp/ct/psi/CtTokenType.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/CtTokenType.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/CtTokenType.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,27 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi
-
-import com.demonwav.mcdev.platform.mcp.ct.CtLanguage
-import com.intellij.psi.tree.IElementType
-import org.jetbrains.annotations.NonNls
-
-class CtTokenType(@NonNls debugName: String) : IElementType(debugName, CtLanguage)
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwClassEntryMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwClassEntryMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwClassEntryMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,23 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins
-
-interface CtAwClassEntryMixin : CtAwEntryMixin
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwClassNameMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwClassNameMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwClassNameMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,26 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins
-
-import com.demonwav.mcdev.platform.mcp.ct.psi.CtElement
-import com.intellij.psi.PsiReference
-
-interface CtAwClassNameMixin : CtElement, PsiReference
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwDescElementMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwDescElementMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwDescElementMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,26 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins
-
-import com.demonwav.mcdev.platform.mcp.ct.psi.CtElement
-import com.intellij.psi.PsiReference
-
-interface CtAwDescElementMixin : CtElement, PsiReference
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwEntryMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwEntryMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwEntryMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,27 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins
-
-interface CtAwEntryMixin : CtEntryMixin {
-
- val accessKind: String?
- val targetClassName: String?
-}
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwFieldEntryMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwFieldEntryMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwFieldEntryMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,27 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins
-
-interface CtAwFieldEntryMixin : CtAwEntryMixin {
-
- val fieldName: String?
- val fieldDescriptor: String?
-}
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwMemberNameMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwMemberNameMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwMemberNameMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,26 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins
-
-import com.demonwav.mcdev.platform.mcp.ct.psi.CtElement
-import com.intellij.psi.PsiReference
-
-interface CtAwMemberNameMixin : CtElement, PsiReference
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwMethodEntryMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwMethodEntryMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/CtAwMethodEntryMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,27 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins
-
-interface CtAwMethodEntryMixin : CtAwEntryMixin {
-
- val methodName: String?
- val methodDescriptor: String?
-}
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/CtEntryMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/CtEntryMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/CtEntryMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,25 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins
-
-import com.demonwav.mcdev.platform.mcp.ct.psi.CtElement
-
-interface CtEntryMixin : CtElement
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/CtExtendEnumEntryMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/CtExtendEnumEntryMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/CtExtendEnumEntryMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,23 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins
-
-interface CtExtendEnumEntryMixin : CtEntryMixin
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/CtHeaderMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/CtHeaderMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/CtHeaderMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,36 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins
-
-import com.demonwav.mcdev.platform.mcp.ct.psi.CtElement
-import com.intellij.psi.PsiElement
-
-interface CtHeaderMixin : CtElement {
-
- val nameElement: PsiElement
- val nameString: String
- val versionElement: PsiElement?
- val versionString: String?
- val namespaceElement: PsiElement?
- val namespaceString: String?
- // Effective version, AW is 1 and 2; CT starts with 3, so CT v1 has effective version 3.
- val effectiveVersion: Int?
-}
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/CtItfEntryMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/CtItfEntryMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/CtItfEntryMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,23 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins
-
-interface CtItfEntryMixin : CtEntryMixin
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwClassEntryImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwClassEntryImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwClassEntryImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,26 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtAwClassEntryMixin
-import com.intellij.lang.ASTNode
-
-abstract class CtAwClassEntryImplMixin(node: ASTNode) : CtAwEntryImplMixin(node), CtAwClassEntryMixin
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwClassNameImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwClassNameImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwClassNameImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,62 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtAwClassNameMixin
-import com.demonwav.mcdev.util.cached
-import com.demonwav.mcdev.util.findQualifiedClass
-import com.intellij.extapi.psi.ASTWrapperPsiElement
-import com.intellij.lang.ASTNode
-import com.intellij.openapi.util.TextRange
-import com.intellij.psi.PsiClass
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiReference
-import com.intellij.psi.util.PsiModificationTracker
-import com.intellij.util.IncorrectOperationException
-
-abstract class CtAwClassNameImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), CtAwClassNameMixin {
-
- override fun getElement(): PsiElement = this
-
- override fun getReference(): PsiReference? = this
-
- override fun resolve(): PsiElement? {
- return cached(PsiModificationTracker.MODIFICATION_COUNT) { findQualifiedClass(text.replace('/', '.'), this) }
- }
-
- override fun getRangeInElement(): TextRange = TextRange(0, text.length)
-
- override fun getCanonicalText(): String = text
-
- override fun handleElementRename(newElementName: String): PsiElement {
- throw IncorrectOperationException()
- }
-
- override fun bindToElement(element: PsiElement): PsiElement {
- throw IncorrectOperationException()
- }
-
- override fun isReferenceTo(element: PsiElement): Boolean {
- return element is PsiClass && element.qualifiedName == text.replace('/', '.')
- }
-
- override fun isSoft(): Boolean = false
-}
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwDescElementImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwDescElementImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwDescElementImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,70 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtAwDescElementMixin
-import com.demonwav.mcdev.util.cached
-import com.demonwav.mcdev.util.findQualifiedClass
-import com.intellij.extapi.psi.ASTWrapperPsiElement
-import com.intellij.lang.ASTNode
-import com.intellij.openapi.util.TextRange
-import com.intellij.psi.PsiClass
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiReference
-import com.intellij.psi.util.PsiModificationTracker
-import com.intellij.util.IncorrectOperationException
-
-abstract class CtAwDescElementImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), CtAwDescElementMixin {
-
- override fun getElement(): PsiElement = this
-
- override fun getReference(): PsiReference? = this
-
- override fun resolve(): PsiElement? = cached(PsiModificationTracker.MODIFICATION_COUNT) {
- val name = asQualifiedName() ?: return@cached null
- return@cached findQualifiedClass(name, this)
- }
-
- override fun getRangeInElement(): TextRange = TextRange(0, text.length)
-
- override fun getCanonicalText(): String = text
-
- override fun handleElementRename(newElementName: String): PsiElement {
- throw IncorrectOperationException()
- }
-
- override fun bindToElement(element: PsiElement): PsiElement {
- throw IncorrectOperationException()
- }
-
- override fun isReferenceTo(element: PsiElement): Boolean {
- return element is PsiClass && element.qualifiedName == asQualifiedName()
- }
-
- private fun asQualifiedName(): String? =
- if (text.length > 1) {
- text.substring(1, text.length - 1).replace('/', '.')
- } else {
- null
- }
-
- override fun isSoft(): Boolean = false
-}
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwEntryImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwEntryImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwEntryImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,35 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtTypes
-import com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtAwEntryMixin
-import com.intellij.lang.ASTNode
-import com.intellij.psi.PsiElement
-
-abstract class CtAwEntryImplMixin(node: ASTNode) : CtEntryImplMixin(node), CtAwEntryMixin {
-
- override val accessKind: String?
- get() = findChildByType(CtTypes.ACCESS)?.text
-
- override val targetClassName: String?
- get() = findChildByType(CtTypes.CLASS_NAME)?.text
-}
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwFieldEntryImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwFieldEntryImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwFieldEntryImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,34 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtTypes
-import com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtAwFieldEntryMixin
-import com.intellij.lang.ASTNode
-import com.intellij.psi.PsiElement
-
-abstract class CtAwFieldEntryImplMixin(node: ASTNode) : CtAwEntryImplMixin(node), CtAwFieldEntryMixin {
- override val fieldName: String?
- get() = findChildByType(CtTypes.MEMBER_NAME)?.text
-
- override val fieldDescriptor: String?
- get() = findChildByType(CtTypes.FIELD_DESC)?.text
-}
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwMemberNameImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwMemberNameImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwMemberNameImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,105 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtAwFieldEntry
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtAwMethodEntry
-import com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtAwEntryMixin
-import com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtAwMemberNameMixin
-import com.demonwav.mcdev.util.MemberReference
-import com.demonwav.mcdev.util.cached
-import com.intellij.codeInsight.completion.JavaLookupElementBuilder
-import com.intellij.extapi.psi.ASTWrapperPsiElement
-import com.intellij.lang.ASTNode
-import com.intellij.openapi.util.TextRange
-import com.intellij.psi.JavaPsiFacade
-import com.intellij.psi.PsiClass
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiMethod
-import com.intellij.psi.PsiReference
-import com.intellij.psi.PsiSubstitutor
-import com.intellij.psi.util.PsiModificationTracker
-import com.intellij.psi.util.parentOfType
-import com.intellij.util.ArrayUtil
-import com.intellij.util.IncorrectOperationException
-import com.intellij.util.containers.map2Array
-
-abstract class CtAwMemberNameImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), CtAwMemberNameMixin {
-
- override fun getElement(): PsiElement = this
-
- override fun getReference(): PsiReference? = this
-
- override fun resolve(): PsiElement? = cached(PsiModificationTracker.MODIFICATION_COUNT) {
- val entry = this.parentOfType() ?: return@cached null
- val owner = entry.targetClassName?.replace('/', '.')
- return@cached when (entry) {
- is CtAwMethodEntry -> {
- val name = entry.methodName ?: return@cached null
- val desc = entry.methodDescriptor
- MemberReference(name, desc, owner).resolveMember(project, resolveScope)
- // fallback if descriptor is invalid
- ?: MemberReference(name, null, owner).resolveMember(project, resolveScope)
- }
- is CtAwFieldEntry -> {
- val name = entry.fieldName ?: return@cached null
- MemberReference(name, null, owner)
- .resolveMember(project, resolveScope)
- }
- else -> null
- }
- }
-
- override fun getVariants(): Array<*> {
- val entry = this.parentOfType() ?: return ArrayUtil.EMPTY_OBJECT_ARRAY
- val targetClassName = entry.targetClassName?.replace('/', '.')?.replace('$', '.')
- ?: return ArrayUtil.EMPTY_OBJECT_ARRAY
- val targetClass = JavaPsiFacade.getInstance(project)?.findClass(targetClassName, resolveScope)
- ?: return ArrayUtil.EMPTY_OBJECT_ARRAY
-
- return when (entry) {
- is CtAwMethodEntry -> targetClass.methods.map2Array(::methodLookupElement)
- is CtAwFieldEntry -> targetClass.fields
- else -> ArrayUtil.EMPTY_OBJECT_ARRAY
- }
- }
-
- private fun methodLookupElement(it: PsiMethod) =
- JavaLookupElementBuilder.forMethod(it, if (it.isConstructor) "" else it.name, PsiSubstitutor.EMPTY, null)
-
- override fun getRangeInElement(): TextRange = TextRange(0, text.length)
-
- override fun getCanonicalText(): String = text
-
- override fun handleElementRename(newElementName: String): PsiElement {
- throw IncorrectOperationException()
- }
-
- override fun bindToElement(element: PsiElement): PsiElement {
- throw IncorrectOperationException()
- }
-
- override fun isReferenceTo(element: PsiElement): Boolean {
- return element is PsiClass && element.qualifiedName == text.replace('/', '.')
- }
-
- override fun isSoft(): Boolean = false
-}
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwMethodEntryImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwMethodEntryImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtAwMethodEntryImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,34 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtTypes
-import com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtAwMethodEntryMixin
-import com.intellij.lang.ASTNode
-import com.intellij.psi.PsiElement
-
-abstract class CtAwMethodEntryImplMixin(node: ASTNode) : CtAwEntryImplMixin(node), CtAwMethodEntryMixin {
- override val methodName: String?
- get() = findChildByType(CtTypes.MEMBER_NAME)?.text
-
- override val methodDescriptor: String?
- get() = findChildByType(CtTypes.METHOD_DESC)?.text
-}
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtEntryImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtEntryImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtEntryImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,27 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtEntryMixin
-import com.intellij.extapi.psi.ASTWrapperPsiElement
-import com.intellij.lang.ASTNode
-
-abstract class CtEntryImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), CtEntryMixin
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtExtendEnumEntryImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtExtendEnumEntryImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtExtendEnumEntryImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,26 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtExtendEnumEntryMixin
-import com.intellij.lang.ASTNode
-
-abstract class CtExtendEnumEntryImplMixin(node: ASTNode): CtEntryImplMixin(node), CtExtendEnumEntryMixin
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtHeaderImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtHeaderImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtHeaderImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,65 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.ct.gen.psi.CtTypes
-import com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtHeaderMixin
-import com.intellij.extapi.psi.ASTWrapperPsiElement
-import com.intellij.lang.ASTNode
-import com.intellij.openapi.diagnostic.logger
-import com.intellij.psi.PsiElement
-
-abstract class CtHeaderImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), CtHeaderMixin {
- companion object {
- private val LOG = logger()
- }
-
- override val nameElement: PsiElement
- get() = findNotNullChildByType(CtTypes.HEADER_NAME)
-
- override val nameString: String
- get() = nameElement.text
-
- override val versionElement: PsiElement?
- get() = findChildByType(CtTypes.HEADER_VERSION_ELEMENT)
-
- override val versionString: String?
- get() = versionElement?.text
-
- override val namespaceElement: PsiElement?
- get() = findChildByType(CtTypes.HEADER_NAMESPACE_ELEMENT)
-
- override val namespaceString: String?
- get() = namespaceElement?.text
-
- override val effectiveVersion: Int?
- get() {
- val version = versionString?.removePrefix("v")?.toIntOrNull() ?: return null
- return when (nameString) {
- "accessWidener" -> version
- "classTweaker" -> version + 2
- else -> {
- LOG.error("Unknown header name: $nameString")
- null
- }
- }
- }
-}
Index: src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtItfEntryImplMixin.kt
===================================================================
--- src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtItfEntryImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/ct/psi/mixins/impl/CtItfEntryImplMixin.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,26 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.ct.psi.mixins.impl
-
-import com.demonwav.mcdev.platform.mcp.ct.psi.mixins.CtItfEntryMixin
-import com.intellij.lang.ASTNode
-
-abstract class CtItfEntryImplMixin(node: ASTNode): CtEntryImplMixin(node), CtItfEntryMixin
Index: src/main/kotlin/platform/mcp/debug/McpRunConfigurationExtension.kt
===================================================================
--- src/main/kotlin/platform/mcp/debug/McpRunConfigurationExtension.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/debug/McpRunConfigurationExtension.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,56 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.debug
-
-import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.mcp.McpModuleType
-import com.demonwav.mcdev.util.ModuleDebugRunConfigurationExtension
-import com.intellij.debugger.DebuggerManager
-import com.intellij.debugger.engine.DebugProcess
-import com.intellij.debugger.engine.DebugProcessImpl
-import com.intellij.debugger.engine.DebugProcessListener
-import com.intellij.execution.process.ProcessHandler
-import com.intellij.openapi.module.Module
-
-class McpRunConfigurationExtension : ModuleDebugRunConfigurationExtension() {
-
- override fun attachToProcess(handler: ProcessHandler, module: Module) {
- if (MinecraftFacet.getInstance(module)?.isOfType(McpModuleType) == true) {
- DebuggerManager.getInstance(module.project)
- .addDebugProcessListener(handler, MyProcessListener())
- }
- }
-
- private inner class MyProcessListener : DebugProcessListener {
-
- override fun processAttached(process: DebugProcess) {
- if (process !is DebugProcessImpl) {
- return
- }
-
- // Add session listener
- process.xdebugProcess?.session?.addSessionListener(UngrabMouseDebugSessionListener(process))
-
- // We don't need any further events
- process.removeDebugProcessListener(this)
- }
- }
-}
Index: src/main/kotlin/platform/mcp/debug/UngrabMouseDebugSessionListener.kt
===================================================================
--- src/main/kotlin/platform/mcp/debug/UngrabMouseDebugSessionListener.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/debug/UngrabMouseDebugSessionListener.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,128 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.debug
-
-import com.intellij.debugger.engine.DebugProcessImpl
-import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
-import com.intellij.debugger.jdi.VirtualMachineProxyImpl
-import com.intellij.xdebugger.XDebugSessionListener
-import com.sun.jdi.BooleanValue
-import com.sun.jdi.ClassType
-import com.sun.jdi.Field
-import com.sun.jdi.Method
-import com.sun.jdi.ObjectReference
-import com.sun.jdi.ReferenceType
-
-class UngrabMouseDebugSessionListener(private val process: DebugProcessImpl) : XDebugSessionListener {
-
- private fun ungrabMouse() {
- val suspendContextImpl = process.debuggerContext.suspendContext ?: return
- if (suspendContextImpl.thread?.isSuspended != true) {
- return
- }
-
- val frameProxy = suspendContextImpl.frameProxy ?: return
- val debugProcess = suspendContextImpl.debugProcess
- val virtualMachine = debugProcess.virtualMachineProxy
- val evaluationContext = EvaluationContextImpl(suspendContextImpl, frameProxy)
-
- val mouseClass = virtualMachine.classesByName("org.lwjgl.input.Mouse")?.singleOrNull() as? ClassType
- // LWJGL 3 does not have the Mouse class, Minecraft uses its own MouseHelper instead
- if (mouseClass != null) {
- ungrab2(mouseClass, virtualMachine, debugProcess, evaluationContext)
- } else {
- ungrab3(virtualMachine, debugProcess, evaluationContext)
- }
- }
-
- private fun ungrab2(
- mouseClass: ClassType,
- virtualMachine: VirtualMachineProxyImpl,
- debugProcess: DebugProcessImpl,
- evaluationContext: EvaluationContextImpl,
- ) {
- val isGrabbed = mouseClass.methodsByName("isGrabbed", "()Z")?.singleOrNull() ?: return
- val setGrabbed = mouseClass.methodsByName("setGrabbed", "(Z)V")?.singleOrNull() ?: return
- val grabValue = virtualMachine.mirrorOf(false)
-
- val currentState = debugProcess.invokeMethod(evaluationContext, mouseClass, isGrabbed, emptyList())
- if ((currentState as? BooleanValue)?.value() == true) {
- debugProcess.invokeMethod(evaluationContext, mouseClass, setGrabbed, listOf(grabValue))
- }
- }
-
- private fun ungrab3(
- virtualMachine: VirtualMachineProxyImpl,
- debugProcess: DebugProcessImpl,
- evaluationContext: EvaluationContextImpl,
- ) {
- fun findClass(vararg names: String): ClassType? {
- for (name in names) {
- (virtualMachine.classesByName(name)?.singleOrNull() as? ClassType)?.let { return it }
- }
- return null
- }
-
- fun ClassType.fieldByName(vararg names: String): Field? {
- for (name in names) {
- this.fieldByName(name)?.let { return it }
- }
- return null
- }
-
- fun ReferenceType.methodByName(vararg names: Pair): Method? {
- for ((name, signature) in names) {
- this.methodsByName(name, signature)?.singleOrNull()?.let { return it }
- }
- return null
- }
-
- val minecraftClass = findClass(
- "net.minecraft.client.Minecraft",
- "net.minecraft.client.MinecraftClient",
- ) ?: return
- val minecraftGetter = minecraftClass.methodByName(
- "getInstance" to "()Lnet/minecraft/client/Minecraft;",
- "getInstance" to "()Lnet/minecraft/client/MinecraftClient;",
- ) ?: return
- val minecraft = debugProcess.invokeMethod(
- evaluationContext,
- minecraftClass,
- minecraftGetter,
- emptyList(),
- ) as? ObjectReference ?: return
-
- val mouseHelperField = minecraftClass.fieldByName("mouseHandler", "mouse", "mouseHelper") ?: return
- val mouseHelper = minecraft.getValue(mouseHelperField) as? ObjectReference ?: return
-
- val ungrabMouse = mouseHelper.referenceType().methodByName(
- "releaseMouse" to "()V",
- "unlockCursor" to "()V",
- "ungrabMouse" to "()V",
- ) ?: return
-
- debugProcess.invokeMethod(evaluationContext, mouseHelper, ungrabMouse, emptyList())
- }
-
- override fun sessionPaused() {
- ungrabMouse()
- }
-}
Index: src/main/kotlin/platform/mcp/fabricloom/FabricLoomData.kt
===================================================================
--- src/main/kotlin/platform/mcp/fabricloom/FabricLoomData.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/fabricloom/FabricLoomData.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,41 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.fabricloom
-
-import com.intellij.openapi.externalSystem.model.Key
-import com.intellij.openapi.externalSystem.model.ProjectKeys
-import com.intellij.openapi.externalSystem.model.project.AbstractExternalEntityData
-import com.intellij.openapi.externalSystem.model.project.ModuleData
-import java.io.File
-
-data class FabricLoomData(
- val module: ModuleData,
- val tinyMappings: File?,
- val decompileTasks: Map>,
- val splitMinecraftJar: Boolean,
-) : AbstractExternalEntityData(module.owner) {
-
- data class Decompiler(val name: String, val taskName: String, val sourcesPath: String)
-
- companion object {
- val KEY = Key.create(FabricLoomData::class.java, ProjectKeys.TASK.processingWeight + 1)
- }
-}
Index: src/main/kotlin/platform/mcp/fabricloom/FabricLoomDataService.kt
===================================================================
--- src/main/kotlin/platform/mcp/fabricloom/FabricLoomDataService.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/fabricloom/FabricLoomDataService.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,248 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.fabricloom
-
-import com.demonwav.mcdev.asset.MCDevBundle
-import com.demonwav.mcdev.platform.fabric.EntryPoint
-import com.demonwav.mcdev.platform.fabric.creator.MAGIC_DEFERRED_INIT_FILE
-import com.demonwav.mcdev.util.addImplements
-import com.demonwav.mcdev.util.addMethod
-import com.demonwav.mcdev.util.ifNotBlank
-import com.demonwav.mcdev.util.invokeLater
-import com.demonwav.mcdev.util.runWriteAction
-import com.demonwav.mcdev.util.runWriteTaskInSmartMode
-import com.intellij.codeInsight.actions.ReformatCodeProcessor
-import com.intellij.codeInsight.generation.OverrideImplementUtil
-import com.intellij.ide.util.EditorHelper
-import com.intellij.json.psi.JsonArray
-import com.intellij.json.psi.JsonElementGenerator
-import com.intellij.json.psi.JsonFile
-import com.intellij.json.psi.JsonObject
-import com.intellij.openapi.externalSystem.model.DataNode
-import com.intellij.openapi.externalSystem.model.Key
-import com.intellij.openapi.externalSystem.model.project.ProjectData
-import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
-import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService
-import com.intellij.openapi.fileEditor.impl.NonProjectFileWritingAccessProvider
-import com.intellij.openapi.module.Module
-import com.intellij.openapi.project.Project
-import com.intellij.openapi.project.guessProjectDir
-import com.intellij.openapi.ui.Messages
-import com.intellij.openapi.util.text.StringUtil
-import com.intellij.openapi.vfs.VfsUtil
-import com.intellij.psi.JavaDirectoryService
-import com.intellij.psi.JavaPsiFacade
-import com.intellij.psi.PsiClass
-import com.intellij.psi.PsiManager
-import com.intellij.psi.search.GlobalSearchScope
-import com.intellij.util.IncorrectOperationException
-import java.nio.file.Path
-import kotlin.io.path.deleteIfExists
-import kotlin.io.path.div
-import kotlin.io.path.isRegularFile
-import kotlin.io.path.readLines
-import org.jetbrains.plugins.gradle.util.GradleConstants
-
-class FabricLoomDataService : AbstractProjectDataService() {
-
- override fun getTargetDataKey(): Key = FabricLoomData.KEY
-
- override fun importData(
- toImport: Collection>,
- projectData: ProjectData?,
- project: Project,
- modelsProvider: IdeModifiableModelsProvider,
- ) {
- // Dummy service to enable platform-side DataNodes cache
- }
-
- override fun postProcess(
- toImport: MutableCollection>,
- projectData: ProjectData?,
- project: Project,
- modelsProvider: IdeModifiableModelsProvider
- ) {
- if (projectData == null || toImport.isEmpty() || projectData.owner != GradleConstants.SYSTEM_ID) {
- return
- }
-
- deferredProjectInit(project)
- }
-
- private fun deferredProjectInit(project: Project) {
- val baseDir = project.guessProjectDir()?.toNioPath()
- ?: return
- val deferredInitFile = baseDir / ".gradle" / MAGIC_DEFERRED_INIT_FILE
- if (!deferredInitFile.isRegularFile()) {
- return
- }
-
- val lines = deferredInitFile.readLines()
- if (lines.size < 4) {
- return
- }
-
- val (rawAuthors, website, repo, rawEntrypoints) = lines
-
- val authors = rawAuthors.ifNotBlank { it.split(',') } ?: emptyList()
-
- val entrypoints = rawEntrypoints.split(';').map { rawEntrypoint ->
- val (category, type, clazzName, interfaceName) = rawEntrypoint.split(',')
- EntryPoint(category, EntryPoint.Type.valueOf(type), clazzName, interfaceName)
- }
-
- project.runWriteTaskInSmartMode {
- fixupFabricModJson(project, baseDir, authors, website, repo, entrypoints)
- createEntryPoints(project, entrypoints)
- deferredInitFile.deleteIfExists()
- }
- }
-
- private fun fixupFabricModJson(
- project: Project,
- baseDir: Path,
- authors: List,
- website: String,
- repo: String,
- entryPoints: List
- ) {
- val fabricModJsonFile =
- VfsUtil.findFile(baseDir.resolve(Path.of("src", "main", "resources", "fabric.mod.json")), true)
- ?: return
- val jsonFile = PsiManager.getInstance(project).findFile(fabricModJsonFile) as? JsonFile ?: return
- val json = jsonFile.topLevelValue as? JsonObject ?: return
- val generator = JsonElementGenerator(project)
-
- NonProjectFileWritingAccessProvider.allowWriting(listOf(fabricModJsonFile))
- jsonFile.runWriteAction {
- (json.findProperty("authors")?.value as? JsonArray)?.let { authorsArray ->
- for (i in authors.indices) {
- if (i != 0) {
- authorsArray.addBefore(generator.createComma(), authorsArray.lastChild)
- }
- authorsArray.addBefore(generator.createStringLiteral(authors[i]), authorsArray.lastChild)
- }
- }
-
- (json.findProperty("contact")?.value as? JsonObject)?.let { contactObject ->
- val properties = mutableListOf>()
- if (website.isNotBlank()) {
- properties += "website" to website
- }
- if (repo.isNotBlank()) {
- properties += "repo" to repo
- }
- for (i in properties.indices) {
- if (i != 0) {
- contactObject.addBefore(generator.createComma(), contactObject.lastChild)
- }
- val key = StringUtil.escapeStringCharacters(properties[i].first)
- val value = "\"" + StringUtil.escapeStringCharacters(properties[i].second) + "\""
- contactObject.addBefore(generator.createProperty(key, value), contactObject.lastChild)
- }
- }
-
- (json.findProperty("entrypoints")?.value as? JsonObject)?.let { entryPointsObject ->
- val entryPointsByCategory = entryPoints
- .groupBy { it.category }
- .asSequence()
- .sortedBy { it.key }
- .toList()
- for (i in entryPointsByCategory.indices) {
- val entryPointCategory = entryPointsByCategory[i]
- if (i != 0) {
- entryPointsObject.addBefore(generator.createComma(), entryPointsObject.lastChild)
- }
- val values = generator.createValue("[]")
- for (j in entryPointCategory.value.indices) {
- if (j != 0) {
- values.addBefore(generator.createComma(), values.lastChild)
- }
- val entryPointReference = entryPointCategory.value[j].computeReference(project)
- val value = generator.createStringLiteral(entryPointReference)
- values.addBefore(value, values.lastChild)
- }
- val key = StringUtil.escapeStringCharacters(entryPointCategory.key)
- val prop = generator.createProperty(key, "[]")
- prop.value?.replace(values)
- entryPointsObject.addBefore(prop, entryPointsObject.lastChild)
- }
- }
-
- ReformatCodeProcessor(project, jsonFile, null, false).run()
- }
- }
-
- private fun createEntryPoints(project: Project, entryPoints: List) {
- val root = project.guessProjectDir() ?: return
- val psiManager = PsiManager.getInstance(project)
-
- val generatedClasses = mutableSetOf()
-
- for (entryPoint in entryPoints) {
- // find the class, and create it if it doesn't exist
- val clazz = JavaPsiFacade.getInstance(project).findClass(
- entryPoint.className,
- GlobalSearchScope.projectScope(project),
- ) ?: run {
- val packageName = entryPoint.className.substringBeforeLast('.', missingDelimiterValue = "")
- val className = entryPoint.className.substringAfterLast('.')
-
- val dir = VfsUtil.createDirectoryIfMissing(root, "src/main/java/${packageName.replace('.', '/')}")
- val psiDir = psiManager.findDirectory(dir) ?: return@run null
- try {
- JavaDirectoryService.getInstance().createClass(psiDir, className)
- } catch (e: IncorrectOperationException) {
- invokeLater {
- val message = MCDevBundle(
- "intention.error.cannot.create.class.message",
- className,
- e.localizedMessage,
- )
- Messages.showErrorDialog(
- project,
- message,
- MCDevBundle("intention.error.cannot.create.class.title"),
- )
- }
- return
- }
- } ?: continue
-
- clazz.containingFile.runWriteAction {
- clazz.addImplements(entryPoint.interfaceName)
-
- val methodsToImplement = OverrideImplementUtil.getMethodsToOverrideImplement(clazz, true)
- val methods = OverrideImplementUtil.overrideOrImplementMethodCandidates(clazz, methodsToImplement, true)
- for (method in methods) {
- clazz.addMethod(method)
- }
- }
-
- generatedClasses += clazz
- }
-
- for (clazz in generatedClasses) {
- ReformatCodeProcessor(project, clazz.containingFile, null, false).run()
- EditorHelper.openInEditor(clazz)
- }
- }
-}
Index: src/main/kotlin/platform/mcp/fabricloom/FabricLoomDecompileSourceProvider.kt
===================================================================
--- src/main/kotlin/platform/mcp/fabricloom/FabricLoomDecompileSourceProvider.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/fabricloom/FabricLoomDecompileSourceProvider.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,122 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.fabricloom
-
-import com.demonwav.mcdev.platform.forge.inspections.sideonly.Side
-import com.demonwav.mcdev.platform.forge.inspections.sideonly.SideOnlyUtil
-import com.demonwav.mcdev.util.findModule
-import com.demonwav.mcdev.util.runGradleTaskWithCallback
-import com.demonwav.mcdev.util.runWriteActionAndWait
-import com.intellij.codeInsight.AttachSourcesProvider
-import com.intellij.openapi.externalSystem.task.TaskCallback
-import com.intellij.openapi.roots.LibraryOrderEntry
-import com.intellij.openapi.roots.OrderRootType
-import com.intellij.openapi.roots.impl.libraries.LibraryEx
-import com.intellij.openapi.util.ActionCallback
-import com.intellij.psi.PsiFile
-import com.intellij.psi.PsiJavaFile
-import java.nio.file.Paths
-import org.jetbrains.plugins.gradle.util.GradleUtil
-
-class FabricLoomDecompileSourceProvider : AttachSourcesProvider {
- override fun getActions(
- orderEntries: List,
- psiFile: PsiFile,
- ): Collection {
- if (psiFile !is PsiJavaFile || !psiFile.packageName.startsWith("net.minecraft")) {
- return emptyList()
- }
-
- val module = psiFile.findModule() ?: return emptyList()
- val loomData = GradleUtil.findGradleModuleData(module)?.children
- ?.find { it.key == FabricLoomData.KEY }?.data as? FabricLoomData
- ?: return emptyList()
-
- val env = if (!loomData.splitMinecraftJar) {
- "single"
- } else if (isClientClass(psiFile)) {
- "client"
- } else {
- "common"
- }
-
- val decompileTasks = loomData.decompileTasks[env] ?: return emptyList()
- return decompileTasks.map(::DecompileAction)
- }
-
- private fun isClientClass(psiFile: PsiJavaFile): Boolean {
- return psiFile.classes.any { psiClass ->
- return SideOnlyUtil.getSideForClass(psiClass).second == Side.CLIENT
- }
- }
-
- private class DecompileAction(val decompiler: FabricLoomData.Decompiler) :
- AttachSourcesProvider.AttachSourcesAction {
-
- override fun getName(): String = "Decompile with ${decompiler.name}"
- @Suppress("DialogTitleCapitalization") // Minecraft is a proper noun
- override fun getBusyText(): String = "Decompiling Minecraft..."
-
- override fun perform(orderEntriesContainingFile: List): ActionCallback {
- val project = orderEntriesContainingFile.firstOrNull()?.ownerModule?.project
- ?: return ActionCallback.REJECTED
- val projectPath = project.basePath ?: return ActionCallback.REJECTED
-
- val callback = ActionCallback()
- val taskCallback = object : TaskCallback {
- override fun onSuccess() {
- attachSources(orderEntriesContainingFile, decompiler.sourcesPath)
- callback.setDone()
- }
-
- override fun onFailure() = callback.setRejected()
- }
- runGradleTaskWithCallback(
- project,
- Paths.get(projectPath),
- toolWindow = false,
- { settings -> settings.taskNames = listOf(decompiler.taskName) },
- taskCallback,
- )
- return callback
- }
-
- private fun attachSources(libraryEntries: List, sourcePath: String): ActionCallback? {
- // Distinct because for some reason the same library is in there twice
- for (libraryEntry in libraryEntries.distinctBy { it.libraryName }) {
- val library = libraryEntry.library
- if (library != null) {
- runWriteActionAndWait {
- if (library is LibraryEx && library.isDisposed) {
- return@runWriteActionAndWait
- }
-
- val model = library.modifiableModel
- model.addRoot("jar://$sourcePath!/", OrderRootType.SOURCES)
- model.commit()
- }
- }
- }
-
- return ActionCallback.DONE
- }
- }
-}
Index: src/main/kotlin/platform/mcp/fabricloom/FabricLoomProjectResolverExtension.kt
===================================================================
--- src/main/kotlin/platform/mcp/fabricloom/FabricLoomProjectResolverExtension.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/fabricloom/FabricLoomProjectResolverExtension.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,76 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.fabricloom
-
-import com.demonwav.mcdev.platform.mcp.McpModuleSettings
-import com.demonwav.mcdev.platform.mcp.gradle.McpModelData
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.fabricloom.FabricLoomModel
-import com.intellij.openapi.externalSystem.model.DataNode
-import com.intellij.openapi.externalSystem.model.project.ModuleData
-import org.gradle.tooling.model.idea.IdeaModule
-import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
-import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
-
-class FabricLoomProjectResolverExtension : AbstractProjectResolverExtension() {
-
- override fun getExtraProjectModelClasses(): Set> =
- setOf(FabricLoomModel::class.java)
-
- override fun getToolingExtensionsClasses() = extraProjectModelClasses
-
- override fun populateModuleExtraModels(gradleModule: IdeaModule, ideModule: DataNode) {
- val loomData = resolverCtx.getExtraProject(gradleModule, FabricLoomModel::class.java)
- if (loomData != null) {
- val decompilers = loomData.decompilers.mapValues { (_, decompilers) ->
- decompilers.mapTo(mutableSetOf()) { decompiler ->
- FabricLoomData.Decompiler(decompiler.name, decompiler.taskName, decompiler.sourcesPath)
- }
- }
-
- val data = FabricLoomData(
- ideModule.data,
- loomData.tinyMappings,
- decompilers,
- loomData.splitMinecraftJar,
- )
- ideModule.createChild(FabricLoomData.KEY, data)
-
- val mcpData = McpModelData(
- ideModule.data,
- McpModuleSettings.State(
- minecraftVersion = loomData.minecraftVersion,
- ),
- null,
- null
- )
- ideModule.createChild(McpModelData.KEY, mcpData)
-
- for (child in ideModule.children) {
- val childData = child.data
- if (childData is GradleSourceSetData) {
- child.createChild(McpModelData.KEY, mcpData.copy(module = childData))
- }
- }
- }
-
- super.populateModuleExtraModels(gradleModule, ideModule)
- }
-}
Index: src/main/kotlin/platform/mcp/fabricloom/TinyUnscrambler.kt
===================================================================
--- src/main/kotlin/platform/mcp/fabricloom/TinyUnscrambler.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/fabricloom/TinyUnscrambler.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,194 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.fabricloom
-
-import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.fabric.FabricModuleType
-import com.intellij.openapi.module.ModuleManager
-import com.intellij.openapi.project.Project
-import com.intellij.openapi.project.ProjectManager
-import com.intellij.openapi.ui.ComboBox
-import com.intellij.ui.SimpleListCellRenderer
-import com.intellij.ui.components.JBLabel
-import com.intellij.uiDesigner.core.GridConstraints
-import com.intellij.uiDesigner.core.GridLayoutManager
-import com.intellij.unscramble.UnscrambleSupport
-import java.awt.Dimension
-import java.nio.file.Path
-import java.nio.file.Paths
-import javax.swing.ComboBoxModel
-import javax.swing.JPanel
-import net.fabricmc.mappingio.MappedElementKind
-import net.fabricmc.mappingio.MappingReader
-import net.fabricmc.mappingio.MappingVisitor
-import org.jdesktop.swingx.combobox.MapComboBoxModel
-import org.jetbrains.plugins.gradle.util.GradleUtil
-
-class TinyUnscrambler : UnscrambleSupport {
-
- private val symbolPattern = Regex("(([\\w$]+\\.)*(class_\\d+\\$?)+)|((?:field|method)_\\d+)")
-
- override fun getPresentableName() = "Remap Tiny names"
-
- class SettingsComponent(mappings: Map) : JPanel(GridLayoutManager(1, 2)) {
-
- val mappingsBoxModel: MapComboBoxModel = MapComboBoxModel(mappings)
- @Suppress("UNCHECKED_CAST")
- val mappingsBox: ComboBox = ComboBox(mappingsBoxModel as ComboBoxModel)
-
- init {
- mappingsBox.renderer = SimpleListCellRenderer.create { label, value, _ ->
- val path = mappingsBoxModel.getValue(value)
- label.text = "[$value] $path"
- }
- add(
- JBLabel("Mappings: "),
- GridConstraints(
- 0,
- 0,
- 1,
- 1,
- GridConstraints.ANCHOR_WEST,
- GridConstraints.FILL_NONE,
- GridConstraints.SIZEPOLICY_FIXED,
- GridConstraints.SIZEPOLICY_FIXED,
- Dimension(-1, -1),
- Dimension(-1, -1),
- Dimension(-1, -1),
- ),
- )
- add(
- mappingsBox,
- GridConstraints(
- 0,
- 1,
- 1,
- 1,
- GridConstraints.ANCHOR_WEST,
- GridConstraints.FILL_HORIZONTAL,
- GridConstraints.SIZEPOLICY_WANT_GROW,
- GridConstraints.SIZEPOLICY_FIXED,
- Dimension(-1, -1),
- Dimension(-1, -1),
- Dimension(-1, -1),
- ),
- )
- }
- }
-
- override fun createSettingsComponent(): SettingsComponent {
- val mappings = mutableMapOf()
- for (project in ProjectManager.getInstance().openProjects) {
- ModuleManager.getInstance(project).modules
- .filter { MinecraftFacet.getInstance(it, FabricModuleType) != null }
- .associateTo(mappings) { module ->
- val loomData = GradleUtil.findGradleModuleData(module)?.children
- ?.find { it.key == FabricLoomData.KEY }?.data as? FabricLoomData
- ?: return@associateTo module.name to null
- module.name to loomData.tinyMappings?.toPath()
- }
- }
-
- @Suppress("UNCHECKED_CAST")
- return SettingsComponent(mappings.filterValues { it != null } as Map)
- }
-
- override fun unscramble(project: Project, text: String, logName: String, settings: SettingsComponent?): String? {
- val mappingsFile = logName.takeIf(String::isNotBlank)?.let(Paths::get)
- ?: settings?.mappingsBoxModel?.let { mappings -> mappings.selectedItem?.let(mappings::getValue) }
- ?: return null
-
- val interToNamed = mutableMapOf()
- val visitor = object : MappingVisitor {
- var interNsIndex = -1
- var namedNsIndex = -1
-
- lateinit var src: String
- var inter: String? = null
- var named: String? = null
-
- override fun visitNamespaces(srcNamespace: String, dstNamespaces: MutableList) {
- namedNsIndex = dstNamespaces.indexOf("named")
- interNsIndex = dstNamespaces.indexOf("intermediary")
- }
-
- override fun visitContent(): Boolean {
- return interNsIndex >= 0 && namedNsIndex >= 0
- }
-
- override fun visitClass(srcName: String): Boolean {
- src = srcName.replace('/', '.')
- return true
- }
-
- override fun visitField(srcName: String?, srcDesc: String?): Boolean {
- if (srcName != null) {
- src = srcName
- }
- return true
- }
-
- override fun visitMethod(srcName: String?, srcDesc: String?): Boolean {
- if (srcName != null) {
- src = srcName
- }
- return true
- }
-
- override fun visitMethodArg(argPosition: Int, lvIndex: Int, srcName: String?): Boolean {
- return false
- }
-
- override fun visitMethodVar(lvtRowIndex: Int, lvIndex: Int, startOpIdx: Int, endOpIdx: Int, srcName: String?): Boolean {
- return false
- }
-
- override fun visitDstName(targetKind: MappedElementKind, namespace: Int, name: String) {
- when (namespace) {
- interNsIndex -> inter = name
- namedNsIndex -> named = name
- else -> return
- }
-
- if (inter != null && named != null) {
- interToNamed[inter!!] = named!!
- if (targetKind == MappedElementKind.CLASS) {
- // Remap dot-separated qualified classes and simple class names too
- interToNamed[inter!!.replace('/', '.')] = named!!.replace('/', '.')
- interToNamed[inter!!.substringAfterLast('/')] = named!!.substringAfterLast('/')
- }
- }
- }
-
- override fun visitComment(targetKind: MappedElementKind, comment: String) {
- }
-
- override fun visitElementContent(targetKind: MappedElementKind?): Boolean {
- return targetKind != MappedElementKind.METHOD
- }
- }
-
- MappingReader.read(mappingsFile, visitor)
- return symbolPattern.replace(text) {
- interToNamed[it.value] ?: it.value
- }
- }
-}
Index: src/main/kotlin/platform/mcp/framework/McpLibraryKind.kt
===================================================================
--- src/main/kotlin/platform/mcp/framework/McpLibraryKind.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/framework/McpLibraryKind.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,26 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.framework
-
-import com.demonwav.mcdev.util.libraryKind
-import com.intellij.openapi.roots.libraries.LibraryKind
-
-val MCP_LIBRARY_KIND: LibraryKind by libraryKind("mcp-library")
Index: src/main/kotlin/platform/mcp/framework/McpPresentationProvider.kt
===================================================================
--- src/main/kotlin/platform/mcp/framework/McpPresentationProvider.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/framework/McpPresentationProvider.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,45 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.framework
-
-import com.demonwav.mcdev.asset.PlatformAssets
-import com.demonwav.mcdev.platform.mcp.util.McpConstants
-import com.demonwav.mcdev.util.localFile
-import com.intellij.framework.library.LibraryVersionProperties
-import com.intellij.openapi.roots.libraries.LibraryPresentationProvider
-import com.intellij.openapi.util.io.JarUtil
-import com.intellij.openapi.vfs.VirtualFile
-
-class McpPresentationProvider : LibraryPresentationProvider(MCP_LIBRARY_KIND) {
-
- override fun getIcon(properties: LibraryVersionProperties?) = PlatformAssets.MCP_ICON
-
- override fun detect(classesRoots: List): LibraryVersionProperties? {
- for (classesRoot in classesRoots) {
- val file = classesRoot.localFile
-
- if (JarUtil.containsClass(file, McpConstants.MINECRAFT_SERVER)) {
- return LibraryVersionProperties()
- }
- }
- return null
- }
-}
Index: src/main/kotlin/platform/mcp/gradle/McpDataService.kt
===================================================================
--- src/main/kotlin/platform/mcp/gradle/McpDataService.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/gradle/McpDataService.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,59 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle
-
-import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.mcp.McpModuleType
-import com.intellij.openapi.externalSystem.model.DataNode
-import com.intellij.openapi.externalSystem.model.Key
-import com.intellij.openapi.externalSystem.model.project.ProjectData
-import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
-import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService
-import com.intellij.openapi.module.Module
-import com.intellij.openapi.project.Project
-
-class McpDataService : AbstractProjectDataService() {
-
- override fun getTargetDataKey(): Key = McpModelData.KEY
-
- override fun importData(
- toImport: Collection>,
- projectData: ProjectData?,
- project: Project,
- modelsProvider: IdeModifiableModelsProvider,
- ) {
- if (projectData == null || toImport.isEmpty()) {
- return
- }
-
- for (node in toImport) {
- val data = node.data
- val module = modelsProvider.findIdeModule(data.module) ?: continue
-
- val mcpModule = MinecraftFacet.getInstance(module, McpModuleType)
- if (mcpModule != null) {
- // Update the local settings and recompute the SRG map
- mcpModule.updateSettings(data.settings)
- continue
- }
- }
- }
-}
Index: src/main/kotlin/platform/mcp/gradle/McpModelData.kt
===================================================================
--- src/main/kotlin/platform/mcp/gradle/McpModelData.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/gradle/McpModelData.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,40 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle
-
-import com.demonwav.mcdev.platform.mcp.McpModuleSettings
-import com.intellij.openapi.externalSystem.model.Key
-import com.intellij.openapi.externalSystem.model.ProjectKeys
-import com.intellij.openapi.externalSystem.model.project.AbstractExternalEntityData
-import com.intellij.openapi.externalSystem.model.project.ModuleData
-import java.io.File
-
-data class McpModelData(
- val module: ModuleData,
- val settings: McpModuleSettings.State,
- val taskName: String?,
- val accessTransformers: List?,
-) : AbstractExternalEntityData(module.owner) {
- companion object {
- // Process McpModelData after builtin services (e.g. dependency or module data)
- val KEY = Key.create(McpModelData::class.java, ProjectKeys.TASK.processingWeight + 1)
- }
-}
Index: src/main/kotlin/platform/mcp/gradle/McpProjectResolverExtension.kt
===================================================================
--- src/main/kotlin/platform/mcp/gradle/McpProjectResolverExtension.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/gradle/McpProjectResolverExtension.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,98 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle
-
-import com.demonwav.mcdev.platform.mcp.gradle.datahandler.McpModelFG2Handler
-import com.demonwav.mcdev.platform.mcp.gradle.datahandler.McpModelFG3Handler
-import com.demonwav.mcdev.platform.mcp.gradle.datahandler.McpModelNG7Handler
-import com.demonwav.mcdev.platform.mcp.gradle.datahandler.McpModelNMDHandler
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelFG2
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelFG3
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNG7
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNMD
-import com.demonwav.mcdev.util.runGradleTask
-import com.intellij.openapi.externalSystem.model.DataNode
-import com.intellij.openapi.externalSystem.model.project.ModuleData
-import com.intellij.openapi.externalSystem.model.project.ProjectData
-import java.nio.file.Paths
-import org.gradle.tooling.model.idea.IdeaModule
-import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
-
-class McpProjectResolverExtension : AbstractProjectResolverExtension() {
-
- // Register our custom Gradle tooling API model in IntelliJ's project resolver
- override fun getExtraProjectModelClasses(): Set> =
- setOf(McpModelFG2::class.java, McpModelFG3::class.java, McpModelNG7::class.java, McpModelNMD::class.java)
-
- override fun getToolingExtensionsClasses() = extraProjectModelClasses
-
- override fun resolveFinished(projectDataNode: DataNode) {
- // FG3 requires us to run a task for each module
- // We do it here so that we can do this one time for all modules
-
- // We do need to have a project here though
- val project = resolverCtx.externalSystemTaskId.findProject() ?: return
-
- val allTaskNames = findAllTaskNames(projectDataNode)
- if (allTaskNames.isEmpty()) {
- // Seems to not be FG3
- return
- }
-
- val projectDirPath = Paths.get(projectDataNode.data.linkedExternalProjectPath)
- runGradleTask(project, projectDirPath) { settings ->
- settings.taskNames = allTaskNames.distinct()
- }
-
- super.resolveFinished(projectDataNode)
- }
-
- private fun findAllTaskNames(node: DataNode<*>): List {
- fun findAllTaskNames(node: DataNode<*>, taskNames: MutableList) {
- val data = node.data
- if (data is McpModelData) {
- data.taskName?.let { taskName ->
- taskNames += taskName
- }
- }
- for (child in node.children) {
- findAllTaskNames(child, taskNames)
- }
- }
-
- val res = arrayListOf()
- findAllTaskNames(node, res)
- return res
- }
-
- override fun populateModuleExtraModels(gradleModule: IdeaModule, ideModule: DataNode) {
- for (handler in Const.handlers) {
- handler.build(gradleModule, ideModule, resolverCtx)
- }
-
- // Process the other resolver extensions
- super.populateModuleExtraModels(gradleModule, ideModule)
- }
-
- private object Const {
- val handlers = listOf(McpModelFG2Handler, McpModelFG3Handler, McpModelNG7Handler, McpModelNMDHandler)
- }
-}
Index: src/main/kotlin/platform/mcp/gradle/datahandler/McpModelDataHandler.kt
===================================================================
--- src/main/kotlin/platform/mcp/gradle/datahandler/McpModelDataHandler.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/gradle/datahandler/McpModelDataHandler.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,30 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.datahandler
-
-import com.intellij.openapi.externalSystem.model.DataNode
-import com.intellij.openapi.externalSystem.model.project.ModuleData
-import org.gradle.tooling.model.idea.IdeaModule
-import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext
-
-interface McpModelDataHandler {
- fun build(gradleModule: IdeaModule, node: DataNode, resolverCtx: ProjectResolverContext)
-}
Index: src/main/kotlin/platform/mcp/gradle/datahandler/McpModelFG2Handler.kt
===================================================================
--- src/main/kotlin/platform/mcp/gradle/datahandler/McpModelFG2Handler.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/gradle/datahandler/McpModelFG2Handler.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,78 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.datahandler
-
-import com.demonwav.mcdev.platform.mcp.McpModuleSettings
-import com.demonwav.mcdev.platform.mcp.gradle.McpModelData
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelFG2
-import com.demonwav.mcdev.platform.mcp.srg.SrgType
-import com.intellij.openapi.externalSystem.model.DataNode
-import com.intellij.openapi.externalSystem.model.project.ModuleData
-import org.gradle.tooling.model.idea.IdeaModule
-import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
-import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext
-
-object McpModelFG2Handler : McpModelDataHandler {
-
- override fun build(
- gradleModule: IdeaModule,
- node: DataNode,
- resolverCtx: ProjectResolverContext,
- ) {
- val data = resolverCtx.getExtraProject(gradleModule, McpModelFG2::class.java) ?: return
-
- val state = McpModuleSettings.State(
- data.minecraftVersion,
- data.mcpVersion,
- data.mappingFiles.find { it.endsWith("mcp-srg.srg") },
- SrgType.SRG,
- )
-
- val modelData = McpModelData(
- node.data,
- state,
- null,
- null,
- )
-
- node.createChild(
- McpModelData.KEY,
- McpModelData(
- node.data,
- McpModuleSettings.State(
- data.minecraftVersion,
- data.mcpVersion,
- data.mappingFiles.find { it.endsWith("mcp-srg.srg") },
- SrgType.SRG,
- ),
- null,
- null,
- ),
- )
-
- for (child in node.children) {
- val childData = child.data
- if (childData is GradleSourceSetData) {
- child.createChild(McpModelData.KEY, modelData.copy(module = childData))
- }
- }
- }
-}
Index: src/main/kotlin/platform/mcp/gradle/datahandler/McpModelFG3Handler.kt
===================================================================
--- src/main/kotlin/platform/mcp/gradle/datahandler/McpModelFG3Handler.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/gradle/datahandler/McpModelFG3Handler.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,98 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.datahandler
-
-import com.demonwav.mcdev.platform.mcp.McpModuleSettings
-import com.demonwav.mcdev.platform.mcp.at.AtFileType
-import com.demonwav.mcdev.platform.mcp.gradle.McpModelData
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelFG3
-import com.demonwav.mcdev.platform.mcp.srg.SrgType
-import com.demonwav.mcdev.util.runWriteTaskLater
-import com.intellij.openapi.externalSystem.model.DataNode
-import com.intellij.openapi.externalSystem.model.project.ModuleData
-import com.intellij.openapi.fileTypes.ExactFileNameMatcher
-import com.intellij.openapi.fileTypes.FileTypeManager
-import com.intellij.openapi.vfs.LocalFileSystem
-import org.gradle.tooling.model.idea.IdeaModule
-import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
-import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext
-import org.jetbrains.plugins.gradle.util.gradleIdentityPath
-
-object McpModelFG3Handler : McpModelDataHandler {
-
- override fun build(
- gradleModule: IdeaModule,
- node: DataNode,
- resolverCtx: ProjectResolverContext,
- ) {
- val data = resolverCtx.getExtraProject(gradleModule, McpModelFG3::class.java) ?: return
-
- var mcVersion: String? = null
- var forgeVersion: String? = null
- for (minecraftDepVersion in data.minecraftDepVersions) {
- val index = minecraftDepVersion.indexOf('-')
- if (index == -1) {
- continue
- }
- mcVersion = minecraftDepVersion.substring(0, index)
-
- val forgeVersionEnd = minecraftDepVersion.indexOf('_')
- if (forgeVersionEnd != -1 && forgeVersionEnd > index) {
- forgeVersion = minecraftDepVersion.substring(index + 1, forgeVersionEnd)
- }
- break
- }
-
- val state = McpModuleSettings.State(
- mcVersion,
- data.mcpVersion,
- data.taskOutputLocation.absolutePath,
- SrgType.TSRG,
- forgeVersion,
- )
-
- // gradleIdentityPath makes it work with composite builds
- val identityPath = node.data.gradleIdentityPath
- // But ignore it if it is the root project, as taskName already starts with a colon
- val taskName = if (identityPath == ":") data.taskName else identityPath + ':' + data.taskName
-
- val ats = data.accessTransformers
- if (ats != null && ats.isNotEmpty()) {
- runWriteTaskLater {
- for (at in ats) {
- val fileTypeManager = FileTypeManager.getInstance()
- val atFile = LocalFileSystem.getInstance().findFileByIoFile(at) ?: continue
- fileTypeManager.associate(AtFileType, ExactFileNameMatcher(atFile.name))
- }
- }
- }
-
- val modelData = McpModelData(node.data, state, taskName, data.accessTransformers)
- node.createChild(McpModelData.KEY, modelData)
-
- for (child in node.children) {
- val childData = child.data
- if (childData is GradleSourceSetData) {
- child.createChild(McpModelData.KEY, modelData.copy(module = childData))
- }
- }
- }
-}
Index: src/main/kotlin/platform/mcp/gradle/datahandler/McpModelNG7Handler.kt
===================================================================
--- src/main/kotlin/platform/mcp/gradle/datahandler/McpModelNG7Handler.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/gradle/datahandler/McpModelNG7Handler.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,77 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.datahandler
-
-import com.demonwav.mcdev.platform.mcp.McpModuleSettings
-import com.demonwav.mcdev.platform.mcp.at.AtFileType
-import com.demonwav.mcdev.platform.mcp.gradle.McpModelData
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNG7
-import com.demonwav.mcdev.platform.mcp.srg.SrgType
-import com.demonwav.mcdev.platform.neoforge.version.NeoForgeVersion
-import com.demonwav.mcdev.util.runWriteTaskLater
-import com.intellij.openapi.externalSystem.model.DataNode
-import com.intellij.openapi.externalSystem.model.project.ModuleData
-import com.intellij.openapi.fileTypes.ExactFileNameMatcher
-import com.intellij.openapi.fileTypes.FileTypeManager
-import com.intellij.openapi.vfs.LocalFileSystem
-import org.gradle.tooling.model.idea.IdeaModule
-import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
-import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext
-
-object McpModelNG7Handler : McpModelDataHandler {
-
- override fun build(
- gradleModule: IdeaModule,
- node: DataNode,
- resolverCtx: ProjectResolverContext,
- ) {
- val data = resolverCtx.getExtraProject(gradleModule, McpModelNG7::class.java) ?: return
-
- val state = McpModuleSettings.State(
- NeoForgeVersion.getMinecraftVersion(data.neoForgeVersion),
- null,
- data.mappingsFile.absolutePath,
- SrgType.TSRG,
- data.neoForgeVersion,
- )
-
- val ats = data.accessTransformers
- if (ats != null && ats.isNotEmpty()) {
- runWriteTaskLater {
- for (at in ats) {
- val fileTypeManager = FileTypeManager.getInstance()
- val atFile = LocalFileSystem.getInstance().findFileByIoFile(at) ?: continue
- fileTypeManager.associate(AtFileType, ExactFileNameMatcher(atFile.name))
- }
- }
- }
-
- val modelData = McpModelData(node.data, state, null, data.accessTransformers)
- node.createChild(McpModelData.KEY, modelData)
-
- for (child in node.children) {
- val childData = child.data
- if (childData is GradleSourceSetData) {
- child.createChild(McpModelData.KEY, modelData.copy(module = childData))
- }
- }
- }
-}
Index: src/main/kotlin/platform/mcp/gradle/datahandler/McpModelNMDHandler.kt
===================================================================
--- src/main/kotlin/platform/mcp/gradle/datahandler/McpModelNMDHandler.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/gradle/datahandler/McpModelNMDHandler.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,83 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.gradle.datahandler
-
-import com.demonwav.mcdev.platform.mcp.McpModuleSettings
-import com.demonwav.mcdev.platform.mcp.at.AtFileType
-import com.demonwav.mcdev.platform.mcp.gradle.McpModelData
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNMD
-import com.demonwav.mcdev.platform.mcp.srg.SrgType
-import com.demonwav.mcdev.platform.neoforge.version.NeoForgeVersion
-import com.demonwav.mcdev.util.runWriteTaskLater
-import com.intellij.openapi.externalSystem.model.DataNode
-import com.intellij.openapi.externalSystem.model.project.ModuleData
-import com.intellij.openapi.fileTypes.ExactFileNameMatcher
-import com.intellij.openapi.fileTypes.FileTypeManager
-import com.intellij.openapi.vfs.LocalFileSystem
-import org.gradle.tooling.model.idea.IdeaModule
-import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
-import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext
-
-object McpModelNMDHandler : McpModelDataHandler {
-
- override fun build(
- gradleModule: IdeaModule,
- node: DataNode,
- resolverCtx: ProjectResolverContext,
- ) {
- val data = resolverCtx.getExtraProject(gradleModule, McpModelNMD::class.java) ?: return
-
- val minecraftVersion = when {
- data.neoForgeVersion != null -> NeoForgeVersion.getMinecraftVersion(data.neoForgeVersion!!)
- data.neoFormVersion != null -> data.neoFormVersion!!.substringBeforeLast('-').removeSuffix(".0")
- else -> null
- }
-
- val state = McpModuleSettings.State(
- minecraftVersion,
- null,
- data.mappingsFile?.absolutePath,
- SrgType.TSRG,
- data.neoForgeVersion,
- )
-
- val ats = data.accessTransformers
- if (ats != null && ats.isNotEmpty()) {
- runWriteTaskLater {
- for (at in ats) {
- val fileTypeManager = FileTypeManager.getInstance()
- val atFile = LocalFileSystem.getInstance().findFileByIoFile(at) ?: continue
- fileTypeManager.associate(AtFileType, ExactFileNameMatcher(atFile.name))
- }
- }
- }
-
- val modelData = McpModelData(node.data, state, null, data.accessTransformers)
- node.createChild(McpModelData.KEY, modelData)
-
- for (child in node.children) {
- val childData = child.data
- if (childData is GradleSourceSetData) {
- child.createChild(McpModelData.KEY, modelData.copy(module = childData))
- }
- }
- }
-}
Index: src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt
===================================================================
--- src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/inspections/StackEmptyInspection.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,131 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.inspections
-
-import com.demonwav.mcdev.platform.mcp.mappings.getMappedClass
-import com.demonwav.mcdev.platform.mcp.mappings.getMappedField
-import com.demonwav.mcdev.platform.mcp.mappings.getMappedMethod
-import com.demonwav.mcdev.util.findModule
-import com.demonwav.mcdev.util.fullQualifiedName
-import com.intellij.codeInspection.LocalQuickFix
-import com.intellij.codeInspection.ProblemDescriptor
-import com.intellij.openapi.module.Module
-import com.intellij.openapi.project.Project
-import com.intellij.psi.JavaPsiFacade
-import com.intellij.psi.JavaTokenType
-import com.intellij.psi.PsiBinaryExpression
-import com.intellij.psi.PsiClassType
-import com.intellij.psi.PsiExpression
-import com.intellij.psi.PsiField
-import com.intellij.psi.PsiReferenceExpression
-import com.intellij.psi.createSmartPointer
-import com.siyeh.ig.BaseInspection
-import com.siyeh.ig.BaseInspectionVisitor
-import org.jetbrains.annotations.Nls
-
-class StackEmptyInspection : BaseInspection() {
- companion object {
- const val STACK_FQ_NAME = "net.minecraft.world.item.ItemStack"
- }
-
- @Nls
- override fun getDisplayName() = "ItemStack comparison through ItemStack.EMPTY"
-
- override fun buildErrorString(vararg infos: Any): String {
- val compareExpression = infos[0] as PsiExpression
- return "\"${compareExpression.text}\" compared with ItemStack.EMPTY"
- }
-
- override fun getStaticDescription() =
- "Comparing an ItemStack to ItemStack.EMPTY to query stack emptiness can cause unwanted issues." +
- "When a stack in an inventory is shrunk, the instance is not replaced with ItemStack.EMPTY, but" +
- " the stack should still be considered empty. Instead, isEmpty() should be called."
-
- override fun buildFix(vararg infos: Any): LocalQuickFix {
- val compareExpressionPointer = (infos[0] as PsiExpression).createSmartPointer()
- val binaryExpressionPointer = (infos[2] as PsiBinaryExpression).createSmartPointer()
- return object : LocalQuickFix {
- override fun getFamilyName() = "Replace with .isEmpty()"
-
- override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
- val elementFactory = JavaPsiFacade.getElementFactory(project)
-
- val compareExpression = compareExpressionPointer.element ?: return
- val binaryExpression = binaryExpressionPointer.element ?: return
-
- val mappedIsEmpty = compareExpression.findModule()?.getMappedMethod(STACK_FQ_NAME, "isEmpty", "()Z")
-
- var expressionText = "${compareExpression.text}.$mappedIsEmpty()"
-
- // If we were checking for != ItemStack.EMPTY, use !stack.isEmpty()
- if (binaryExpression.operationSign.tokenType == JavaTokenType.NE) {
- expressionText = "!$expressionText"
- }
-
- val replacedExpression =
- elementFactory.createExpressionFromText(expressionText, binaryExpression.context)
- binaryExpression.replace(replacedExpression)
- }
- }
- }
-
- override fun buildVisitor(): BaseInspectionVisitor {
- return object : BaseInspectionVisitor() {
- override fun visitBinaryExpression(expression: PsiBinaryExpression) {
- val operationType = expression.operationSign.tokenType
-
- if (operationType == JavaTokenType.EQEQ || operationType == JavaTokenType.NE) {
- val leftExpression = expression.lOperand
- val rightExpression = expression.rOperand
-
- // Check if both operands evaluate to an ItemStack
- val module = expression.findModule() ?: return
- if (isExpressionStack(module, leftExpression) && isExpressionStack(module, rightExpression)) {
- val leftEmpty = isExpressionEmptyConstant(module, leftExpression)
- val rightEmpty = isExpressionEmptyConstant(module, rightExpression)
-
- // Check that only one of the references are ItemStack.EMPTY
- if (leftEmpty xor rightEmpty) {
- // The other operand will be the stack
- val compareExpression = if (leftEmpty) rightExpression else leftExpression
- val emptyReference = if (leftEmpty) leftExpression else rightExpression
-
- registerError(expression, compareExpression, emptyReference, expression)
- }
- }
- }
- }
-
- private fun isExpressionStack(module: Module, expression: PsiExpression?): Boolean {
- val fqn = (expression?.type as? PsiClassType)?.resolve()?.fullQualifiedName
- return fqn == module.getMappedClass(STACK_FQ_NAME)
- }
-
- private fun isExpressionEmptyConstant(module: Module, expression: PsiExpression?): Boolean {
- val reference = expression as? PsiReferenceExpression ?: return false
- val field = reference.resolve() as? PsiField ?: return false
- val mappedEmpty = module.getMappedField(STACK_FQ_NAME, "EMPTY")
- return field.name == mappedEmpty &&
- field.containingClass?.fullQualifiedName == module.getMappedClass(STACK_FQ_NAME)
- }
- }
- }
-}
Index: src/main/kotlin/platform/mcp/mappings/HardcodedYarnToMojmap.kt
===================================================================
--- src/main/kotlin/platform/mcp/mappings/HardcodedYarnToMojmap.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/mappings/HardcodedYarnToMojmap.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,62 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.mappings
-
-import com.demonwav.mcdev.util.MemberReference
-import com.google.common.collect.ImmutableBiMap
-
-/**
- * A temporary solution until we get something more dynamic sorted
- */
-object HardcodedYarnToMojmap {
- fun createMappings() = Mappings(
- ImmutableBiMap.ofEntries(
- "net.minecraft.item.ItemStack" mapTo "net.minecraft.world.item.ItemStack",
- "net.minecraft.util.Formatting" mapTo "net.minecraft.ChatFormatting",
- "net.minecraft.text.Text" mapTo "net.minecraft.network.chat.Component",
- ),
- ImmutableBiMap.ofEntries(),
- ImmutableBiMap.ofEntries(
- MemberReference(
- owner = "net.minecraft.util.Text",
- name = "stringifiedTranslatable",
- descriptor = "(Ljava/lang/String;[Ljava/lang/Object;)Lnet/minecraft/text/MutableText;"
- ) mapTo MemberReference(
- owner = "net.minecraft.network.chat.Component",
- name = "translatableEscape",
- descriptor = "(Ljava/lang/String;[Ljava/lang/Object;)Lnet/minecraft/network/chat/MutableComponent;"
- ),
- MemberReference(
- owner = "net.minecraft.client.resource.language.I18n",
- name = "translate",
- descriptor = "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;"
- ) mapTo MemberReference(
- owner = "net.minecraft.client.resources.language.I18n",
- name = "get",
- descriptor = "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;"
- )
- ),
- hashMapOf(),
- false,
- )
-
- private infix fun T.mapTo(value: T) = java.util.AbstractMap.SimpleEntry(this, value)
-}
Index: src/main/kotlin/platform/mcp/mappings/HasCustomNamedMappings.kt
===================================================================
--- src/main/kotlin/platform/mcp/mappings/HasCustomNamedMappings.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/mappings/HasCustomNamedMappings.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,25 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.mappings
-
-interface HasCustomNamedMappings {
- val namedToMojangManager: MappingsManager?
-}
Index: src/main/kotlin/platform/mcp/mappings/Mappings.kt
===================================================================
--- src/main/kotlin/platform/mcp/mappings/Mappings.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/mappings/Mappings.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,139 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.mappings
-
-import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.util.MemberReference
-import com.demonwav.mcdev.util.descriptor
-import com.demonwav.mcdev.util.fullQualifiedName
-import com.demonwav.mcdev.util.mapFirstNotNull
-import com.demonwav.mcdev.util.qualifiedMemberReference
-import com.demonwav.mcdev.util.simpleQualifiedMemberReference
-import com.google.common.collect.ImmutableBiMap
-import com.intellij.openapi.module.Module
-import com.intellij.psi.PsiClass
-import com.intellij.psi.PsiField
-import com.intellij.psi.PsiMethod
-
-class Mappings(
- val classMap: ImmutableBiMap,
- val fieldMap: ImmutableBiMap,
- val methodMap: ImmutableBiMap,
- private val intermediaryNames: HashMap,
- val containsFieldDescriptors: Boolean,
-) {
- fun getIntermediaryClass(fullQualifiedName: String) = classMap[fullQualifiedName]
- fun getIntermediaryClass(psiClass: PsiClass): String? {
- return getIntermediaryClass(psiClass.fullQualifiedName ?: return null)
- }
-
- fun getIntermediaryField(reference: MemberReference) = fieldMap[reference]
- fun getIntermediaryField(field: PsiField) = getIntermediaryField(
- if (containsFieldDescriptors) {
- field.qualifiedMemberReference
- } else {
- field.simpleQualifiedMemberReference
- }
- )
-
- fun getIntermediaryMethod(reference: MemberReference) = methodMap[reference]
- fun getIntermediaryMethod(method: PsiMethod) = getIntermediaryMethod(method.qualifiedMemberReference)
-
- fun tryGetMappedClass(fullQualifiedName: String) = classMap.inverse()[fullQualifiedName]
- fun getMappedClass(fullQualifiedName: String) = tryGetMappedClass(fullQualifiedName) ?: fullQualifiedName
-
- fun tryGetMappedField(reference: MemberReference) = fieldMap.inverse()[reference]
- fun getMappedField(reference: MemberReference) = tryGetMappedField(reference) ?: reference
-
- fun tryGetMappedMethod(reference: MemberReference) = methodMap.inverse()[reference]
- fun getMappedMethod(reference: MemberReference) = tryGetMappedMethod(reference) ?: reference
-
- fun mapIntermediaryToMapped(name: String) = intermediaryNames[name]
-}
-
-private val Module.namedToMojang: Mappings? get() {
- val mcFacet = MinecraftFacet.getInstance(this) ?: return null
- val manager = mcFacet.modules.filterIsInstance().mapFirstNotNull { it.namedToMojangManager }
- ?: return null
- return manager.mappingsNow?.takeUnless { it.containsFieldDescriptors }
-}
-
-fun Module.getMappedClass(mojangName: String): String {
- return namedToMojang?.getMappedClass(mojangName) ?: mojangName
-}
-
-fun Module.getMojangClass(mappedName: String): String {
- return namedToMojang?.getIntermediaryClass(mappedName) ?: mappedName
-}
-
-fun Module.getMojangClass(clazz: PsiClass): String? {
- return getMojangClass(clazz.fullQualifiedName ?: return null)
-}
-
-fun Module.getMappedField(mojangField: MemberReference): String {
- return namedToMojang?.tryGetMappedField(mojangField.withoutDescriptor)?.name ?: mojangField.name
-}
-
-fun Module.getMappedField(mojangClass: String, mojangField: String): String {
- return getMappedField(MemberReference(mojangField, null, mojangClass))
-}
-
-fun Module.getMojangField(mappedField: MemberReference): String {
- return namedToMojang?.getIntermediaryField(mappedField.withoutDescriptor)?.name ?: mappedField.name
-}
-
-fun Module.getMojangField(mappedClass: String, mappedField: String): String {
- return getMojangField(MemberReference(mappedField, null, mappedClass))
-}
-
-fun Module.getMojangField(field: PsiField): String? {
- val clazz = field.containingClass?.fullQualifiedName ?: return null
- return getMojangField(clazz, field.name)
-}
-
-fun Module.getMappedMethod(mojangMethod: MemberReference): String {
- return namedToMojang?.tryGetMappedMethod(mojangMethod)?.name ?: mojangMethod.name
-}
-
-fun Module.getMappedMethod(mojangClass: String, mojangMethod: String, mojangDescriptor: String): String {
- return getMappedMethod(MemberReference(mojangMethod, mojangDescriptor, mojangClass))
-}
-
-fun Module.getMappedMethodCall(mojangClass: String, mojangMethod: String, mojangDescriptor: String, p: String): String {
- val mappedMethodRef = namedToMojang?.tryGetMappedMethod(
- MemberReference(mojangMethod, mojangDescriptor, mojangClass)
- ) ?: return "$mojangClass.$mojangMethod($p)"
- return "${mappedMethodRef.owner}.${mappedMethodRef.name}($p)"
-}
-
-fun Module.getMojangMethod(mappedMethod: MemberReference): String {
- return namedToMojang?.getIntermediaryMethod(mappedMethod)?.name ?: mappedMethod.name
-}
-
-fun Module.getMojangMethod(mappedClass: String, mappedMethod: String, mappedDescriptor: String): String {
- return getMojangMethod(MemberReference(mappedMethod, mappedDescriptor, mappedClass))
-}
-
-fun Module.getMojangMethod(method: PsiMethod): String? {
- val clazz = method.containingClass?.fullQualifiedName ?: return null
- val descriptor = method.descriptor ?: return null
- return getMojangMethod(clazz, method.name, descriptor)
-}
Index: src/main/kotlin/platform/mcp/mappings/MappingsManager.kt
===================================================================
--- src/main/kotlin/platform/mcp/mappings/MappingsManager.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/mappings/MappingsManager.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,100 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.mappings
-
-import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.mcp.McpModuleType
-import com.demonwav.mcdev.platform.mcp.srg.SrgType
-import com.demonwav.mcdev.util.mapFirstNotNull
-import com.intellij.openapi.module.ModuleManager
-import com.intellij.openapi.project.Project
-import java.nio.file.Files
-import java.nio.file.Paths
-import java.util.concurrent.ExecutionException
-import java.util.concurrent.TimeUnit
-import java.util.concurrent.TimeoutException
-import kotlin.io.path.absolutePathString
-import org.jetbrains.concurrency.Promise
-import org.jetbrains.concurrency.rejectedPromise
-import org.jetbrains.concurrency.resolvedPromise
-import org.jetbrains.concurrency.runAsync
-
-abstract class MappingsManager {
- var mappings: Promise = rejectedPromise("Mappings not loaded")
- @Synchronized get
- protected set
-
- val mappingsNow: Mappings?
- @Synchronized get() = try {
- mappings.blockingGet(1, TimeUnit.NANOSECONDS)
- } catch (e: ExecutionException) {
- null
- } catch (e: TimeoutException) {
- null
- }
-
- abstract fun parse()
-
- companion object {
- private val map = HashMap()
-
- @Deprecated("This needs replacing with something that doesn't cause memory leaks")
- fun getInstance(file: String, srgType: SrgType) = map.computeIfAbsent(file) { SrgMappingsManager(it, srgType) }
-
- fun findAnyInstance(project: Project) =
- ModuleManager.getInstance(project).modules.mapFirstNotNull {
- MinecraftFacet.getInstance(it, McpModuleType)?.mappingsManager
- }
- }
-
- class Immediate(mappings: Mappings) : MappingsManager() {
- init {
- this.mappings = resolvedPromise(mappings)
- }
-
- override fun parse() {
- }
- }
-
- private class SrgMappingsManager(val file: String, val srgType: SrgType) : MappingsManager() {
- @Synchronized
- override fun parse() {
- if (mappings.state == Promise.State.PENDING) {
- return
- }
-
- mappings = if (file.isNotBlank()) {
- val path = Paths.get(file)
- if (Files.notExists(path)) {
- rejectedPromise("No mapping data available at " + path.absolutePathString())
- } else {
- runAsync {
- // Load SRG map from files
- srgType.srgParser.parseSrg(Paths.get(file))
- }
- }
- } else {
- // Path to SRG files is unknown
- rejectedPromise("No mapping data available: file path is blank")
- }
- }
- }
-}
Index: src/main/kotlin/platform/mcp/navigation/SrgMemberChooseByNameContributor.kt
===================================================================
--- src/main/kotlin/platform/mcp/navigation/SrgMemberChooseByNameContributor.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/navigation/SrgMemberChooseByNameContributor.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,103 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.navigation
-
-import com.demonwav.mcdev.facet.MinecraftFacet
-import com.demonwav.mcdev.platform.mcp.McpModuleType
-import com.demonwav.mcdev.platform.mcp.mappings.Mappings
-import com.demonwav.mcdev.util.MemberReference
-import com.intellij.navigation.ChooseByNameContributor
-import com.intellij.navigation.NavigationItem
-import com.intellij.openapi.module.Module
-import com.intellij.openapi.module.ModuleManager
-import com.intellij.openapi.project.Project
-import com.intellij.psi.search.GlobalSearchScope
-
-class SrgMemberChooseByNameContributor : ChooseByNameContributor {
-
- // Cached between uses
- var srgMap: Mappings? = null
- var module: Module? = null
-
- override fun getNames(project: Project, includeNonProjectItems: Boolean): Array {
- if (!includeNonProjectItems) {
- return emptyArray()
- }
-
- val names = mutableSetOf()
-
- val modules = ModuleManager.getInstance(project).modules
- for (module in modules) {
- val mcpModule = MinecraftFacet.getInstance(module, McpModuleType) ?: continue
- srgMap = mcpModule.mappingsManager?.mappingsNow ?: continue
- this.module = module
- break // for speed's sake, only use the first one found
- }
-
- srgMap?.apply {
- fieldMap.values.mapTo(names) { it.name }
- methodMap.values.mapTo(names) { it.name + it.descriptor }
- }
-
- return names.toTypedArray()
- }
-
- override fun getItemsByName(
- name: String,
- pattern: String,
- project: Project,
- includeNonProjectItems: Boolean,
- ): Array {
- if (!includeNonProjectItems || srgMap == null || module == null) {
- return emptyArray()
- }
-
- var memberRef: MemberReference? = null
- if (name.startsWith("field")) {
- for ((mcp, srg) in srgMap!!.fieldMap) {
- if (name == srg.name) {
- memberRef = mcp
- break
- }
- }
- } else if (name.startsWith("func")) {
- for ((mcp, srg) in srgMap!!.methodMap) {
- if (name == srg.name + srg.descriptor) {
- memberRef = mcp
- break
- }
- }
- }
-
- try {
- memberRef?.let {
- val member =
- it.resolveMember(project, GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module!!))
- ?: return emptyArray()
- return arrayOf(member)
- }
- return emptyArray()
- } finally {
- srgMap = null // reset for next run
- module = null
- }
- }
-}
Index: src/main/kotlin/platform/mcp/srg/McpUnscrambler.kt
===================================================================
--- src/main/kotlin/platform/mcp/srg/McpUnscrambler.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/srg/McpUnscrambler.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,38 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.srg
-
-import com.demonwav.mcdev.platform.mcp.mappings.MappingsManager
-import com.intellij.openapi.project.Project
-import com.intellij.unscramble.UnscrambleSupport
-import javax.swing.JComponent
-
-class McpUnscrambler : UnscrambleSupport {
-
- private val srgPattern = Regex("(?:field|func)_\\d+_[a-zA-Z]+_?")
-
- override fun getPresentableName() = "Remap SRG names"
-
- override fun unscramble(project: Project, text: String, logName: String, settings: JComponent?): String? {
- val srgMap = MappingsManager.findAnyInstance(project)?.mappingsNow ?: return null
- return srgPattern.replace(text) { srgMap.mapIntermediaryToMapped(it.value) ?: it.value }
- }
-}
Index: src/main/kotlin/platform/mcp/srg/SrgMemberReference.kt
===================================================================
--- src/main/kotlin/platform/mcp/srg/SrgMemberReference.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/srg/SrgMemberReference.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,35 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.srg
-
-import com.demonwav.mcdev.util.MemberReference
-
-object SrgMemberReference {
-
- fun toString(reference: MemberReference): String {
- return reference.owner!!.replace('.', '/') + '/' + reference.name + (reference.descriptor ?: "")
- }
-
- fun parse(reference: String, descriptor: String? = null): MemberReference {
- val pos = reference.lastIndexOf('/')
- return MemberReference(reference.substring(pos + 1), descriptor, reference.substring(0, pos).replace('/', '.'))
- }
-}
Index: src/main/kotlin/platform/mcp/srg/SrgParser.kt
===================================================================
--- src/main/kotlin/platform/mcp/srg/SrgParser.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/srg/SrgParser.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,28 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.srg
-
-import com.demonwav.mcdev.platform.mcp.mappings.Mappings
-import java.nio.file.Path
-
-interface SrgParser {
- fun parseSrg(path: Path): Mappings
-}
Index: src/main/kotlin/platform/mcp/srg/SrgType.kt
===================================================================
--- src/main/kotlin/platform/mcp/srg/SrgType.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/srg/SrgType.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,27 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.srg
-
-enum class SrgType(val srgParser: SrgParser) {
- SRG(StandardSrgParser),
- TSRG(TinySrgParser),
- ;
-}
Index: src/main/kotlin/platform/mcp/srg/StandardSrgParser.kt
===================================================================
--- src/main/kotlin/platform/mcp/srg/StandardSrgParser.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/srg/StandardSrgParser.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,61 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.srg
-
-import com.demonwav.mcdev.platform.mcp.mappings.Mappings
-import com.demonwav.mcdev.util.MemberReference
-import com.google.common.collect.ImmutableBiMap
-import java.nio.file.Files
-import java.nio.file.Path
-
-object StandardSrgParser : SrgParser {
- override fun parseSrg(path: Path): Mappings {
- val classMapBuilder = ImmutableBiMap.builder()
- val fieldMapBuilder = ImmutableBiMap.builder()
- val methodMapBuilder = ImmutableBiMap.builder()
- val srgNames = hashMapOf()
-
- Files.lines(path).forEach { line ->
- val parts = line.split(' ')
- when (parts[0]) {
- "CL:" -> {
- val srg = parts[1].replace('/', '.')
- val mcp = parts[2].replace('/', '.')
- classMapBuilder.put(mcp, srg)
- }
- "FD:" -> {
- val mcp = SrgMemberReference.parse(parts[1])
- val srg = SrgMemberReference.parse(parts[2])
- fieldMapBuilder.put(mcp, srg)
- srgNames[srg.name] = mcp.name
- }
- "MD:" -> {
- val mcp = SrgMemberReference.parse(parts[1], parts[2])
- val srg = SrgMemberReference.parse(parts[3], parts[4])
- methodMapBuilder.put(mcp, srg)
- srgNames[srg.name] = mcp.name
- }
- }
- }
-
- return Mappings(classMapBuilder.build(), fieldMapBuilder.build(), methodMapBuilder.build(), srgNames, false)
- }
-}
Index: src/main/kotlin/platform/mcp/srg/TinySrgParser.kt
===================================================================
--- src/main/kotlin/platform/mcp/srg/TinySrgParser.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/srg/TinySrgParser.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,183 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.srg
-
-import com.demonwav.mcdev.platform.mcp.mappings.Mappings
-import com.demonwav.mcdev.util.MemberReference
-import com.google.common.collect.ImmutableBiMap
-import com.intellij.openapi.util.registry.Registry
-import java.nio.file.Files
-import java.nio.file.Path
-import net.fabricmc.mappingio.MappedElementKind
-import net.fabricmc.mappingio.MappingReader
-import net.fabricmc.mappingio.MappingVisitor
-
-object TinySrgParser : SrgParser {
- private val commentRegex = Regex("#.+")
-
- override fun parseSrg(path: Path): Mappings {
- val classMapBuilder = ImmutableBiMap.builder()
- val fieldMapBuilder = ImmutableBiMap.builder()
- val methodMapBuilder = ImmutableBiMap.builder()
- val srgNames = hashMapOf()
-
- if (Registry.`is`("mcdev.new.tsrg.parser")) {
- newParser(path, classMapBuilder, fieldMapBuilder, methodMapBuilder, srgNames)
- } else {
- oldParser(path, classMapBuilder, fieldMapBuilder, methodMapBuilder, srgNames)
- }
-
- return Mappings(
- classMapBuilder.build(),
- fieldMapBuilder.build(),
- methodMapBuilder.build(),
- srgNames,
- false,
- )
- }
-
- private fun oldParser(
- path: Path,
- classMapBuilder: ImmutableBiMap.Builder,
- fieldMapBuilder: ImmutableBiMap.Builder,
- methodMapBuilder: ImmutableBiMap.Builder,
- srgNames: HashMap,
- ) {
- var classRef: Pair? = null
-
- Files.lines(path).forEach { line ->
- val cleaned = commentRegex.replace(line, "")
- if (cleaned.isEmpty()) {
- return@forEach
- }
-
- if (!cleaned.startsWith('\t')) {
- val (mcp, srg) = cleaned.split(' ')
- val mcpRef = mcp.replace('/', '.')
- val srgRef = srg.replace('/', '.')
- classMapBuilder.put(mcpRef, srgRef)
- classRef = Pair(mcpRef, srgRef)
- return@forEach
- }
-
- // Don't error on an invalid file, just skip
- val clazz = classRef ?: return@forEach
-
- val parts = cleaned.split(' ')
- if (parts.size == 2) {
- // Field
- val (mcp, srg) = cleaned.substring(1).split(' ')
- val mcpRef = SrgMemberReference.parse(clazz.first + "/" + mcp)
- val srgRef = SrgMemberReference.parse(clazz.second + "/" + srg)
- fieldMapBuilder.put(mcpRef, srgRef)
- srgNames[srg] = mcp
- } else if (parts.size == 3) {
- // Method
- val (mcp, sig, srg) = cleaned.substring(1).split(' ')
- val mcpRef = SrgMemberReference.parse(clazz.first + "/" + mcp, sig)
- val srgRef = SrgMemberReference.parse(clazz.second + "/" + srg, sig)
- methodMapBuilder.put(mcpRef, srgRef)
- srgNames[srg] = mcp
- }
- }
- }
-
- private fun newParser(
- path: Path,
- classMapBuilder: ImmutableBiMap.Builder,
- fieldMapBuilder: ImmutableBiMap.Builder,
- methodMapBuilder: ImmutableBiMap.Builder,
- srgNames: HashMap,
- ) {
- val visitor = object : MappingVisitor {
- var namedNsIndex = -1
-
- lateinit var cls: String
- var desc: String? = null
- var inter: String? = null
- var named: String? = null
-
- override fun visitNamespaces(srcNamespace: String, dstNamespaces: MutableList) {
- namedNsIndex = dstNamespaces.indexOf("right")
- }
-
- override fun visitContent(): Boolean {
- return namedNsIndex >= 0
- }
-
- override fun visitClass(srcName: String): Boolean {
- cls = srcName.replace('/', '.')
- desc = null
- inter = null
- named = null
- return true
- }
-
- override fun visitField(srcName: String, srcDesc: String?): Boolean {
- inter = srcName
- return true
- }
-
- override fun visitMethod(srcName: String?, srcDesc: String?): Boolean {
- inter = srcName
- desc = srcDesc
- return true
- }
-
- override fun visitMethodArg(argPosition: Int, lvIndex: Int, srcName: String?): Boolean {
- return false
- }
-
- override fun visitMethodVar(lvtRowIndex: Int, lvIndex: Int, startOpIdx: Int, endOpIdx: Int, srcName: String?): Boolean {
- return false
- }
-
- override fun visitDstName(targetKind: MappedElementKind, namespace: Int, name: String) {
- when (namespace) {
- namedNsIndex -> named = name
- else -> return
- }
-
- if (targetKind == MappedElementKind.CLASS) {
- classMapBuilder.put(cls, name.replace('/', '.'))
- } else if (inter != null) {
- val inter = inter!!
- if (targetKind == MappedElementKind.FIELD) {
- fieldMapBuilder.put(MemberReference(inter, null, cls), MemberReference(name, null, cls))
- srgNames[inter] = name
- } else if (targetKind == MappedElementKind.METHOD) {
- methodMapBuilder.put(MemberReference(inter, desc, cls), MemberReference(name, desc, cls))
- srgNames[inter] = name
- }
- }
- }
-
- override fun visitComment(targetKind: MappedElementKind, comment: String) {
- }
-
- override fun visitElementContent(targetKind: MappedElementKind?): Boolean {
- return targetKind != MappedElementKind.METHOD
- }
- }
-
- MappingReader.read(path, visitor)
- }
-}
Index: src/main/kotlin/platform/mcp/util/McpConstants.kt
===================================================================
--- src/main/kotlin/platform/mcp/util/McpConstants.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/util/McpConstants.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,29 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.util
-
-object McpConstants {
-
- const val CHAT_FORMATTING = "net.minecraft.ChatFormatting"
- const val TEXT_COLOR = "net.minecraft.network.chat.TextColor"
- const val MINECRAFT_SERVER = "net.minecraft.server.MinecraftServer"
- const val PNG_MCMETA = "*.png.mcmeta"
-}
Index: src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleData.kt
===================================================================
--- src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleData.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleData.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,35 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.vanillagradle
-
-import com.intellij.openapi.externalSystem.model.Key
-import com.intellij.openapi.externalSystem.model.ProjectKeys
-import com.intellij.openapi.externalSystem.model.project.AbstractExternalEntityData
-import com.intellij.openapi.externalSystem.model.project.ModuleData
-
-data class VanillaGradleData(
- val module: ModuleData,
- val decompileTaskName: String,
-) : AbstractExternalEntityData(module.owner) {
- companion object {
- val KEY = Key.create(VanillaGradleData::class.java, ProjectKeys.TASK.processingWeight + 1)
- }
-}
Index: src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleDataService.kt
===================================================================
--- src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleDataService.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleDataService.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,43 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.vanillagradle
-
-import com.intellij.openapi.externalSystem.model.DataNode
-import com.intellij.openapi.externalSystem.model.Key
-import com.intellij.openapi.externalSystem.model.project.ProjectData
-import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
-import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService
-import com.intellij.openapi.module.Module
-import com.intellij.openapi.project.Project
-
-class VanillaGradleDataService : AbstractProjectDataService() {
-
- override fun getTargetDataKey(): Key = VanillaGradleData.KEY
-
- override fun importData(
- toImport: Collection>,
- projectData: ProjectData?,
- project: Project,
- modelsProvider: IdeModifiableModelsProvider,
- ) {
- // Dummy service to enable platform-side DataNodes cache
- }
-}
Index: src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleDecompileSourceProvider.kt
===================================================================
--- src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleDecompileSourceProvider.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleDecompileSourceProvider.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,97 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2026 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.vanillagradle
-
-import com.demonwav.mcdev.util.findModule
-import com.demonwav.mcdev.util.runGradleTaskWithCallback
-import com.intellij.codeInsight.AttachSourcesProvider
-import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder
-import com.intellij.openapi.externalSystem.model.DataNode
-import com.intellij.openapi.externalSystem.model.project.ProjectData
-import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback
-import com.intellij.openapi.externalSystem.task.TaskCallback
-import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
-import com.intellij.openapi.roots.LibraryOrderEntry
-import com.intellij.openapi.util.ActionCallback
-import com.intellij.psi.PsiFile
-import com.intellij.psi.PsiJavaFile
-import java.nio.file.Paths
-import org.jetbrains.plugins.gradle.util.GradleConstants
-import org.jetbrains.plugins.gradle.util.GradleUtil
-
-class VanillaGradleDecompileSourceProvider : AttachSourcesProvider {
- override fun getActions(
- orderEntries: List,
- psiFile: PsiFile,
- ): Collection {
- if (psiFile !is PsiJavaFile || !psiFile.packageName.startsWith("net.minecraft")) {
- return emptyList()
- }
-
- val module = psiFile.findModule() ?: return emptyList()
- val vgData = GradleUtil.findGradleModuleData(module)?.children
- ?.find { it.key == VanillaGradleData.KEY }?.data as? VanillaGradleData
- ?: return emptyList()
- return listOf(DecompileAction(vgData.decompileTaskName))
- }
-
- private class DecompileAction(val decompileTaskName: String) : AttachSourcesProvider.AttachSourcesAction {
-
- override fun getName(): String = "Decompile Minecraft"
-
- override fun getBusyText(): String = @Suppress("DialogTitleCapitalization") "Decompiling Minecraft..."
-
- override fun perform(orderEntriesContainingFile: List): ActionCallback {
- val project = orderEntriesContainingFile.firstOrNull()?.ownerModule?.project
- ?: return ActionCallback.REJECTED
- val projectPath = project.basePath ?: return ActionCallback.REJECTED
-
- val callback = ActionCallback()
- val taskCallback = object : TaskCallback {
- override fun onSuccess() {
- val importSpec = ImportSpecBuilder(project, GradleConstants.SYSTEM_ID)
- .withCallback(
- object : ExternalProjectRefreshCallback {
- override fun onSuccess(externalProject: DataNode?) = callback.setDone()
-
- override fun onFailure(errorMessage: String, errorDetails: String?) {
- callback.reject(
- if (errorDetails == null) errorMessage else "$errorMessage: $errorDetails",
- )
- }
- },
- )
- ExternalSystemUtil.refreshProject(projectPath, importSpec)
- }
-
- override fun onFailure() = callback.setRejected()
- }
- runGradleTaskWithCallback(
- project,
- Paths.get(projectPath),
- toolWindow = false,
- { settings -> settings.taskNames = listOf(decompileTaskName) },
- taskCallback,
- )
- return callback
- }
- }
-}
Index: src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleProjectResolverExtension.kt
===================================================================
--- src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleProjectResolverExtension.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
+++ src/main/kotlin/platform/mcp/vanillagradle/VanillaGradleProjectResolverExtension.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056)
@@ -1,50 +0,0 @@
-/*
- * Minecraft Development for IntelliJ
- *
- * https://mcdev.io/
- *
- * Copyright (C) 2025 minecraft-dev
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, version 3.0 only.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.demonwav.mcdev.platform.mcp.vanillagradle
-
-import com.demonwav.mcdev.platform.mcp.gradle.tooling.vanillagradle.VanillaGradleModel
-import com.intellij.openapi.application.runReadAction
-import com.intellij.openapi.externalSystem.model.DataNode
-import com.intellij.openapi.externalSystem.model.project.ModuleData
-import org.gradle.tooling.model.idea.IdeaModule
-import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
-
-class VanillaGradleProjectResolverExtension : AbstractProjectResolverExtension() {
-
- override fun getExtraProjectModelClasses(): Set> =
- setOf(VanillaGradleModel::class.java)
-
- override fun getToolingExtensionsClasses() = extraProjectModelClasses
-
- override fun populateModuleExtraModels(gradleModule: IdeaModule, ideModule: DataNode) {
- val vgData = runReadAction {
- resolverCtx.getExtraProject(gradleModule, VanillaGradleModel::class.java)
- }
- if (vgData != null && vgData.hasVanillaGradle()) {
- val gradleProjectPath = gradleModule.gradleProject.projectIdentifier.projectPath
- val suffix = if (gradleProjectPath.endsWith(':')) "" else ":"
- val decompileTaskName = gradleProjectPath + suffix + "decompile"
- ideModule.createChild(VanillaGradleData.KEY, VanillaGradleData(ideModule.data, decompileTaskName))
- }
-
- super.populateModuleExtraModels(gradleModule, ideModule)
- }
-}
Index: src/main/kotlin/platform/minecraft/MinecraftModule.kt
===================================================================
--- src/main/kotlin/platform/minecraft/MinecraftModule.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/MinecraftModule.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,120 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft
+
+import com.demonwav.mcdev.MinecraftSettings
+import com.demonwav.mcdev.facet.MinecraftFacet
+import com.demonwav.mcdev.platform.AbstractModule
+import com.demonwav.mcdev.platform.PlatformType
+import com.demonwav.mcdev.platform.minecraft.mappings.MappingsManager
+import com.demonwav.mcdev.platform.minecraft.util.MinecraftConstants
+import com.demonwav.mcdev.translations.TranslationFileListener
+import com.demonwav.mcdev.util.runWriteTaskLater
+import com.intellij.json.JsonFileType
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder
+import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
+import com.intellij.openapi.fileTypes.FileTypeManager
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.openapi.vfs.VirtualFileManager
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiMethod
+import com.intellij.util.messages.MessageBusConnection
+import javax.swing.Icon
+import org.jetbrains.plugins.gradle.settings.GradleSettings
+import org.jetbrains.plugins.gradle.util.GradleConstants
+
+class MinecraftModule(facet: MinecraftFacet) : AbstractModule(facet) {
+
+ private lateinit var connection: MessageBusConnection
+
+ private val settings: MinecraftModuleSettings = MinecraftModuleSettings.getInstance(module)
+ val accessTransformers = mutableSetOf()
+
+ var mappingsManager: MappingsManager? = null
+ private set
+
+ override fun init() {
+ initSrg()
+ connection = project.messageBus.connect()
+ connection.subscribe(VirtualFileManager.VFS_CHANGES, TranslationFileListener)
+
+ runWriteTaskLater {
+ FileTypeManager.getInstance().associatePattern(JsonFileType.INSTANCE, MinecraftConstants.PNG_MCMETA)
+ }
+
+ if (MinecraftSettings.instance.forceExternalAnnotations) {
+ // Force enable external annotations so that ours are provided
+ var requiresRefresh = false
+ for (settings in GradleSettings.getInstance(project).linkedProjectsSettings) {
+ if (!settings.isResolveExternalAnnotations) {
+ settings.isResolveExternalAnnotations = true
+ requiresRefresh = true
+ }
+ }
+
+ if (requiresRefresh) {
+ // Schedule Gradle project refresh outside write lock
+ ApplicationManager.getApplication().invokeLater {
+ ExternalSystemUtil.refreshProjects(ImportSpecBuilder(project, GradleConstants.SYSTEM_ID))
+ }
+ }
+ }
+ }
+
+ private fun initSrg() {
+ val settings = getSettings()
+ val file = settings.mappingFile ?: return
+ val srgType = settings.srgType ?: return
+
+ mappingsManager = MappingsManager.getInstance(file, srgType)
+ mappingsManager?.parse()
+ }
+
+ override val moduleType = MinecraftModuleType
+ override val type = PlatformType.MINECRAFT
+ override val icon: Icon? = null
+
+ override fun writeErrorMessageForEventParameter(eventClass: PsiClass, method: PsiMethod) = ""
+
+ fun getSettings() = settings.state
+
+ fun updateSettings(data: MinecraftModuleSettings.State) {
+ this.settings.loadState(data)
+ val mappingFile = data.mappingFile ?: return
+ val srgType = data.srgType ?: return
+
+ mappingsManager = MappingsManager.getInstance(mappingFile, srgType)
+ mappingsManager?.parse()
+ }
+
+ fun addAccessTransformerFile(file: VirtualFile) {
+ accessTransformers.add(file)
+ }
+
+ override fun dispose() {
+ super.dispose()
+
+ connection.disconnect()
+ accessTransformers.clear()
+ mappingsManager = null
+ }
+}
Index: src/main/kotlin/platform/minecraft/MinecraftModuleSettings.kt
===================================================================
--- src/main/kotlin/platform/minecraft/MinecraftModuleSettings.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/MinecraftModuleSettings.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,72 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft
+
+import com.demonwav.mcdev.platform.minecraft.srg.SrgType
+import com.intellij.openapi.components.PersistentStateComponent
+import com.intellij.openapi.components.State
+import com.intellij.openapi.components.Storage
+import com.intellij.openapi.components.StoragePathMacros
+import com.intellij.openapi.module.Module
+import com.intellij.openapi.module.ModuleManager
+
+// Persisted name kept from when this was the "MCP" platform, so existing module settings still load
+@State(name = "McpModuleSettings", storages = [Storage(StoragePathMacros.MODULE_FILE)])
+class MinecraftModuleSettings : PersistentStateComponent {
+
+ data class State(
+ var minecraftVersion: String? = null,
+ var mcpVersion: String? = null,
+ var mappingFile: String? = null,
+ var srgType: SrgType? = null,
+ var platformVersion: String? = null,
+ )
+
+ private var state: State = State(srgType = SrgType.SRG)
+
+ override fun getState(): State = state
+
+ override fun loadState(state: State) {
+ this.state = state
+ }
+
+ companion object {
+ fun getInstance(module: Module): MinecraftModuleSettings {
+ // TODO: Migrate these to the facet's settings
+
+ val settings = module.getService(MinecraftModuleSettings::class.java) as MinecraftModuleSettings
+ if (settings.getState().minecraftVersion != null) {
+ return settings
+ }
+
+ // Attempt to find settings on the parent module
+ val manager = ModuleManager.getInstance(module.project)
+ val path = manager.getModuleGroupPath(module) ?: return settings
+ val parent = manager.findModuleByName(path.last()) ?: return settings
+
+ val newSettings = parent.getService(MinecraftModuleSettings::class.java) as MinecraftModuleSettings
+ if (newSettings.getState().minecraftVersion == null) {
+ return settings
+ }
+ return newSettings
+ }
+ }
+}
Index: src/main/kotlin/platform/minecraft/MinecraftModuleType.kt
===================================================================
--- src/main/kotlin/platform/minecraft/MinecraftModuleType.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/MinecraftModuleType.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,60 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft
+
+import com.demonwav.mcdev.facet.MinecraftFacet
+import com.demonwav.mcdev.platform.AbstractModuleType
+import com.demonwav.mcdev.platform.PlatformType
+import com.demonwav.mcdev.platform.minecraft.mappings.getMappedClass
+import com.demonwav.mcdev.platform.minecraft.mappings.getMappedField
+import com.demonwav.mcdev.platform.minecraft.util.MinecraftConstants
+import com.demonwav.mcdev.util.CommonColors
+import com.intellij.openapi.module.Module
+import java.awt.Color
+import javax.swing.Icon
+
+object MinecraftModuleType : AbstractModuleType("", "") {
+
+ private const val ID = "MINECRAFT_MODULE_TYPE"
+
+ init {
+ CommonColors.applyStandardColors(colorMap, MinecraftConstants.CHAT_FORMATTING)
+ CommonColors.applyStandardColors(colorMap, MinecraftConstants.TEXT_COLOR)
+ }
+
+ override fun classToColorMappings(module: Module): Map {
+ return colorMap.mapKeys { key ->
+ val parts = key.key.split('.')
+ val className = parts.dropLast(1).joinToString(".")
+ val fieldName = parts.last()
+ "${module.getMappedClass(className)}.${module.getMappedField(className, fieldName)}"
+ }
+ }
+
+ override val platformType = PlatformType.MINECRAFT
+ override val icon: Icon? = null
+ override val id = ID
+ override val ignoredAnnotations = emptyList()
+ override val listenerAnnotations = emptyList()
+ override val hasIcon = false
+
+ override fun generateModule(facet: MinecraftFacet) = MinecraftModule(facet)
+}
Index: src/main/kotlin/platform/minecraft/actions/CopyAtAction.kt
===================================================================
--- src/main/kotlin/platform/minecraft/actions/CopyAtAction.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/actions/CopyAtAction.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,115 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.actions
+
+import com.demonwav.mcdev.platform.minecraft.mappings.Mappings
+import com.demonwav.mcdev.util.ActionData
+import com.demonwav.mcdev.util.descriptor
+import com.demonwav.mcdev.util.fullQualifiedName
+import com.demonwav.mcdev.util.internalName
+import com.demonwav.mcdev.util.showBalloon
+import com.demonwav.mcdev.util.showSuccessBalloon
+import com.intellij.openapi.actionSystem.AnActionEvent
+import com.intellij.openapi.editor.Editor
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiField
+import com.intellij.psi.PsiMethod
+import java.awt.Toolkit
+import java.awt.datatransfer.StringSelection
+
+class CopyAtAction : SrgActionBase() {
+ override fun withSrgTarget(parent: PsiElement, srgMap: Mappings?, e: AnActionEvent, data: ActionData) {
+ if (srgMap == null) {
+ when (parent) {
+ is PsiField -> {
+ val className = parent.containingClass?.fullQualifiedName ?: return showBalloon(
+ e,
+ "No containing class found"
+ )
+ copyToClipboard(
+ data.editor,
+ data.element,
+ className + " " + parent.name,
+ )
+ }
+ is PsiMethod -> {
+ val className = parent.containingClass?.fullQualifiedName ?: return showBalloon(
+ e,
+ "No containing class found"
+ )
+ copyToClipboard(
+ data.editor,
+ data.element,
+ className + " " + parent.internalName + parent.descriptor,
+ )
+ }
+ is PsiClass -> {
+ val className = parent.fullQualifiedName ?: return showBalloon(e, "Could not get FQN")
+ copyToClipboard(
+ data.editor,
+ data.element,
+ className,
+ )
+ }
+ }
+ } else {
+ when (parent) {
+ is PsiField -> {
+ val containing = parent.containingClass ?: return showBalloon(e, "No SRG name found")
+ val classSrg = srgMap.getIntermediaryClass(containing) ?: return showBalloon(e, "No SRG name found")
+ val srg = srgMap.getIntermediaryField(parent) ?: return showBalloon(e, "No SRG name found")
+ copyToClipboard(
+ data.editor,
+ data.element,
+ classSrg + " " + srg.name + " # " + parent.name,
+ )
+ }
+
+ is PsiMethod -> {
+ val containing = parent.containingClass ?: return showBalloon(e, "No SRG name found")
+ val classSrg = srgMap.getIntermediaryClass(containing) ?: return showBalloon(e, "No SRG name found")
+ val srg = srgMap.getIntermediaryMethod(parent) ?: return showBalloon(e, "No SRG name found")
+ copyToClipboard(
+ data.editor,
+ data.element,
+ classSrg + " " + srg.name + srg.descriptor + " # " + parent.name,
+ )
+ }
+
+ is PsiClass -> {
+ val classMcpToSrg =
+ srgMap.getIntermediaryClass(parent) ?: return showBalloon(e, "No SRG name found")
+ copyToClipboard(data.editor, data.element, classMcpToSrg)
+ }
+
+ else -> showBalloon(e, "Not a valid element")
+ }
+ }
+ }
+
+ private fun copyToClipboard(editor: Editor, element: PsiElement, text: String) {
+ val stringSelection = StringSelection(text)
+ val clpbrd = Toolkit.getDefaultToolkit().systemClipboard
+ clpbrd.setContents(stringSelection, null)
+ showSuccessBalloon(editor, element, "Copied $text")
+ }
+}
Index: src/main/kotlin/platform/minecraft/actions/CopyAwAction.kt
===================================================================
--- src/main/kotlin/platform/minecraft/actions/CopyAwAction.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/actions/CopyAwAction.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,102 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.actions
+
+import com.demonwav.mcdev.util.descriptor
+import com.demonwav.mcdev.util.getDataFromActionEvent
+import com.demonwav.mcdev.util.internalName
+import com.demonwav.mcdev.util.showBalloon
+import com.demonwav.mcdev.util.showSuccessBalloon
+import com.intellij.openapi.actionSystem.AnAction
+import com.intellij.openapi.actionSystem.AnActionEvent
+import com.intellij.openapi.editor.Editor
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiField
+import com.intellij.psi.PsiIdentifier
+import com.intellij.psi.PsiMember
+import com.intellij.psi.PsiMethod
+import com.intellij.psi.PsiReference
+import java.awt.Toolkit
+import java.awt.datatransfer.StringSelection
+
+class CopyAwAction : AnAction() {
+
+ override fun actionPerformed(e: AnActionEvent) {
+ val data = getDataFromActionEvent(e) ?: return showBalloon(e, "Unknown failure")
+ val editor = data.editor
+
+ val element = data.element
+ if (element !is PsiIdentifier) {
+ showBalloon(e, "Invalid element")
+ return
+ }
+
+ val target = when (val parent = element.parent) {
+ is PsiMember -> parent
+ is PsiReference -> parent.resolve()
+ else -> null
+ } ?: return showBalloon(e, "Invalid element")
+
+ Util.doCopy(target, element, editor, e)
+ }
+
+ object Util {
+ fun doCopy(target: PsiElement, element: PsiElement, editor: Editor?, e: AnActionEvent?) {
+ when (target) {
+ is PsiClass -> {
+ val text = "accessible class ${target.internalName}"
+ copyToClipboard(editor, element, text)
+ }
+ is PsiField -> {
+ val containing = target.containingClass?.internalName
+ ?: return maybeShow(e, "Could not get owner of field")
+ val desc = target.type.descriptor
+ val text = "accessible field $containing ${target.name} $desc"
+ copyToClipboard(editor, element, text)
+ }
+ is PsiMethod -> {
+ val containing = target.containingClass?.internalName
+ ?: return maybeShow(e, "Could not get owner of method")
+ val desc = target.descriptor ?: return maybeShow(e, "Could not get descriptor of method")
+ val text = "accessible method $containing ${target.internalName} $desc"
+ copyToClipboard(editor, element, text)
+ }
+ else -> maybeShow(e, "Invalid element")
+ }
+ }
+
+ private fun copyToClipboard(editor: Editor?, element: PsiElement, text: String) {
+ val stringSelection = StringSelection(text)
+ val clpbrd = Toolkit.getDefaultToolkit().systemClipboard
+ clpbrd.setContents(stringSelection, null)
+ if (editor != null) {
+ showSuccessBalloon(editor, element, "Copied: \"$text\"")
+ }
+ }
+
+ private fun maybeShow(e: AnActionEvent?, text: String) {
+ if (e != null) {
+ showBalloon(e, text)
+ }
+ }
+ }
+}
Index: src/main/kotlin/platform/minecraft/actions/CopyCoremodTargetAction.kt
===================================================================
--- src/main/kotlin/platform/minecraft/actions/CopyCoremodTargetAction.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/actions/CopyCoremodTargetAction.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,102 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.actions
+
+import com.demonwav.mcdev.platform.minecraft.mappings.Mappings
+import com.demonwav.mcdev.util.ActionData
+import com.demonwav.mcdev.util.descriptor
+import com.demonwav.mcdev.util.fullQualifiedName
+import com.demonwav.mcdev.util.showBalloon
+import com.demonwav.mcdev.util.showSuccessBalloon
+import com.intellij.openapi.actionSystem.AnActionEvent
+import com.intellij.openapi.editor.Editor
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiField
+import com.intellij.psi.PsiMethod
+import java.awt.Toolkit
+import java.awt.datatransfer.StringSelection
+import kotlinx.serialization.json.JsonObject
+import kotlinx.serialization.json.JsonPrimitive
+
+class CopyCoremodTargetAction : SrgActionBase() {
+ override fun withSrgTarget(parent: PsiElement, srgMap: Mappings?, e: AnActionEvent, data: ActionData) {
+ when (parent) {
+ is PsiField -> {
+ val containing = parent.containingClass ?: return showBalloon(e, "No containing class")
+ val classSrg = srgMap?.getIntermediaryClass(containing) ?: containing.fullQualifiedName ?: return showBalloon(
+ e,
+ "No containing class found"
+ )
+ val srg = srgMap?.getIntermediaryField(parent)?.name ?: parent.name
+ copyToClipboard(
+ data.editor,
+ data.element,
+ Pair("target", "FIELD"),
+ Pair("class", classSrg),
+ Pair("fieldName", srg),
+ )
+ }
+ is PsiMethod -> {
+ val containing = parent.containingClass ?: return showBalloon(e, "No containing class")
+ val classSrg = srgMap?.getIntermediaryClass(containing) ?: containing.fullQualifiedName ?: return showBalloon(
+ e,
+ "No containing class found"
+ )
+ val (srgName, srgDescriptor) = srgMap?.getIntermediaryMethod(parent)?.let {
+ it.name to it.descriptor
+ } ?: (parent.name to parent.descriptor)
+ if (srgDescriptor == null) {
+ return showBalloon(e, "No method descriptor found")
+ }
+ copyToClipboard(
+ data.editor,
+ data.element,
+ Pair("target", "METHOD"),
+ Pair("class", classSrg),
+ Pair("methodName", srgName),
+ Pair("methodDesc", srgDescriptor),
+ )
+ }
+ is PsiClass -> {
+ val classSrg = srgMap?.getIntermediaryClass(parent) ?: parent.fullQualifiedName ?: return showBalloon(
+ e,
+ "No FQN found"
+ )
+ copyToClipboard(
+ data.editor,
+ data.element,
+ Pair("target", "CLASS"),
+ Pair("name", classSrg),
+ )
+ }
+ else -> showBalloon(e, "Not a valid element")
+ }
+ }
+
+ private fun copyToClipboard(editor: Editor, element: PsiElement, vararg keys: Pair) {
+ val text = JsonObject(keys.toMap().mapValues { JsonPrimitive(it.value) }).toString()
+ val stringSelection = StringSelection(text)
+ val clpbrd = Toolkit.getDefaultToolkit().systemClipboard
+ clpbrd.setContents(stringSelection, null)
+ showSuccessBalloon(editor, element, "Copied Coremod Target Reference")
+ }
+}
Index: src/main/kotlin/platform/minecraft/actions/FindSrgMappingAction.kt
===================================================================
--- src/main/kotlin/platform/minecraft/actions/FindSrgMappingAction.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/actions/FindSrgMappingAction.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,56 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.actions
+
+import com.demonwav.mcdev.platform.minecraft.mappings.Mappings
+import com.demonwav.mcdev.util.ActionData
+import com.demonwav.mcdev.util.showBalloon
+import com.demonwav.mcdev.util.showSuccessBalloon
+import com.intellij.openapi.actionSystem.AnActionEvent
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiField
+import com.intellij.psi.PsiMethod
+
+class FindSrgMappingAction : SrgActionBase() {
+
+ override fun withSrgTarget(parent: PsiElement, srgMap: Mappings?, e: AnActionEvent, data: ActionData) {
+ if (srgMap == null) {
+ return showBalloon(e, "No mappings found")
+ }
+
+ when (parent) {
+ is PsiField -> {
+ val srg = srgMap.getIntermediaryField(parent) ?: return showBalloon(e, "No SRG name found")
+ showSuccessBalloon(data.editor, data.element, "SRG name: " + srg.name)
+ }
+ is PsiMethod -> {
+ val srg = srgMap.getIntermediaryMethod(parent) ?: return showBalloon(e, "No SRG name found")
+ showSuccessBalloon(data.editor, data.element, "SRG name: " + srg.name + srg.descriptor)
+ }
+ is PsiClass -> {
+ val classMcpToSrg = srgMap.getIntermediaryClass(parent) ?: return showBalloon(e, "No SRG name found")
+ showSuccessBalloon(data.editor, data.element, "SRG name: $classMcpToSrg")
+ }
+ else -> showBalloon(e, "Not a valid element")
+ }
+ }
+}
Index: src/main/kotlin/platform/minecraft/actions/GotoAtEntryAction.kt
===================================================================
--- src/main/kotlin/platform/minecraft/actions/GotoAtEntryAction.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/actions/GotoAtEntryAction.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,117 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.actions
+
+import com.demonwav.mcdev.facet.MinecraftFacet
+import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType
+import com.demonwav.mcdev.platform.minecraft.mappings.MappingsManager
+import com.demonwav.mcdev.platform.mixin.handlers.ShadowHandler
+import com.demonwav.mcdev.util.ActionData
+import com.demonwav.mcdev.util.getDataFromActionEvent
+import com.demonwav.mcdev.util.gotoTargetElement
+import com.demonwav.mcdev.util.qualifiedMemberReference
+import com.demonwav.mcdev.util.showBalloon
+import com.demonwav.mcdev.util.simpleQualifiedMemberReference
+import com.intellij.openapi.actionSystem.AnAction
+import com.intellij.openapi.actionSystem.AnActionEvent
+import com.intellij.openapi.module.ModuleManager
+import com.intellij.psi.PsiField
+import com.intellij.psi.PsiIdentifier
+import com.intellij.psi.PsiManager
+import com.intellij.psi.PsiMember
+import com.intellij.psi.PsiMethod
+import com.intellij.psi.search.LocalSearchScope
+import com.intellij.psi.search.PsiSearchHelper
+import com.intellij.psi.search.UsageSearchContext
+
+class GotoAtEntryAction : AnAction() {
+ override fun actionPerformed(e: AnActionEvent) {
+ val data = getDataFromActionEvent(e) ?: return showBalloon(e)
+
+ if (data.element !is PsiIdentifier) {
+ showBalloon(e)
+ return
+ }
+
+ val mappingsManager = data.instance.getModuleOfType(MinecraftModuleType)?.mappingsManager
+ // Not all ATs are in Minecraft modules, fallback to this if possible
+ // TODO try to find SRG references for all modules if current module isn't found?
+ ?: MappingsManager.findAnyInstance(data.project) ?: return showBalloon(e)
+
+ mappingsManager.mappings.onSuccess { srgMap ->
+ var parent = data.element.parent
+
+ if (parent is PsiMember) {
+ val shadowTarget = ShadowHandler.Util.getInstance()?.findFirstShadowTargetForNavigation(parent)?.element
+ if (shadowTarget != null) {
+ parent = shadowTarget
+ }
+ }
+
+ when (parent) {
+ is PsiField -> {
+ val reference = srgMap.getIntermediaryField(parent) ?: parent.simpleQualifiedMemberReference
+ searchForText(e, data, reference.name)
+ }
+ is PsiMethod -> {
+ val reference = srgMap.getIntermediaryMethod(parent) ?: parent.qualifiedMemberReference
+ searchForText(e, data, reference.name + reference.descriptor)
+ }
+ else ->
+ showBalloon(e)
+ }
+ }
+ }
+
+ private fun searchForText(e: AnActionEvent, data: ActionData, text: String) {
+ val manager = ModuleManager.getInstance(data.project)
+ manager.modules.asSequence()
+ .mapNotNull { MinecraftFacet.getInstance(it, MinecraftModuleType) }
+ .flatMap { it.accessTransformers.asSequence() }
+ .forEach { virtualFile ->
+ val file = PsiManager.getInstance(data.project).findFile(virtualFile) ?: return@forEach
+
+ var found = false
+ PsiSearchHelper.getInstance(data.project)
+ .processElementsWithWord(
+ { element, _ ->
+ gotoTargetElement(element, data.editor, data.file)
+ found = true
+ false
+ },
+ LocalSearchScope(file),
+ text,
+ UsageSearchContext.ANY,
+ true,
+ )
+
+ if (found) {
+ return
+ }
+ }
+
+ showBalloon(e)
+ }
+
+ private fun showBalloon(e: AnActionEvent) {
+ showBalloon(e, "No access transformer entry found")
+ }
+}
Index: src/main/kotlin/platform/minecraft/actions/LookupMemberAction.kt
===================================================================
--- src/main/kotlin/platform/minecraft/actions/LookupMemberAction.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/actions/LookupMemberAction.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,30 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.actions
+
+import com.intellij.openapi.actionSystem.AnAction
+import com.intellij.openapi.actionSystem.AnActionEvent
+
+class LookupMemberAction : AnAction() {
+ override fun actionPerformed(e: AnActionEvent) {
+ // TODO
+ }
+}
Index: src/main/kotlin/platform/minecraft/actions/SrgActionBase.kt
===================================================================
--- src/main/kotlin/platform/minecraft/actions/SrgActionBase.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/actions/SrgActionBase.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,79 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.actions
+
+import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType
+import com.demonwav.mcdev.platform.minecraft.mappings.Mappings
+import com.demonwav.mcdev.platform.mixin.handlers.ShadowHandler
+import com.demonwav.mcdev.util.ActionData
+import com.demonwav.mcdev.util.getDataFromActionEvent
+import com.demonwav.mcdev.util.showBalloon
+import com.intellij.openapi.actionSystem.AnAction
+import com.intellij.openapi.actionSystem.AnActionEvent
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiIdentifier
+import com.intellij.psi.PsiMember
+import com.intellij.psi.PsiReference
+
+abstract class SrgActionBase : AnAction() {
+
+ override fun actionPerformed(e: AnActionEvent) {
+ val data = getDataFromActionEvent(e) ?: return showBalloon(e, "Unknown failure")
+
+ if (data.element !is PsiIdentifier) {
+ showBalloon(e, "Not a valid element")
+ return
+ }
+
+ val minecraftModule = data.instance.getModuleOfType(MinecraftModuleType)
+
+ val mappingsManager = minecraftModule?.mappingsManager ?: return performWithMappings(e, data, data.element, null)
+ mappingsManager.mappings.onSuccess { srgMap ->
+ performWithMappings(e, data, data.element, srgMap)
+ }.onError {
+ showBalloon(e, it.message ?: "No MCP data available")
+ }
+ }
+
+ private fun performWithMappings(
+ e: AnActionEvent,
+ data: ActionData,
+ element: PsiIdentifier,
+ srgMap: Mappings?,
+ ) {
+ var parent = element.parent ?: return showBalloon(e, "Not a valid element")
+
+ if (parent is PsiMember) {
+ val shadowTarget = ShadowHandler.Util.getInstance()?.findFirstShadowTargetForReference(parent)?.element
+ if (shadowTarget != null) {
+ parent = shadowTarget
+ }
+ }
+
+ if (parent is PsiReference) {
+ parent = parent.resolve() ?: return showBalloon(e, "Not a valid element")
+ }
+
+ withSrgTarget(parent, srgMap, e, data)
+ }
+
+ abstract fun withSrgTarget(parent: PsiElement, srgMap: Mappings?, e: AnActionEvent, data: ActionData)
+}
Index: src/main/kotlin/platform/minecraft/at/AtAnnotator.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/AtAnnotator.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/AtAnnotator.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,91 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at
+
+import com.demonwav.mcdev.facet.MinecraftFacet
+import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtEntry
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtFieldName
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtFunction
+import com.demonwav.mcdev.platform.minecraft.at.psi.AtElement
+import com.intellij.lang.annotation.AnnotationHolder
+import com.intellij.lang.annotation.Annotator
+import com.intellij.lang.annotation.HighlightSeverity
+import com.intellij.openapi.editor.markup.EffectType
+import com.intellij.openapi.editor.markup.TextAttributes
+import com.intellij.openapi.module.ModuleUtilCore
+import com.intellij.psi.PsiElement
+import java.awt.Font
+
+class AtAnnotator : Annotator {
+
+ override fun annotate(element: PsiElement, holder: AnnotationHolder) {
+ if (element !is AtEntry) {
+ return
+ }
+
+ val member = element.function ?: element.fieldName ?: return
+
+ val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return
+ val facet = MinecraftFacet.getInstance(module) ?: return
+ val minecraftModule = facet.getModuleOfType(MinecraftModuleType) ?: return
+ val srgMap = minecraftModule.mappingsManager?.mappingsNow ?: return
+
+ val reference = AtMemberReference.get(element, member) ?: return
+
+ // We can resolve this without checking the srg map
+ if (reference.resolveMember(element.project) != null) {
+ if (member is AtFunction) {
+ underline(member.funcName, holder)
+ } else {
+ underline(member, holder)
+ }
+ return
+ }
+
+ // We need to check the srg map, or it can't be resolved (and no underline)
+ when (member) {
+ is AtFieldName -> {
+ srgMap.tryGetMappedField(reference)?.resolveMember(element.project) ?: return
+ underline(member, holder)
+ }
+ is AtFunction -> {
+ srgMap.tryGetMappedMethod(reference)?.resolveMember(element.project) ?: return
+ underline(member.funcName, holder)
+ }
+ }
+ }
+
+ private fun underline(element: AtElement, holder: AnnotationHolder) {
+ holder.newSilentAnnotation(HighlightSeverity.INFORMATION)
+ .range(element)
+ .enforcedTextAttributes(
+ TextAttributes(
+ null,
+ null,
+ AtSyntaxHighlighter.ELEMENT_NAME.defaultAttributes.foregroundColor,
+ EffectType.BOLD_LINE_UNDERSCORE,
+ Font.PLAIN,
+ ),
+ )
+ .create()
+ }
+}
Index: src/main/kotlin/platform/minecraft/at/AtColorSettingsPage.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/AtColorSettingsPage.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/AtColorSettingsPage.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,62 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at
+
+import com.demonwav.mcdev.asset.PlatformAssets
+import com.intellij.openapi.editor.colors.TextAttributesKey
+import com.intellij.openapi.options.colors.AttributesDescriptor
+import com.intellij.openapi.options.colors.ColorDescriptor
+import com.intellij.openapi.options.colors.ColorSettingsPage
+
+class AtColorSettingsPage : ColorSettingsPage {
+
+ override fun getIcon() = PlatformAssets.MINECRAFT_ICON
+ override fun getHighlighter() = AtSyntaxHighlighter()
+ override fun getDemoText() =
+ $$"""
+ # Minecraft
+
+ public net.minecraft.block.BlockFlowerPot func_149928_a(Lnet/minecraft/block/Block;I)Z # canNotContain
+ private-f net.minecraft.inventory.ContainerChest field_7515F4_f # numRows
+ protected net.minecraft.block.state.BlockStateContainer$StateImplementation
+ public-f net.minecraft.item.Item func_77656_e(I)Lnet/minecraft/item/Item; # setMaxDamage
+ public+f net.minecraft.server.management.UserList *
+ default+f net.minecraft.item.Item *()
+ public net.minecraft.world.demo.DemoWorldServer func_175680_a(IIZ)Z # isChunkLoaded
+ """.trimIndent()
+
+ override fun getAdditionalHighlightingTagToDescriptorMap(): Map? = null
+ override fun getAttributeDescriptors() = Constants.DESCRIPTORS
+ override fun getColorDescriptors(): Array = ColorDescriptor.EMPTY_ARRAY
+ override fun getDisplayName() = "Access Transformers"
+
+ private object Constants {
+ val DESCRIPTORS = arrayOf(
+ AttributesDescriptor("Keyword", AtSyntaxHighlighter.KEYWORD),
+ AttributesDescriptor("Class name", AtSyntaxHighlighter.CLASS_NAME),
+ AttributesDescriptor("Class value", AtSyntaxHighlighter.CLASS_VALUE),
+ AttributesDescriptor("Primitive value", AtSyntaxHighlighter.PRIMITIVE),
+ AttributesDescriptor("Element name", AtSyntaxHighlighter.ELEMENT_NAME),
+ AttributesDescriptor("Asterisk", AtSyntaxHighlighter.ASTERISK),
+ AttributesDescriptor("Comment", AtSyntaxHighlighter.COMMENT),
+ )
+ }
+}
Index: src/main/kotlin/platform/minecraft/at/AtCommenter.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/AtCommenter.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/AtCommenter.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,32 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at
+
+import com.intellij.lang.Commenter
+
+class AtCommenter : Commenter {
+
+ override fun getLineCommentPrefix() = "#"
+ override fun getBlockCommentPrefix(): String? = null
+ override fun getBlockCommentSuffix(): String? = null
+ override fun getCommentedBlockCommentPrefix(): String? = null
+ override fun getCommentedBlockCommentSuffix(): String? = null
+}
Index: src/main/kotlin/platform/minecraft/at/AtElementFactory.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/AtElementFactory.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/AtElementFactory.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,137 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+@file:Suppress("unused") // this file represents an API
+
+package com.demonwav.mcdev.platform.minecraft.at
+
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtArgument
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtAsterisk
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtClassName
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtEntry
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtFieldName
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtFuncName
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtFunction
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtKeyword
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtReturnValue
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtTypes
+import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiComment
+import com.intellij.psi.PsiFileFactory
+
+object AtElementFactory {
+
+ fun createFile(project: Project, text: String): AtFile {
+ return PsiFileFactory.getInstance(project).createFileFromText("name", AtFileType, text) as AtFile
+ }
+
+ fun createArgument(project: Project, text: String): AtArgument {
+ val line = "public c.c f($text)V"
+ val file = createFile(project, line)
+
+ return file.firstChild.node.findChildByType(AtTypes.FUNCTION)!!
+ .findChildByType(AtTypes.ARGUMENT)!!.psi as AtArgument
+ }
+
+ fun createClassName(project: Project, name: String): AtClassName {
+ val line = "public $name f(Z)V"
+ val file = createFile(project, line)
+
+ return file.firstChild.node.findChildByType(AtTypes.CLASS_NAME)!!.psi as AtClassName
+ }
+
+ fun createEntry(project: Project, entry: String): AtEntry {
+ val file = createFile(project, entry)
+ return file.firstChild as AtEntry
+ }
+
+ fun createFieldName(project: Project, name: String): AtFieldName {
+ val line = "public c.c $name"
+ val file = createFile(project, line)
+
+ return file.firstChild.node.findChildByType(AtTypes.FIELD_NAME)!!.psi as AtFieldName
+ }
+
+ fun createFuncName(project: Project, name: String): AtFuncName {
+ val line = "public c.c $name(Z)V"
+ val file = createFile(project, line)
+
+ return file.firstChild.node.findChildByType(AtTypes.FUNCTION)!!
+ .findChildByType(AtTypes.FUNC_NAME)!!.psi as AtFuncName
+ }
+
+ fun createFunction(project: Project, function: String): AtFunction {
+ val line = "public c.c $function"
+ val file = createFile(project, line)
+
+ return file.firstChild.node.findChildByType(AtTypes.FUNCTION)!!.psi as AtFunction
+ }
+
+ fun createAsterisk(project: Project): AtAsterisk {
+ val line = "public c.c *"
+ val file = createFile(project, line)
+
+ return file.firstChild.node.findChildByType(AtTypes.FUNCTION)!!
+ .findChildByType(AtTypes.ASTERISK)!!.psi as AtAsterisk
+ }
+
+ fun createKeyword(project: Project, keyword: Keyword): AtKeyword {
+ val line = "${keyword.text} c.c f(Z)V"
+ val file = createFile(project, line)
+
+ return file.firstChild.node.findChildByType(AtTypes.KEYWORD)!!.psi as AtKeyword
+ }
+
+ fun createReturnValue(project: Project, returnValue: String): AtReturnValue {
+ val line = "public c.c f(Z)$returnValue"
+ val file = createFile(project, line)
+
+ return file.firstChild.node.findChildByType(AtTypes.FUNCTION)!!
+ .findChildByType(AtTypes.RETURN_VALUE)!!.psi as AtReturnValue
+ }
+
+ fun createComment(project: Project, comment: String): PsiComment {
+ val line = "# $comment"
+ val file = createFile(project, line)
+
+ return file.node.findChildByType(AtTypes.COMMENT)!!.psi as PsiComment
+ }
+
+ enum class Keyword(val text: String) {
+ PRIVATE("private"),
+ PRIVATE_MINUS_F("private-f"),
+ PRIVATE_PLUS_F("private+f"),
+ PROTECTED("protected"),
+ PROTECTED_MINUS_F("protected-f"),
+ PROTECTED_PLUS_F("protected+f"),
+ PUBLIC("public"),
+ PUBLIC_MINUS_F("public-f"),
+ PUBLIC_PLUS_F("public+f"),
+ DEFAULT("default"),
+ DEFAULT_MINUS_F("default-f"),
+ DEFAULT_PLUS_F("default+f"),
+ ;
+
+ companion object {
+ fun match(s: String) = entries.firstOrNull { it.text == s }
+ fun softMatch(s: String) = entries.filter { it.text.contains(s) }
+ }
+ }
+}
Index: src/main/kotlin/platform/minecraft/at/AtFile.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/AtFile.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/AtFile.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,52 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at
+
+import com.demonwav.mcdev.asset.PlatformAssets
+import com.demonwav.mcdev.facet.MinecraftFacet
+import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType
+import com.intellij.extapi.psi.PsiFileBase
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.module.ModuleUtilCore
+import com.intellij.psi.FileViewProvider
+
+class AtFile(viewProvider: FileViewProvider) : PsiFileBase(viewProvider, AtLanguage) {
+
+ init {
+ setup()
+ }
+
+ private fun setup() {
+ if (ApplicationManager.getApplication().isUnitTestMode) {
+ return
+ }
+
+ val vFile = viewProvider.virtualFile
+
+ val module = ModuleUtilCore.findModuleForFile(vFile, project) ?: return
+ val minecraftModule = MinecraftFacet.getInstance(module, MinecraftModuleType) ?: return
+ minecraftModule.addAccessTransformerFile(vFile)
+ }
+
+ override fun getFileType() = AtFileType
+ override fun toString() = AtFileType.description
+ override fun getIcon(flags: Int) = PlatformAssets.MINECRAFT_ICON
+}
Index: src/main/kotlin/platform/minecraft/at/AtFileType.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/AtFileType.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/AtFileType.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,32 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at
+
+import com.demonwav.mcdev.asset.PlatformAssets
+import com.intellij.openapi.fileTypes.LanguageFileType
+
+object AtFileType : LanguageFileType(AtLanguage) {
+
+ override fun getName() = "Access Transformers"
+ override fun getDescription() = "Access transformers"
+ override fun getDefaultExtension() = ""
+ override fun getIcon() = PlatformAssets.MINECRAFT_ICON
+}
Index: src/main/kotlin/platform/minecraft/at/AtGotoDeclarationHandler.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/AtGotoDeclarationHandler.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/AtGotoDeclarationHandler.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,110 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at
+
+import com.demonwav.mcdev.facet.MinecraftFacet
+import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtClassName
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtEntry
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtFieldName
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtFuncName
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtFunction
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtTypes
+import com.demonwav.mcdev.util.findQualifiedClass
+import com.demonwav.mcdev.util.getPrimitiveType
+import com.demonwav.mcdev.util.parseClassDescriptor
+import com.intellij.codeInsight.navigation.actions.GotoDeclarationHandler
+import com.intellij.openapi.actionSystem.DataContext
+import com.intellij.openapi.editor.Editor
+import com.intellij.openapi.module.ModuleUtilCore
+import com.intellij.psi.JavaPsiFacade
+import com.intellij.psi.PsiElement
+import com.intellij.psi.search.GlobalSearchScope
+
+class AtGotoDeclarationHandler : GotoDeclarationHandler {
+ override fun getGotoDeclarationTargets(
+ sourceElement: PsiElement?,
+ offset: Int,
+ editor: Editor,
+ ): Array? {
+ if (sourceElement?.language !== AtLanguage) {
+ return null
+ }
+
+ val module = ModuleUtilCore.findModuleForPsiElement(sourceElement) ?: return null
+
+ val instance = MinecraftFacet.getInstance(module) ?: return null
+
+ val minecraftModule = instance.getModuleOfType(MinecraftModuleType) ?: return null
+
+ val srgMap = minecraftModule.mappingsManager?.mappingsNow ?: return null
+
+ return when {
+ sourceElement.node.treeParent.elementType === AtTypes.CLASS_NAME -> {
+ val className = sourceElement.parent as AtClassName
+ val classSrgToMcp = srgMap.getMappedClass(className.classNameText)
+ val psiClass = findQualifiedClass(sourceElement.project, classSrgToMcp) ?: return null
+ arrayOf(psiClass)
+ }
+ sourceElement.node.treeParent.elementType === AtTypes.FUNC_NAME -> {
+ val funcName = sourceElement.parent as AtFuncName
+ val function = funcName.parent as AtFunction
+ val entry = function.parent as AtEntry
+
+ val reference = srgMap.getMappedMethod(AtMemberReference.get(entry, function) ?: return null)
+ val member = reference.resolveMember(sourceElement.project) ?: return null
+ arrayOf(member)
+ }
+ sourceElement.node.treeParent.elementType === AtTypes.FIELD_NAME -> {
+ val fieldName = sourceElement.parent as AtFieldName
+ val entry = fieldName.parent as AtEntry
+
+ val reference = srgMap.getMappedField(AtMemberReference.get(entry, fieldName) ?: return null)
+ val member = reference.resolveMember(sourceElement.project) ?: return null
+ arrayOf(member)
+ }
+ sourceElement.node.elementType === AtTypes.CLASS_VALUE -> {
+ val className = srgMap.getMappedClass(parseClassDescriptor(sourceElement.text))
+ val psiClass = findQualifiedClass(sourceElement.project, className) ?: return null
+ arrayOf(psiClass)
+ }
+ sourceElement.node.elementType === AtTypes.PRIMITIVE -> {
+ val text = sourceElement.text
+ if (text.length != 1) {
+ return null
+ }
+
+ val type = getPrimitiveType(text[0]) ?: return null
+
+ val boxedType = type.boxedTypeName ?: return null
+
+ val psiClass = JavaPsiFacade.getInstance(sourceElement.project).findClass(
+ boxedType,
+ GlobalSearchScope.allScope(sourceElement.project),
+ ) ?: return null
+ arrayOf(psiClass)
+ }
+ else -> null
+ }
+ }
+
+ override fun getActionText(context: DataContext): String? = null
+}
Index: src/main/kotlin/platform/minecraft/at/AtLanguage.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/AtLanguage.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/AtLanguage.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,29 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at
+
+import com.intellij.lang.Language
+import java.io.Serial
+
+object AtLanguage : Language("Access Transformers") {
+ @Serial
+ private fun readResolve(): Any = AtLanguage
+}
Index: src/main/kotlin/platform/minecraft/at/AtLexerAdapter.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/AtLexerAdapter.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/AtLexerAdapter.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,26 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at
+
+import com.demonwav.mcdev.platform.minecraft.at.gen.AtLexer
+import com.intellij.lexer.FlexAdapter
+
+class AtLexerAdapter : FlexAdapter(AtLexer())
Index: src/main/kotlin/platform/minecraft/at/AtMemberReference.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/AtMemberReference.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/AtMemberReference.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,41 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at
+
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtEntry
+import com.demonwav.mcdev.util.MemberReference
+import com.intellij.psi.PsiElement
+
+object AtMemberReference {
+
+ fun get(entry: AtEntry, member: PsiElement): MemberReference? {
+ val memberText = member.text
+
+ val owner = entry.className?.text ?: return null
+
+ val pos = memberText.indexOf('(')
+ return if (pos != -1) {
+ MemberReference(memberText.substring(0, pos), memberText.substring(pos), owner)
+ } else {
+ MemberReference(memberText, null, owner)
+ }
+ }
+}
Index: src/main/kotlin/platform/minecraft/at/AtParserDefinition.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/AtParserDefinition.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/AtParserDefinition.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,66 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at
+
+import com.demonwav.mcdev.platform.minecraft.at.gen.parser.AtParser
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtTypes
+import com.intellij.lang.ASTNode
+import com.intellij.lang.Language
+import com.intellij.lang.ParserDefinition
+import com.intellij.openapi.project.Project
+import com.intellij.psi.FileViewProvider
+import com.intellij.psi.PsiElement
+import com.intellij.psi.tree.IElementType
+import com.intellij.psi.tree.IFileElementType
+import com.intellij.psi.tree.TokenSet
+
+class AtParserDefinition : ParserDefinition {
+
+ override fun createLexer(project: Project) = AtLexerAdapter()
+ override fun getCommentTokens() = TokenSets.COMMENTS
+ override fun getStringLiteralElements(): TokenSet = TokenSet.EMPTY
+ override fun createParser(project: Project) = AtParser()
+ override fun getFileNodeType() = TokenSets.FILE
+ override fun createFile(viewProvider: FileViewProvider) = AtFile(viewProvider)
+ override fun createElement(node: ASTNode): PsiElement = AtTypes.Factory.createElement(node)
+
+ override fun spaceExistenceTypeBetweenTokens(left: ASTNode, right: ASTNode) =
+ TokenSets.MAP.entries.firstOrNull { e -> left.elementType == e.key.first || right.elementType == e.key.second }?.value
+ ?: ParserDefinition.SpaceRequirements.MUST_NOT
+
+ object TokenSets {
+ val COMMENTS = TokenSet.create(AtTypes.COMMENT)
+
+ val FILE = IFileElementType(Language.findInstance(AtLanguage::class.java))
+
+ val MAP: Map, ParserDefinition.SpaceRequirements> = mapOf(
+ (AtTypes.KEYWORD to AtTypes.CLASS_NAME) to ParserDefinition.SpaceRequirements.MUST,
+ (AtTypes.CLASS_NAME to AtTypes.FIELD_NAME) to ParserDefinition.SpaceRequirements.MUST,
+ (AtTypes.CLASS_NAME to AtTypes.FUNCTION) to ParserDefinition.SpaceRequirements.MUST,
+ (AtTypes.CLASS_NAME to AtTypes.ASTERISK) to ParserDefinition.SpaceRequirements.MUST,
+ (AtTypes.FIELD_NAME to AtTypes.COMMENT) to ParserDefinition.SpaceRequirements.MUST,
+ (AtTypes.ASTERISK to AtTypes.COMMENT) to ParserDefinition.SpaceRequirements.MUST,
+ (AtTypes.COMMENT to AtTypes.KEYWORD) to ParserDefinition.SpaceRequirements.MUST_LINE_BREAK,
+ (AtTypes.COMMENT to AtTypes.COMMENT) to ParserDefinition.SpaceRequirements.MUST_LINE_BREAK,
+ (AtTypes.FUNCTION to AtTypes.COMMENT) to ParserDefinition.SpaceRequirements.MUST,
+ )
+ }
+}
Index: src/main/kotlin/platform/minecraft/at/AtSyntaxHighlighter.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/AtSyntaxHighlighter.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/AtSyntaxHighlighter.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,74 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at
+
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtTypes
+import com.intellij.openapi.editor.DefaultLanguageHighlighterColors
+import com.intellij.openapi.editor.HighlighterColors
+import com.intellij.openapi.editor.colors.TextAttributesKey
+import com.intellij.openapi.fileTypes.SyntaxHighlighterBase
+import com.intellij.psi.TokenType
+import com.intellij.psi.tree.IElementType
+
+class AtSyntaxHighlighter : SyntaxHighlighterBase() {
+
+ override fun getHighlightingLexer() = AtLexerAdapter()
+
+ override fun getTokenHighlights(tokenType: IElementType?): Array =
+ when (tokenType) {
+ AtTypes.KEYWORD_ELEMENT -> KEYWORD_KEYS
+ AtTypes.CLASS_NAME_ELEMENT -> CLASS_NAME_KEYS
+ AtTypes.CLASS_VALUE -> CLASS_VALUE_KEYS
+ AtTypes.NAME_ELEMENT -> ELEMENT_NAME_KEYS
+ AtTypes.ASTERISK_ELEMENT -> ASTERISK_KEYS
+ AtTypes.PRIMITIVE -> PRIMITIVE_KEYS
+ AtTypes.COMMENT -> COMMENT_KEYS
+ TokenType.BAD_CHARACTER -> BAD_CHARACTER_KEYS
+ else -> TextAttributesKey.EMPTY_ARRAY
+ }
+
+ companion object {
+ val KEYWORD = TextAttributesKey.createTextAttributesKey("AT_KEYWORD", DefaultLanguageHighlighterColors.KEYWORD)
+ val CLASS_NAME =
+ TextAttributesKey.createTextAttributesKey("AT_CLASS_NAME", DefaultLanguageHighlighterColors.STRING)
+ val CLASS_VALUE =
+ TextAttributesKey.createTextAttributesKey("AT_CLASS_VALUE", DefaultLanguageHighlighterColors.STATIC_METHOD)
+ val ELEMENT_NAME =
+ TextAttributesKey.createTextAttributesKey("AT_ELEMENT_NAME", DefaultLanguageHighlighterColors.STATIC_FIELD)
+ val ASTERISK =
+ TextAttributesKey.createTextAttributesKey("AT_ASTERISK", DefaultLanguageHighlighterColors.KEYWORD)
+ val PRIMITIVE =
+ TextAttributesKey.createTextAttributesKey("AT_PRIMITIVE", DefaultLanguageHighlighterColors.NUMBER)
+ val COMMENT =
+ TextAttributesKey.createTextAttributesKey("AT_COMMENT", DefaultLanguageHighlighterColors.LINE_COMMENT)
+ val BAD_CHARACTER =
+ TextAttributesKey.createTextAttributesKey("AT_BAD_CHARACTER", HighlighterColors.BAD_CHARACTER)
+
+ private val KEYWORD_KEYS = arrayOf(KEYWORD)
+ private val CLASS_NAME_KEYS = arrayOf(CLASS_NAME)
+ private val CLASS_VALUE_KEYS = arrayOf(CLASS_VALUE)
+ private val ELEMENT_NAME_KEYS = arrayOf(ELEMENT_NAME)
+ private val ASTERISK_KEYS = arrayOf(ASTERISK)
+ private val PRIMITIVE_KEYS = arrayOf(PRIMITIVE)
+ private val COMMENT_KEYS = arrayOf(COMMENT)
+ private val BAD_CHARACTER_KEYS = arrayOf(BAD_CHARACTER)
+ }
+}
Index: src/main/kotlin/platform/minecraft/at/AtSyntaxHighlighterFactory.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/AtSyntaxHighlighterFactory.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/AtSyntaxHighlighterFactory.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,29 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at
+
+import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.vfs.VirtualFile
+
+class AtSyntaxHighlighterFactory : SyntaxHighlighterFactory() {
+ override fun getSyntaxHighlighter(project: Project?, virtualFile: VirtualFile?) = AtSyntaxHighlighter()
+}
Index: src/main/kotlin/platform/minecraft/at/AtUsageInspection.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/AtUsageInspection.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/AtUsageInspection.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,80 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at
+
+import com.demonwav.mcdev.facet.MinecraftFacet
+import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtEntry
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtFieldName
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtFunction
+import com.intellij.codeInspection.LocalInspectionTool
+import com.intellij.codeInspection.ProblemHighlightType
+import com.intellij.codeInspection.ProblemsHolder
+import com.intellij.openapi.module.ModuleUtilCore
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiElementVisitor
+import com.intellij.psi.search.GlobalSearchScope
+import com.intellij.psi.search.searches.ReferencesSearch
+
+class AtUsageInspection : LocalInspectionTool() {
+
+ override fun getStaticDescription(): String {
+ return "The declared access transformer is never used"
+ }
+
+ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
+ return object : PsiElementVisitor() {
+ override fun visitElement(element: PsiElement) {
+ if (element !is AtEntry) {
+ return
+ }
+
+ val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return
+ val instance = MinecraftFacet.getInstance(module) ?: return
+ val minecraftModule = instance.getModuleOfType(MinecraftModuleType) ?: return
+ val srgMap = minecraftModule.mappingsManager?.mappingsNow ?: return
+
+ val member = element.function ?: element.fieldName ?: return
+ val reference = AtMemberReference.get(element, member) ?: return
+
+ val psi = when (member) {
+ is AtFunction ->
+ reference.resolveMember(element.project) ?: srgMap.tryGetMappedMethod(reference)?.resolveMember(
+ element.project,
+ ) ?: return
+ is AtFieldName ->
+ reference.resolveMember(element.project)
+ ?: srgMap.tryGetMappedField(reference)?.resolveMember(element.project) ?: return
+ else ->
+ return
+ }
+
+ val query = ReferencesSearch.search(psi, GlobalSearchScope.projectScope(element.project))
+ query.findFirst()
+ ?: holder.registerProblem(
+ element,
+ "Access Transformer entry is never used",
+ ProblemHighlightType.LIKE_UNUSED_SYMBOL,
+ )
+ }
+ }
+ }
+}
Index: src/main/kotlin/platform/minecraft/at/completion/AtCompletionContributor.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/completion/AtCompletionContributor.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/completion/AtCompletionContributor.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,356 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.completion
+
+import com.demonwav.mcdev.facet.MinecraftFacet
+import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType
+import com.demonwav.mcdev.platform.minecraft.at.AtElementFactory
+import com.demonwav.mcdev.platform.minecraft.at.AtLanguage
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtEntry
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtFieldName
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtFunction
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtTypes
+import com.demonwav.mcdev.util.anonymousClasses
+import com.demonwav.mcdev.util.fullQualifiedName
+import com.demonwav.mcdev.util.getSimilarity
+import com.demonwav.mcdev.util.localClasses
+import com.demonwav.mcdev.util.nameAndParameterTypes
+import com.demonwav.mcdev.util.qualifiedMemberReference
+import com.demonwav.mcdev.util.simpleQualifiedMemberReference
+import com.intellij.codeInsight.completion.CompletionContributor
+import com.intellij.codeInsight.completion.CompletionParameters
+import com.intellij.codeInsight.completion.CompletionResultSet
+import com.intellij.codeInsight.completion.CompletionType
+import com.intellij.codeInsight.completion.CompletionUtil
+import com.intellij.codeInsight.completion.PrioritizedLookupElement
+import com.intellij.codeInsight.lookup.LookupElementBuilder
+import com.intellij.openapi.module.ModuleUtilCore
+import com.intellij.patterns.PlatformPatterns.elementType
+import com.intellij.patterns.PlatformPatterns.psiElement
+import com.intellij.patterns.PsiElementPattern
+import com.intellij.psi.JavaPsiFacade
+import com.intellij.psi.PsiDocumentManager
+import com.intellij.psi.PsiElement
+import com.intellij.psi.search.GlobalSearchScope
+import com.intellij.psi.search.PsiShortNamesCache
+import com.intellij.psi.tree.IElementType
+import com.intellij.psi.tree.TokenSet
+import com.intellij.psi.util.PsiUtilCore
+import com.intellij.util.PlatformIcons
+
+class AtCompletionContributor : CompletionContributor() {
+
+ override fun fillCompletionVariants(parameters: CompletionParameters, result: CompletionResultSet) {
+ if (parameters.completionType != CompletionType.BASIC) {
+ return
+ }
+
+ val position = parameters.position
+ if (!PsiUtilCore.findLanguageFromElement(position).isKindOf(AtLanguage)) {
+ return
+ }
+
+ val parent = position.parent
+
+ val parentText = parent.text ?: return
+ if (parentText.length < CompletionUtil.DUMMY_IDENTIFIER.length) {
+ return
+ }
+ val text = parentText.substring(0, parentText.length - CompletionUtil.DUMMY_IDENTIFIER.length)
+
+ when {
+ Const.AFTER_KEYWORD.accepts(parent) -> handleAtClassName(text, parent, result)
+ Const.AFTER_CLASS_NAME.accepts(parent) -> handleAtName(text, parent, result)
+ Const.AFTER_NEWLINE.accepts(parent) -> handleNewLine(text, result)
+ }
+ }
+
+ private fun handleAtClassName(text: String, element: PsiElement, result: CompletionResultSet) {
+ if (text.isEmpty()) {
+ return
+ }
+
+ val currentPackage = text.substringBeforeLast('.', "")
+ val beginning = text.substringAfterLast('.', "")
+
+ if (currentPackage == "" || beginning == "") {
+ return
+ }
+
+ val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return
+ val scope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module)
+ val project = module.project
+
+ // Short name completion
+ if (!text.contains('.')) {
+ val kindResult = result.withPrefixMatcher(KindPrefixMatcher(text))
+ val cache = PsiShortNamesCache.getInstance(project)
+
+ var counter = 0
+ for (className in cache.allClassNames) {
+ if (!className.contains(beginning, ignoreCase = true)) {
+ continue
+ }
+
+ if (counter++ > 1000) {
+ break // Prevent insane CPU usage
+ }
+
+ val classesByName = cache.getClassesByName(className, scope)
+ for (classByName in classesByName) {
+ val name = classByName.fullQualifiedName ?: continue
+ kindResult.addElement(
+ PrioritizedLookupElement.withPriority(
+ LookupElementBuilder.create(name).withIcon(PlatformIcons.CLASS_ICON),
+ 1.0 + name.getValue(beginning),
+ ),
+ )
+ }
+ }
+ }
+
+ // Anonymous and inner class completion
+ if (text.contains('$')) {
+ val currentClass =
+ JavaPsiFacade.getInstance(project).findClass(text.substringBeforeLast('$'), scope) ?: return
+
+ for (innerClass in currentClass.allInnerClasses) {
+ if (innerClass.name?.contains(beginning.substringAfterLast('$'), ignoreCase = true) != true) {
+ continue
+ }
+
+ val name = innerClass.fullQualifiedName ?: continue
+ result.addElement(
+ PrioritizedLookupElement.withPriority(
+ LookupElementBuilder.create(name).withIcon(PlatformIcons.CLASS_ICON),
+ 1.0,
+ ),
+ )
+ }
+
+ for (anonClass in currentClass.anonymousClasses) {
+ val name = anonClass.fullQualifiedName ?: continue
+ result.addElement(
+ PrioritizedLookupElement.withPriority(
+ LookupElementBuilder.create(name).withIcon(PlatformIcons.CLASS_ICON),
+ 1.0,
+ ),
+ )
+ }
+
+ for (localClass in currentClass.localClasses) {
+ val name = localClass.fullQualifiedName ?: continue
+ result.addElement(
+ PrioritizedLookupElement.withPriority(
+ LookupElementBuilder.create(name).withIcon(PlatformIcons.CLASS_ICON),
+ 1.0,
+ ),
+ )
+ }
+
+ return
+ }
+
+ val psiPackage = JavaPsiFacade.getInstance(project).findPackage(currentPackage) ?: return
+
+ // Classes in package completion
+ val used = mutableSetOf()
+ for (psiClass in psiPackage.classes) {
+ if (psiClass.name == null) {
+ continue
+ }
+
+ if (!psiClass.name!!.contains(beginning, ignoreCase = true) || psiClass.name == "package-info") {
+ continue
+ }
+
+ if (!used.add(psiClass.name!!)) {
+ continue
+ }
+
+ val name = psiClass.fullQualifiedName ?: continue
+ result.addElement(
+ PrioritizedLookupElement.withPriority(
+ LookupElementBuilder.create(name).withIcon(PlatformIcons.CLASS_ICON),
+ 1.0,
+ ),
+ )
+ }
+ used.clear() // help GC
+
+ // Packages in package completion
+ for (subPackage in psiPackage.subPackages) {
+ if (subPackage.name == null) {
+ continue
+ }
+
+ if (!subPackage.name!!.contains(beginning, ignoreCase = true)) {
+ continue
+ }
+
+ val name = subPackage.qualifiedName
+ result.addElement(
+ PrioritizedLookupElement.withPriority(
+ LookupElementBuilder.create(name).withIcon(PlatformIcons.PACKAGE_ICON),
+ 0.0,
+ ),
+ )
+ }
+ }
+
+ private fun handleAtName(text: String, memberName: PsiElement, result: CompletionResultSet) {
+ if (memberName !is AtFieldName) {
+ return
+ }
+
+ val entry = memberName.parent as? AtEntry ?: return
+
+ val entryClass = entry.className?.classNameValue ?: return
+
+ val module = ModuleUtilCore.findModuleForPsiElement(memberName) ?: return
+ val project = module.project
+
+ val minecraftModule = MinecraftFacet.getInstance(module)?.getModuleOfType(MinecraftModuleType) ?: return
+
+ val srgMap = minecraftModule.mappingsManager?.mappingsNow ?: return
+
+ val srgResult = result.withPrefixMatcher(SrgPrefixMatcher(text))
+
+ for (field in entryClass.fields) {
+ if (!field.name.contains(text, ignoreCase = true)) {
+ continue
+ }
+
+ val memberReference = srgMap.getIntermediaryField(field) ?: field.simpleQualifiedMemberReference
+ srgResult.addElement(
+ PrioritizedLookupElement.withPriority(
+ LookupElementBuilder
+ .create(field.name)
+ .withIcon(PlatformIcons.FIELD_ICON)
+ .withTailText(" (${memberReference.name})", true)
+ .withInsertHandler handler@{ context, _ ->
+ val currentElement = context.file.findElementAt(context.startOffset) ?: return@handler
+ currentElement.replace(
+ AtElementFactory.createFieldName(
+ context.project,
+ memberReference.name,
+ ),
+ )
+
+ // TODO: Fix visibility decrease
+ PsiDocumentManager.getInstance(context.project)
+ .doPostponedOperationsAndUnblockDocument(context.document)
+ val comment = " # ${field.name}"
+ context.document.insertString(context.editor.caretModel.offset, comment)
+ context.editor.caretModel.moveCaretRelatively(comment.length, 0, false, false, false)
+ },
+ 1.0,
+ ),
+ )
+ }
+
+ for (method in entryClass.methods) {
+ if (!method.name.contains(text, ignoreCase = true)) {
+ continue
+ }
+
+ val memberReference = srgMap.getIntermediaryMethod(method) ?: method.qualifiedMemberReference
+ srgResult.addElement(
+ PrioritizedLookupElement.withPriority(
+ LookupElementBuilder.create(method.nameAndParameterTypes)
+ .withIcon(PlatformIcons.METHOD_ICON)
+ .withTailText(" (${memberReference.name})", true)
+ .withInsertHandler handler@{ context, _ ->
+ var currentElement = context.file.findElementAt(context.startOffset) ?: return@handler
+ var counter = 0
+ while (currentElement !is AtFieldName && currentElement !is AtFunction) {
+ currentElement = currentElement.parent
+ if (counter++ > 3) {
+ break
+ }
+ }
+
+ // Hopefully this won't happen lol
+ if (currentElement !is AtFieldName && currentElement !is AtFunction) {
+ return@handler
+ }
+
+ if (currentElement is AtFieldName) {
+ // get rid of the bad parameters
+ val parent = currentElement.parent
+ val children =
+ parent.node.getChildren(TokenSet.create(AtTypes.OPEN_PAREN, AtTypes.CLOSE_PAREN))
+ if (children.size == 2) {
+ parent.node.removeRange(children[0], children[1].treeNext)
+ }
+ }
+
+ currentElement.replace(
+ AtElementFactory.createFunction(
+ project,
+ memberReference.name + memberReference.descriptor,
+ ),
+ )
+
+ // TODO: Fix visibility decreases
+ PsiDocumentManager.getInstance(context.project)
+ .doPostponedOperationsAndUnblockDocument(context.document)
+ val comment = " # ${method.name}"
+ context.document.insertString(context.editor.caretModel.offset, comment)
+ context.editor.caretModel.moveCaretRelatively(comment.length, 0, false, false, false)
+ },
+ 0.0,
+ ),
+ )
+ }
+ }
+
+ private fun handleNewLine(text: String, result: CompletionResultSet) {
+ for (keyword in AtElementFactory.Keyword.softMatch(text)) {
+ result.addElement(LookupElementBuilder.create(keyword.text))
+ }
+ }
+
+ /**
+ * This helps order the (hopefully) most relevant entries in the short name completion
+ */
+ private fun String?.getValue(text: String): Int {
+ if (this == null) {
+ return 0
+ }
+
+ // Push net.minecraft{forge} classes up to the top
+ val packageBonus = if (this.startsWith("net.minecraft")) 10_000 else 0
+
+ val thisName = this.substringAfterLast('.')
+
+ return thisName.getSimilarity(text, packageBonus)
+ }
+
+ object Const {
+ private fun after(type: IElementType): PsiElementPattern.Capture =
+ psiElement().afterSibling(psiElement().withElementType(elementType().oneOf(type)))
+
+ val AFTER_KEYWORD = after(AtTypes.KEYWORD)
+ val AFTER_CLASS_NAME = after(AtTypes.CLASS_NAME)
+ val AFTER_NEWLINE = after(AtTypes.CRLF)
+ }
+}
Index: src/main/kotlin/platform/minecraft/at/completion/AtTypedHandlerDelegate.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/completion/AtTypedHandlerDelegate.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/completion/AtTypedHandlerDelegate.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,36 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.completion
+
+import com.demonwav.mcdev.platform.minecraft.at.AtLanguage
+import com.intellij.codeInsight.editorActions.TypedHandlerDelegate
+import com.intellij.openapi.editor.Editor
+import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiFile
+
+class AtTypedHandlerDelegate : TypedHandlerDelegate() {
+ override fun checkAutoPopup(charTyped: Char, project: Project, editor: Editor, file: PsiFile): Result {
+ if (file.language == AtLanguage && charTyped == '$') {
+ return Result.CONTINUE
+ }
+ return super.checkAutoPopup(charTyped, project, editor, file)
+ }
+}
Index: src/main/kotlin/platform/minecraft/at/completion/KindPrefixMatcher.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/completion/KindPrefixMatcher.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/completion/KindPrefixMatcher.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,32 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.completion
+
+import com.intellij.codeInsight.completion.PrefixMatcher
+import com.intellij.codeInsight.lookup.LookupElement
+
+class KindPrefixMatcher(prefix: String) : PrefixMatcher(prefix) {
+ override fun prefixMatches(name: String) = true
+ override fun cloneWithPrefix(prefix: String) = KindPrefixMatcher(prefix)
+
+ override fun prefixMatches(element: LookupElement) =
+ element.lookupString.contains(prefix, ignoreCase = true)
+}
Index: src/main/kotlin/platform/minecraft/at/completion/SrgPrefixMatcher.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/completion/SrgPrefixMatcher.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/completion/SrgPrefixMatcher.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,33 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.completion
+
+import com.intellij.codeInsight.completion.PrefixMatcher
+import com.intellij.codeInsight.lookup.LookupElement
+
+class SrgPrefixMatcher(prefix: String) : PrefixMatcher(prefix) {
+ override fun prefixMatches(name: String) = true
+ override fun cloneWithPrefix(prefix: String) = SrgPrefixMatcher(prefix)
+
+ override fun prefixMatches(element: LookupElement): Boolean {
+ return element.lookupString.contains(myPrefix, ignoreCase = true)
+ }
+}
Index: src/main/kotlin/platform/minecraft/at/psi/AtElement.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/AtElement.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/AtElement.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,25 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi
+
+import com.intellij.psi.PsiElement
+
+interface AtElement : PsiElement
Index: src/main/kotlin/platform/minecraft/at/psi/AtElementType.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/AtElementType.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/AtElementType.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,27 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi
+
+import com.demonwav.mcdev.platform.minecraft.at.AtLanguage
+import com.intellij.psi.tree.IElementType
+import org.jetbrains.annotations.NonNls
+
+class AtElementType(@NonNls debugName: String) : IElementType(debugName, AtLanguage)
Index: src/main/kotlin/platform/minecraft/at/psi/AtMixinUtil.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/AtMixinUtil.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/AtMixinUtil.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,50 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi
+
+import com.demonwav.mcdev.util.findQualifiedClass
+import com.demonwav.mcdev.util.getPrimitiveWrapperClass
+import com.demonwav.mcdev.util.parseClassDescriptor
+import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiClass
+import com.intellij.psi.search.GlobalSearchScope
+
+private val bracket = Regex("\\[")
+
+fun getClassFromString(text: String?, project: Project): PsiClass? {
+ var newText = text ?: return null
+
+ // We don't care about arrays
+ newText = newText.replace(bracket, "")
+
+ val scope = GlobalSearchScope.allScope(project)
+
+ if (newText.startsWith("L")) {
+ val finalText = parseClassDescriptor(newText)
+ return findQualifiedClass(project, finalText, scope)
+ }
+
+ if (newText.length != 1 || !"BCDFIJSZ".contains(newText[0])) {
+ return null
+ }
+
+ return getPrimitiveWrapperClass(newText[0], project)
+}
Index: src/main/kotlin/platform/minecraft/at/psi/AtTokenType.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/AtTokenType.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/AtTokenType.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,27 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi
+
+import com.demonwav.mcdev.platform.minecraft.at.AtLanguage
+import com.intellij.psi.tree.IElementType
+import org.jetbrains.annotations.NonNls
+
+class AtTokenType(@NonNls debugName: String) : IElementType(debugName, AtLanguage)
Index: src/main/kotlin/platform/minecraft/at/psi/mixins/AtArgumentMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/mixins/AtArgumentMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/mixins/AtArgumentMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,35 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi.mixins
+
+import com.demonwav.mcdev.platform.minecraft.at.psi.AtElement
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiElement
+
+interface AtArgumentMixin : AtElement {
+
+ val classValue: PsiElement?
+ val primitive: PsiElement?
+ val argumentClass: PsiClass?
+ val argumentText: String
+
+ fun setArgument(argument: String)
+}
Index: src/main/kotlin/platform/minecraft/at/psi/mixins/AtClassNameMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/mixins/AtClassNameMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/mixins/AtClassNameMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,34 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi.mixins
+
+import com.demonwav.mcdev.platform.minecraft.at.psi.AtElement
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiElement
+
+interface AtClassNameMixin : AtElement {
+
+ val classNameElement: PsiElement
+ val classNameValue: PsiClass?
+ val classNameText: String
+
+ fun setClassName(className: String)
+}
Index: src/main/kotlin/platform/minecraft/at/psi/mixins/AtEntryMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/mixins/AtEntryMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/mixins/AtEntryMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,55 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi.mixins
+
+import com.demonwav.mcdev.platform.minecraft.at.AtElementFactory
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtAsterisk
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtClassName
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtFieldName
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtFunction
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtKeyword
+import com.demonwav.mcdev.platform.minecraft.at.psi.AtElement
+
+interface AtEntryMixin : AtElement {
+
+ val asterisk: AtAsterisk?
+ val className: AtClassName
+ val fieldName: AtFieldName?
+ val function: AtFunction?
+ val keyword: AtKeyword
+
+ fun setEntry(entry: String)
+ fun setKeyword(keyword: AtElementFactory.Keyword)
+ fun setClassName(className: String)
+ fun setFieldName(fieldName: String)
+ fun setFunction(function: String)
+ fun setAsterisk()
+
+ fun replaceMember(element: AtElement) {
+ // One of these must be true
+ when {
+ fieldName != null -> fieldName!!.replace(element)
+ function != null -> function!!.replace(element)
+ asterisk != null -> asterisk!!.replace(element)
+ else -> addAfter(className, element)
+ }
+ }
+}
Index: src/main/kotlin/platform/minecraft/at/psi/mixins/AtFieldNameMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/mixins/AtFieldNameMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/mixins/AtFieldNameMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,32 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi.mixins
+
+import com.demonwav.mcdev.platform.minecraft.at.psi.AtElement
+import com.intellij.psi.PsiElement
+
+interface AtFieldNameMixin : AtElement {
+
+ val nameElement: PsiElement
+ val fieldNameText: String
+
+ fun setFieldName(fieldName: String)
+}
Index: src/main/kotlin/platform/minecraft/at/psi/mixins/AtFuncNameMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/mixins/AtFuncNameMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/mixins/AtFuncNameMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,32 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi.mixins
+
+import com.demonwav.mcdev.platform.minecraft.at.psi.AtElement
+import com.intellij.psi.PsiElement
+
+interface AtFuncNameMixin : AtElement {
+
+ val nameElement: PsiElement
+ val funcNameText: String
+
+ fun setFuncName(funcName: String)
+}
Index: src/main/kotlin/platform/minecraft/at/psi/mixins/AtFunctionMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/mixins/AtFunctionMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/mixins/AtFunctionMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,37 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi.mixins
+
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtArgument
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtFuncName
+import com.demonwav.mcdev.platform.minecraft.at.gen.psi.AtReturnValue
+import com.demonwav.mcdev.platform.minecraft.at.psi.AtElement
+
+interface AtFunctionMixin : AtElement {
+
+ val argumentList: List
+ val funcName: AtFuncName
+ val returnValue: AtReturnValue
+
+ fun setArgumentList(argumentList: String)
+ fun setReturnValue(returnValue: String)
+ fun setFunction(function: String)
+}
Index: src/main/kotlin/platform/minecraft/at/psi/mixins/AtKeywordMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/mixins/AtKeywordMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/mixins/AtKeywordMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,33 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi.mixins
+
+import com.demonwav.mcdev.platform.minecraft.at.AtElementFactory
+import com.demonwav.mcdev.platform.minecraft.at.psi.AtElement
+import com.intellij.psi.PsiElement
+
+interface AtKeywordMixin : AtElement {
+
+ val keywordElement: PsiElement
+ val keywordValue: AtElementFactory.Keyword
+
+ fun setKeyword(keyword: AtElementFactory.Keyword)
+}
Index: src/main/kotlin/platform/minecraft/at/psi/mixins/AtReturnValueMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/mixins/AtReturnValueMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/mixins/AtReturnValueMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,35 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi.mixins
+
+import com.demonwav.mcdev.platform.minecraft.at.psi.AtElement
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiElement
+
+interface AtReturnValueMixin : AtElement {
+
+ val classValue: PsiElement?
+ val primitive: PsiElement?
+ val returnValueClass: PsiClass?
+ val returnValueText: String
+
+ fun setReturnValue(returnValue: String)
+}
Index: src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtArgumentImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtArgumentImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtArgumentImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,40 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.at.AtElementFactory
+import com.demonwav.mcdev.platform.minecraft.at.psi.getClassFromString
+import com.demonwav.mcdev.platform.minecraft.at.psi.mixins.AtArgumentMixin
+import com.intellij.extapi.psi.ASTWrapperPsiElement
+import com.intellij.lang.ASTNode
+
+abstract class AtArgumentImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), AtArgumentMixin {
+
+ override val argumentClass
+ get() = getClassFromString(argumentText, project)
+
+ override val argumentText: String
+ get() = classValue?.text ?: primitive!!.text
+
+ override fun setArgument(argument: String) {
+ replace(AtElementFactory.createArgument(project, argument))
+ }
+}
Index: src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtClassNameImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtClassNameImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtClassNameImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,40 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.at.AtElementFactory
+import com.demonwav.mcdev.platform.minecraft.at.psi.mixins.AtClassNameMixin
+import com.demonwav.mcdev.util.findQualifiedClass
+import com.intellij.extapi.psi.ASTWrapperPsiElement
+import com.intellij.lang.ASTNode
+
+abstract class AtClassNameImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), AtClassNameMixin {
+
+ override val classNameValue
+ get() = findQualifiedClass(project, classNameText)
+
+ override val classNameText: String
+ get() = classNameElement.text
+
+ override fun setClassName(className: String) {
+ replace(AtElementFactory.createClassName(project, className))
+ }
+}
Index: src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtEntryImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtEntryImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtEntryImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,56 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.at.AtElementFactory
+import com.demonwav.mcdev.platform.minecraft.at.psi.mixins.AtEntryMixin
+import com.intellij.extapi.psi.ASTWrapperPsiElement
+import com.intellij.lang.ASTNode
+
+abstract class AtEntryImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), AtEntryMixin {
+
+ override fun setEntry(entry: String) {
+ replace(AtElementFactory.createEntry(project, entry))
+ }
+
+ override fun setKeyword(keyword: AtElementFactory.Keyword) {
+ this.keyword.replace(AtElementFactory.createKeyword(project, keyword))
+ }
+
+ override fun setClassName(className: String) {
+ this.className.replace(AtElementFactory.createClassName(project, className))
+ }
+
+ override fun setFieldName(fieldName: String) {
+ val newField = AtElementFactory.createFieldName(project, fieldName)
+ replaceMember(newField)
+ }
+
+ override fun setFunction(function: String) {
+ val atFunction = AtElementFactory.createFunction(project, function)
+ replaceMember(atFunction)
+ }
+
+ override fun setAsterisk() {
+ val asterisk = AtElementFactory.createAsterisk(project)
+ replaceMember(asterisk)
+ }
+}
Index: src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtFieldNameImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtFieldNameImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtFieldNameImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,36 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.at.AtElementFactory
+import com.demonwav.mcdev.platform.minecraft.at.psi.mixins.AtFieldNameMixin
+import com.intellij.extapi.psi.ASTWrapperPsiElement
+import com.intellij.lang.ASTNode
+
+abstract class AtFieldNameImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), AtFieldNameMixin {
+
+ override fun setFieldName(fieldName: String) {
+ replace(AtElementFactory.createFieldName(project, fieldName))
+ }
+
+ override val fieldNameText: String
+ get() = nameElement.text
+}
Index: src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtFuncNameImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtFuncNameImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtFuncNameImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,36 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.at.AtElementFactory
+import com.demonwav.mcdev.platform.minecraft.at.psi.mixins.AtFuncNameMixin
+import com.intellij.extapi.psi.ASTWrapperPsiElement
+import com.intellij.lang.ASTNode
+
+abstract class AtFuncNameImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), AtFuncNameMixin {
+
+ override fun setFuncName(funcName: String) {
+ replace(AtElementFactory.createFuncName(project, funcName))
+ }
+
+ override val funcNameText: String
+ get() = nameElement.text
+}
Index: src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtFunctionImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtFunctionImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtFunctionImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,45 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.at.AtElementFactory
+import com.demonwav.mcdev.platform.minecraft.at.psi.mixins.AtFunctionMixin
+import com.intellij.extapi.psi.ASTWrapperPsiElement
+import com.intellij.lang.ASTNode
+
+abstract class AtFunctionImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), AtFunctionMixin {
+
+ override fun setArgumentList(argumentList: String) {
+ val funcName = funcName.nameElement.text
+ this.argumentList.forEach { it.delete() }
+
+ val returnValue = returnValue.classValue!!.text
+ replace(AtElementFactory.createFunction(project, "$funcName($argumentList)$returnValue"))
+ }
+
+ override fun setReturnValue(returnValue: String) {
+ this.returnValue.replace(AtElementFactory.createReturnValue(project, returnValue))
+ }
+
+ override fun setFunction(function: String) {
+ replace(AtElementFactory.createFunction(project, function))
+ }
+}
Index: src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtKeywordImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtKeywordImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtKeywordImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,36 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.at.AtElementFactory
+import com.demonwav.mcdev.platform.minecraft.at.psi.mixins.AtKeywordMixin
+import com.intellij.extapi.psi.ASTWrapperPsiElement
+import com.intellij.lang.ASTNode
+
+abstract class AtKeywordImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), AtKeywordMixin {
+
+ override val keywordValue
+ get() = AtElementFactory.Keyword.match(keywordElement.text)!!
+
+ override fun setKeyword(keyword: AtElementFactory.Keyword) {
+ replace(AtElementFactory.createKeyword(project, keyword))
+ }
+}
Index: src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtReturnValueImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtReturnValueImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/at/psi/mixins/impl/AtReturnValueImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,41 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.at.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.at.AtElementFactory
+import com.demonwav.mcdev.platform.minecraft.at.psi.getClassFromString
+import com.demonwav.mcdev.platform.minecraft.at.psi.mixins.AtReturnValueMixin
+import com.intellij.extapi.psi.ASTWrapperPsiElement
+import com.intellij.lang.ASTNode
+import com.intellij.psi.PsiClass
+
+abstract class AtReturnValueImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), AtReturnValueMixin {
+
+ override val returnValueClass: PsiClass?
+ get() = getClassFromString(returnValueText, project)
+
+ override val returnValueText: String
+ get() = primitive?.text ?: classValue!!.text
+
+ override fun setReturnValue(returnValue: String) {
+ replace(AtElementFactory.createReturnValue(project, returnValue))
+ }
+}
Index: src/main/kotlin/platform/minecraft/ct/CtAnnotator.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/CtAnnotator.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/CtAnnotator.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,112 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct
+
+import com.demonwav.mcdev.platform.fabric.util.FabricConstants
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtAccess
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtClassLiteral
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtExtendEnumEntry
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtFieldLiteral
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtHeader
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtItfEntry
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtMethodLiteral
+import com.demonwav.mcdev.util.childOfType
+import com.google.common.collect.HashMultimap
+import com.google.common.collect.Multimaps
+import com.intellij.lang.annotation.AnnotationHolder
+import com.intellij.lang.annotation.Annotator
+import com.intellij.lang.annotation.HighlightSeverity
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiWhiteSpace
+import com.intellij.psi.util.PsiTreeUtil
+
+class CtAnnotator : Annotator {
+
+ override fun annotate(element: PsiElement, holder: AnnotationHolder) {
+ val effectiveVersion by lazy { element.containingFile?.childOfType()?.effectiveVersion ?: 1 }
+
+ when (element) {
+ is CtAccess -> {
+ val access = element.text
+ val target = PsiTreeUtil.skipSiblingsForward(element, PsiWhiteSpace::class.java)?.text
+ if (!TokenSets.compatibleByAccessMap.get(access).contains(target)) {
+ holder.newAnnotation(HighlightSeverity.ERROR, "Access '$access' cannot be used on '$target'").create()
+ }
+
+ if (element.accessElement.text.startsWith("transitive-") && effectiveVersion < 2) {
+ holder.newAnnotation(HighlightSeverity.ERROR, "Transitive accesses were introduced in v2").create()
+ }
+ }
+ is CtItfEntry -> {
+ if (effectiveVersion < 3) {
+ holder.newAnnotation(HighlightSeverity.ERROR, "Interface injection was introduced in ClassTweaker v1")
+ .range(element.firstChild)
+ .create()
+ }
+ }
+ is CtExtendEnumEntry -> {
+ if (effectiveVersion < 4) {
+ holder.newAnnotation(HighlightSeverity.ERROR, "Enum extension was introduced in ClassTweaker v2")
+ .range(element.firstChild)
+ .create()
+ }
+ }
+ is CtFieldLiteral, is CtMethodLiteral, is CtClassLiteral -> {
+ val target = element.text
+ val access = PsiTreeUtil.skipSiblingsBackward(element, PsiWhiteSpace::class.java)?.text
+ if (!TokenSets.compatibleByTargetMap.get(target).contains(access)) {
+ holder.newAnnotation(HighlightSeverity.ERROR, "'$target' cannot be used with '$access'").create()
+ }
+ }
+ is CtHeader -> {
+ val version = element.effectiveVersion
+ val versionElement = element.versionElement ?: return
+ when (element.nameString) {
+ "accessWidener" -> {
+ if (version == null || version < 1 || version > 2) {
+ holder.newAnnotation(HighlightSeverity.ERROR, "Unrecognized access widener version").range(versionElement).create()
+ }
+ }
+ "classTweaker" -> {
+ if (version == null || version < 3 || version > FabricConstants.CLASS_TWEAKER_VERSION) {
+ holder.newAnnotation(HighlightSeverity.ERROR, "Unrecognized class tweaker version").range(versionElement).create()
+ }
+ }
+ }
+ }
+ }
+ }
+
+ object TokenSets {
+ val compatibleByAccessMap = HashMultimap.create()
+ val compatibleByTargetMap = HashMultimap.create()
+
+ init {
+ compatibleByAccessMap.putAll("accessible", setOf("class", "method", "field"))
+ compatibleByAccessMap.putAll("transitive-accessible", setOf("class", "method", "field"))
+ compatibleByAccessMap.putAll("extendable", setOf("class", "method"))
+ compatibleByAccessMap.putAll("transitive-extendable", setOf("class", "method"))
+ compatibleByAccessMap.putAll("mutable", setOf("field"))
+ compatibleByAccessMap.putAll("transitive-mutable", setOf("field"))
+ Multimaps.invertFrom(compatibleByAccessMap, compatibleByTargetMap)
+ }
+ }
+}
Index: src/main/kotlin/platform/minecraft/ct/CtColorSettingsPage.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/CtColorSettingsPage.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/CtColorSettingsPage.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,75 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct
+
+import com.demonwav.mcdev.asset.PlatformAssets
+import com.intellij.openapi.editor.colors.TextAttributesKey
+import com.intellij.openapi.options.colors.AttributesDescriptor
+import com.intellij.openapi.options.colors.ColorDescriptor
+import com.intellij.openapi.options.colors.ColorSettingsPage
+
+class CtColorSettingsPage : ColorSettingsPage {
+
+ override fun getIcon() = PlatformAssets.MINECRAFT_ICON
+ override fun getHighlighter() = CtSyntaxHighlighter()
+ override fun getDemoText() =
+ $$"""
+ classTweaker v2 named
+
+ # https://docs.fabricmc.net/develop/class-tweakers/
+
+ extendable class net/minecraft/world/item/crafting/Ingredient
+ transitive-extendable class net/minecraft/world/item/crafting/Ingredient
+ accessible class net/minecraft/world/entity/monster/Phantom$AttackPhase
+ transitive-accessible class net/minecraft/world/entity/monster/Phantom$AttackPhase
+ extendable method net/minecraft/server/players/IpBanList getIpFromAddress (Ljava/net/SocketAddress;)Ljava/lang/String;
+ extendable method net/minecraft/world/item/crafting/Ingredient (Ljava/util/stream/Stream;)V
+ accessible field net/minecraft/world/item/crafting/Ingredient values [Lnet/minecraft/world/item/crafting/Ingredient$Value;
+ inject-interface net/minecraft/world/level/block/Block com/example/MyBlockInterface
+ transitive-inject-interface net/minecraft/world/level/block/Block com/example/MyTransitiveBlockInterface
+ extend-enum net/minecraft/client/gui/Gui$HeartType MYMOD_HEART_TYPE
+ transitive-extend-enum net/minecraft/client/gui/Gui$HeartType MYMOD_TRANSITIVE_HEART_TYPE
+ """.trimIndent()
+
+ override fun getAdditionalHighlightingTagToDescriptorMap(): Map? = null
+ override fun getAttributeDescriptors() = Const.DESCRIPTORS
+ override fun getColorDescriptors(): Array = ColorDescriptor.EMPTY_ARRAY
+ override fun getDisplayName() = "Class Tweakers"
+
+ private object Const {
+ val DESCRIPTORS = arrayOf(
+ AttributesDescriptor("Header name", CtSyntaxHighlighter.HEADER_NAME),
+ AttributesDescriptor("Header namespace", CtSyntaxHighlighter.HEADER_NAMESPACE),
+ AttributesDescriptor("Access", CtSyntaxHighlighter.ACCESS),
+ AttributesDescriptor("Inject interface", CtSyntaxHighlighter.INJECT_INTERFACE),
+ AttributesDescriptor("Extend enum", CtSyntaxHighlighter.EXTEND_ENUM),
+ AttributesDescriptor("Class element", CtSyntaxHighlighter.CLASS_ELEMENT),
+ AttributesDescriptor("Method element", CtSyntaxHighlighter.METHOD_ELEMENT),
+ AttributesDescriptor("Field element", CtSyntaxHighlighter.FIELD_ELEMENT),
+ AttributesDescriptor("Class name", CtSyntaxHighlighter.CLASS_NAME),
+ AttributesDescriptor("Member name", CtSyntaxHighlighter.MEMBER_NAME),
+ AttributesDescriptor("Class value", CtSyntaxHighlighter.CLASS_VALUE),
+ AttributesDescriptor("Primitive", CtSyntaxHighlighter.PRIMITIVE),
+ AttributesDescriptor("Type variable", CtSyntaxHighlighter.TYPE_VARIABLE),
+ AttributesDescriptor("Comment", CtSyntaxHighlighter.COMMENT),
+ )
+ }
+}
Index: src/main/kotlin/platform/minecraft/ct/CtCommenter.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/CtCommenter.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/CtCommenter.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,36 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct
+
+import com.intellij.lang.Commenter
+
+class CtCommenter : Commenter {
+
+ override fun getLineCommentPrefix() = "#"
+
+ override fun getBlockCommentPrefix(): String? = null
+
+ override fun getBlockCommentSuffix(): String? = null
+
+ override fun getCommentedBlockCommentPrefix(): String? = null
+
+ override fun getCommentedBlockCommentSuffix(): String? = null
+}
Index: src/main/kotlin/platform/minecraft/ct/CtCompletionContributor.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/CtCompletionContributor.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/CtCompletionContributor.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,149 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct
+
+import com.demonwav.mcdev.facet.MinecraftFacet
+import com.demonwav.mcdev.platform.fabric.FabricModuleType
+import com.demonwav.mcdev.platform.fabric.util.FabricConstants
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtTypes
+import com.demonwav.mcdev.util.findModule
+import com.intellij.codeInsight.completion.CodeCompletionHandlerBase
+import com.intellij.codeInsight.completion.CompletionContributor
+import com.intellij.codeInsight.completion.CompletionParameters
+import com.intellij.codeInsight.completion.CompletionProvider
+import com.intellij.codeInsight.completion.CompletionResultSet
+import com.intellij.codeInsight.completion.CompletionType
+import com.intellij.codeInsight.completion.InsertionContext
+import com.intellij.codeInsight.completion.PrioritizedLookupElement
+import com.intellij.codeInsight.lookup.LookupElementBuilder
+import com.intellij.openapi.application.runReadAction
+import com.intellij.patterns.PlatformPatterns
+import com.intellij.psi.PsiDocumentManager
+import com.intellij.psi.TokenType
+import com.intellij.psi.util.elementType
+import com.intellij.psi.util.prevLeaf
+import com.intellij.util.ProcessingContext
+
+class CtCompletionContributor : CompletionContributor() {
+ init {
+ extend(null, PlatformPatterns.psiElement(), CtHeaderCompletionProvider)
+ val whitespace = PlatformPatterns.psiElement(TokenType.WHITE_SPACE)
+ val namespacePattern = PlatformPatterns.psiElement()
+ .afterLeafSkipping(whitespace, PlatformPatterns.psiElement(CtTypes.HEADER_VERSION_ELEMENT))
+ extend(null, namespacePattern, CtNamespaceCompletionProvider)
+ val entryStartPattern = PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement(CtTypes.CRLF))
+ extend(null, entryStartPattern, CtEntryStartCompletionProvider)
+ val awTargetPattern = PlatformPatterns.psiElement()
+ .afterLeafSkipping(whitespace, PlatformPatterns.psiElement(CtTypes.ACCESS_ELEMENT))
+ extend(null, awTargetPattern, CtAwTargetCompletionProvider)
+ }
+}
+
+private fun insertWhitespace(context: InsertionContext) {
+ PsiDocumentManager.getInstance(context.project)
+ .doPostponedOperationsAndUnblockDocument(context.document)
+ context.document.insertString(context.editor.caretModel.offset, " ")
+ context.editor.caretModel.moveCaretRelatively(1, 0, false, false, false)
+ context.setLaterRunnable {
+ runReadAction {
+ CodeCompletionHandlerBase.createHandler(CompletionType.BASIC)
+ .invokeCompletion(context.project, context.editor)
+ }
+ }
+}
+
+private val ADDITIONAL_NAMESPACE_PRIORITY = mapOf(
+ "named" to 0.2,
+ "official" to 0.1,
+)
+
+object CtHeaderCompletionProvider : CompletionProvider() {
+
+ override fun addCompletions(
+ parameters: CompletionParameters,
+ context: ProcessingContext,
+ result: CompletionResultSet,
+ ) {
+ if (parameters.position.prevLeaf(true) == null) {
+ val module = parameters.originalFile.findModule() ?: return
+ val fabricModule = MinecraftFacet.getInstance(module, FabricModuleType) ?: return
+ for (mappingNamespace in fabricModule.mappingNamespaces) {
+ val additionalPriority = ADDITIONAL_NAMESPACE_PRIORITY[mappingNamespace] ?: 0.0
+ result.addElement(PrioritizedLookupElement.withPriority(LookupElementBuilder.create("accessWidener v1 $mappingNamespace"), 1.0 + additionalPriority))
+ result.addElement(PrioritizedLookupElement.withPriority(LookupElementBuilder.create("accessWidener v2 $mappingNamespace"), 2.0 + additionalPriority))
+ for (ctVersion in 1..FabricConstants.CLASS_TWEAKER_VERSION - 2) {
+ result.addElement(PrioritizedLookupElement.withPriority(LookupElementBuilder.create("classTweaker v$ctVersion $mappingNamespace"), 2.0 + ctVersion + additionalPriority))
+ }
+ }
+ }
+ }
+}
+
+object CtNamespaceCompletionProvider : CompletionProvider() {
+
+ override fun addCompletions(
+ parameters: CompletionParameters,
+ context: ProcessingContext,
+ result: CompletionResultSet,
+ ) {
+ val module = parameters.originalFile.findModule() ?: return
+ val fabricModule = MinecraftFacet.getInstance(module, FabricModuleType) ?: return
+ result.addAllElements(fabricModule.mappingNamespaces.map(LookupElementBuilder::create))
+ }
+}
+
+object CtEntryStartCompletionProvider : CompletionProvider() {
+
+ override fun addCompletions(
+ parameters: CompletionParameters,
+ context: ProcessingContext,
+ result: CompletionResultSet,
+ ) {
+ val elements = listOf(
+ "accessible",
+ "transitive-accessible",
+ "extendable",
+ "transitive-extendable",
+ "mutable",
+ "transitive-mutable",
+ "inject-interface",
+ "transitive-inject-interface",
+ "extend-enum",
+ "transitive-extend-enum",
+ ).map { LookupElementBuilder.create(it).withInsertHandler { ctx, _ -> insertWhitespace(ctx) } }
+ result.addAllElements(elements)
+ }
+}
+
+object CtAwTargetCompletionProvider : CompletionProvider() {
+
+ override fun addCompletions(
+ parameters: CompletionParameters,
+ context: ProcessingContext,
+ result: CompletionResultSet,
+ ) {
+ val text = parameters.position
+ .prevLeaf { it.elementType == CtTypes.ACCESS_ELEMENT || it.elementType == CtTypes.CRLF }?.text ?: return
+ val elements = CtAnnotator.TokenSets.compatibleByAccessMap.get(text)
+ .map { LookupElementBuilder.create(it).withInsertHandler { ctx, _ -> insertWhitespace(ctx) } }
+ result.addAllElements(elements)
+ }
+}
Index: src/main/kotlin/platform/minecraft/ct/CtFile.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/CtFile.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/CtFile.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,41 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct
+
+import com.demonwav.mcdev.asset.PlatformAssets
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtHeader
+import com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtEntryMixin
+import com.demonwav.mcdev.util.childrenOfType
+import com.intellij.extapi.psi.PsiFileBase
+import com.intellij.psi.FileViewProvider
+
+class CtFile(viewProvider: FileViewProvider) : PsiFileBase(viewProvider, CtLanguage) {
+
+ val header: CtHeader?
+ get() = children.first { it is CtHeader } as? CtHeader
+
+ val entries: Collection
+ get() = childrenOfType()
+
+ override fun getFileType() = CtFileType
+ override fun toString() = "Class Tweaker File"
+ override fun getIcon(flags: Int) = PlatformAssets.MINECRAFT_ICON
+}
Index: src/main/kotlin/platform/minecraft/ct/CtFileType.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/CtFileType.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/CtFileType.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,35 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct
+
+import com.demonwav.mcdev.asset.PlatformAssets
+import com.intellij.openapi.fileTypes.LanguageFileType
+
+object CtFileType : LanguageFileType(CtLanguage) {
+
+ override fun getName() = "Class Tweaker"
+
+ override fun getDescription() = "Class tweaker"
+
+ override fun getDefaultExtension() = "classtweaker"
+
+ override fun getIcon() = PlatformAssets.MINECRAFT_ICON
+}
Index: src/main/kotlin/platform/minecraft/ct/CtLanguage.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/CtLanguage.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/CtLanguage.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,29 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct
+
+import com.intellij.lang.Language
+import java.io.Serial
+
+object CtLanguage : Language("Class Tweaker") {
+ @Serial
+ private fun readResolve(): Any = CtLanguage
+}
Index: src/main/kotlin/platform/minecraft/ct/CtLexerAdapter.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/CtLexerAdapter.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/CtLexerAdapter.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,26 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct
+
+import com.demonwav.mcdev.platform.minecraft.ct.gen.CtLexer
+import com.intellij.lexer.FlexAdapter
+
+class CtLexerAdapter : FlexAdapter(CtLexer())
Index: src/main/kotlin/platform/minecraft/ct/CtParserDefinition.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/CtParserDefinition.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/CtParserDefinition.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,60 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct
+
+import com.demonwav.mcdev.platform.minecraft.ct.gen.parser.CtParser
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtTypes
+import com.intellij.lang.ASTNode
+import com.intellij.lang.Language
+import com.intellij.lang.LanguageUtil
+import com.intellij.lang.ParserDefinition
+import com.intellij.lang.PsiParser
+import com.intellij.lexer.Lexer
+import com.intellij.openapi.project.Project
+import com.intellij.psi.FileViewProvider
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiFile
+import com.intellij.psi.TokenType
+import com.intellij.psi.tree.IFileElementType
+import com.intellij.psi.tree.TokenSet
+
+class CtParserDefinition : ParserDefinition {
+
+ override fun createLexer(project: Project): Lexer = CtLexerAdapter()
+ override fun createParser(project: Project): PsiParser = CtParser()
+ override fun getFileNodeType(): IFileElementType = TokenSets.FILE
+ override fun getWhitespaceTokens(): TokenSet = TokenSets.WHITE_SPACES
+ override fun getCommentTokens(): TokenSet = TokenSets.COMMENTS
+ override fun getStringLiteralElements(): TokenSet = TokenSet.EMPTY
+ override fun createElement(node: ASTNode): PsiElement = CtTypes.Factory.createElement(node)
+ override fun createFile(viewProvider: FileViewProvider): PsiFile = CtFile(viewProvider)
+
+ override fun spaceExistenceTypeBetweenTokens(left: ASTNode, right: ASTNode): ParserDefinition.SpaceRequirements {
+ return LanguageUtil.canStickTokensTogetherByLexer(left, right, CtLexerAdapter())
+ }
+
+ object TokenSets {
+ val WHITE_SPACES = TokenSet.create(TokenType.WHITE_SPACE)
+ val COMMENTS = TokenSet.create(CtTypes.COMMENT)
+
+ val FILE = IFileElementType(Language.findInstance(CtLanguage::class.java))
+ }
+}
Index: src/main/kotlin/platform/minecraft/ct/CtSyntaxHighlighter.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/CtSyntaxHighlighter.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/CtSyntaxHighlighter.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,104 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct
+
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtTypes
+import com.intellij.openapi.editor.DefaultLanguageHighlighterColors
+import com.intellij.openapi.editor.HighlighterColors
+import com.intellij.openapi.editor.colors.TextAttributesKey
+import com.intellij.openapi.fileTypes.SyntaxHighlighterBase
+import com.intellij.psi.TokenType
+import com.intellij.psi.tree.IElementType
+
+class CtSyntaxHighlighter : SyntaxHighlighterBase() {
+
+ override fun getHighlightingLexer() = CtLexerAdapter()
+
+ override fun getTokenHighlights(tokenType: IElementType) =
+ when (tokenType) {
+ CtTypes.HEADER_NAME -> HEADER_NAME_KEYS
+ CtTypes.HEADER_NAMESPACE_ELEMENT -> HEADER_NAMESPACE_KEYS
+ CtTypes.ACCESS_ELEMENT -> ACCESS_KEYS
+ CtTypes.INJECT_INTERFACE_ELEMENT -> INJECT_INTERFACE_KEYS
+ CtTypes.EXTEND_ENUM_ELEMENT -> EXTEND_ENUM_KEYS
+ CtTypes.CLASS_ELEMENT -> CLASS_ELEMENT_KEYS
+ CtTypes.METHOD_ELEMENT -> METHOD_ELEMENT_KEYS
+ CtTypes.FIELD_ELEMENT -> FIELD_ELEMENT_KEYS
+ CtTypes.CLASS_NAME_ELEMENT -> CLASS_NAME_KEYS
+ CtTypes.NAME_ELEMENT -> MEMBER_NAME_KEYS
+ CtTypes.CLASS_VALUE, CtTypes.SIGNATURE_CLASS_VALUE_START, CtTypes.SIGNATURE_CLASS_VALUE_END -> CLASS_VALUE_KEYS
+ CtTypes.PRIMITIVE -> PRIMITIVE_KEYS
+ CtTypes.TYPE_VARIABLE -> TYPE_VARIABLE_KEYS
+ CtTypes.COMMENT -> COMMENT_KEYS
+ TokenType.BAD_CHARACTER -> BAD_CHARACTER_KEYS
+ else -> EMPTY_KEYS
+ }
+
+ companion object {
+ val HEADER_NAME =
+ TextAttributesKey.createTextAttributesKey("CT_HEADER_NAME", DefaultLanguageHighlighterColors.KEYWORD)
+ val HEADER_NAMESPACE =
+ TextAttributesKey.createTextAttributesKey("CT_HEADER_NAMESPACE", DefaultLanguageHighlighterColors.CLASS_REFERENCE)
+ val ACCESS =
+ TextAttributesKey.createTextAttributesKey("CT_ACCESS", DefaultLanguageHighlighterColors.KEYWORD)
+ val INJECT_INTERFACE =
+ TextAttributesKey.createTextAttributesKey("CT_INJECT_INTERFACE", DefaultLanguageHighlighterColors.KEYWORD)
+ val EXTEND_ENUM =
+ TextAttributesKey.createTextAttributesKey("CT_EXTEND_ENUM", DefaultLanguageHighlighterColors.KEYWORD)
+ val CLASS_ELEMENT =
+ TextAttributesKey.createTextAttributesKey("CT_CLASS_ELEMENT", DefaultLanguageHighlighterColors.KEYWORD)
+ val METHOD_ELEMENT =
+ TextAttributesKey.createTextAttributesKey("CT_METHOD_ELEMENT", DefaultLanguageHighlighterColors.KEYWORD)
+ val FIELD_ELEMENT =
+ TextAttributesKey.createTextAttributesKey("CT_FIELD_ELEMENT", DefaultLanguageHighlighterColors.KEYWORD)
+ val CLASS_NAME =
+ TextAttributesKey.createTextAttributesKey("CT_CLASS_NAME", DefaultLanguageHighlighterColors.STRING)
+ val MEMBER_NAME =
+ TextAttributesKey.createTextAttributesKey("CT_MEMBER_NAME", DefaultLanguageHighlighterColors.STATIC_FIELD)
+ val CLASS_VALUE =
+ TextAttributesKey.createTextAttributesKey("CT_CLASS_VALUE", DefaultLanguageHighlighterColors.STATIC_METHOD)
+ val PRIMITIVE =
+ TextAttributesKey.createTextAttributesKey("CT_PRIMITIVE", DefaultLanguageHighlighterColors.NUMBER)
+ val TYPE_VARIABLE =
+ TextAttributesKey.createTextAttributesKey("CT_TYPE_VARIABLE", DefaultLanguageHighlighterColors.STATIC_METHOD)
+ val COMMENT =
+ TextAttributesKey.createTextAttributesKey("CT_COMMENT", DefaultLanguageHighlighterColors.LINE_COMMENT)
+ val BAD_CHARACTER =
+ TextAttributesKey.createTextAttributesKey("CT_BAD_CHARACTER", HighlighterColors.BAD_CHARACTER)
+
+ private val HEADER_NAME_KEYS = arrayOf(HEADER_NAME)
+ private val HEADER_NAMESPACE_KEYS = arrayOf(HEADER_NAMESPACE)
+ private val ACCESS_KEYS = arrayOf(ACCESS)
+ private val INJECT_INTERFACE_KEYS = arrayOf(INJECT_INTERFACE)
+ private val EXTEND_ENUM_KEYS = arrayOf(EXTEND_ENUM)
+ private val CLASS_ELEMENT_KEYS = arrayOf(CLASS_ELEMENT)
+ private val METHOD_ELEMENT_KEYS = arrayOf(METHOD_ELEMENT)
+ private val FIELD_ELEMENT_KEYS = arrayOf(FIELD_ELEMENT)
+ private val CLASS_NAME_KEYS = arrayOf(CLASS_NAME)
+ private val MEMBER_NAME_KEYS = arrayOf(MEMBER_NAME)
+ private val CLASS_VALUE_KEYS = arrayOf(CLASS_VALUE)
+ private val PRIMITIVE_KEYS = arrayOf(PRIMITIVE)
+ private val TYPE_VARIABLE_KEYS = arrayOf(TYPE_VARIABLE)
+ private val COMMENT_KEYS = arrayOf(COMMENT)
+ private val BAD_CHARACTER_KEYS = arrayOf(BAD_CHARACTER)
+ private val EMPTY_KEYS = emptyArray()
+ }
+}
Index: src/main/kotlin/platform/minecraft/ct/CtSyntaxHighlighterFactory.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/CtSyntaxHighlighterFactory.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/CtSyntaxHighlighterFactory.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,29 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct
+
+import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.vfs.VirtualFile
+
+class CtSyntaxHighlighterFactory : SyntaxHighlighterFactory() {
+ override fun getSyntaxHighlighter(project: Project?, virtualFile: VirtualFile?) = CtSyntaxHighlighter()
+}
Index: src/main/kotlin/platform/minecraft/ct/fixes/CopyAwAccessibleEntryFix.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/fixes/CopyAwAccessibleEntryFix.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/fixes/CopyAwAccessibleEntryFix.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,69 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.fixes
+
+import com.demonwav.mcdev.facet.MinecraftFacet
+import com.demonwav.mcdev.platform.fabric.FabricModuleType
+import com.demonwav.mcdev.platform.minecraft.actions.CopyAwAction
+import com.demonwav.mcdev.platform.sponge.SpongeModuleType
+import com.demonwav.mcdev.util.findModule
+import com.intellij.codeInsight.daemon.QuickFixActionRegistrar
+import com.intellij.codeInsight.intention.IntentionAction
+import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider
+import com.intellij.openapi.editor.Editor
+import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiFile
+import com.intellij.psi.PsiJavaCodeReferenceElement
+
+class CopyAwAccessibleEntryFix(val target: PsiElement, val element: PsiElement) : IntentionAction {
+
+ class Provider : UnresolvedReferenceQuickFixProvider() {
+
+ override fun registerFixes(ref: PsiJavaCodeReferenceElement, registrar: QuickFixActionRegistrar) {
+ val module = ref.findModule() ?: return
+ val isApplicable = MinecraftFacet.getInstance(module, FabricModuleType, SpongeModuleType) != null
+ if (!isApplicable) {
+ return
+ }
+
+ val resolve = ref.advancedResolve(true)
+ val target = resolve.element
+ if (target != null && !resolve.isAccessible) {
+ registrar.register(CopyAwAccessibleEntryFix(target, ref))
+ }
+ }
+
+ override fun getReferenceClass(): Class = PsiJavaCodeReferenceElement::class.java
+ }
+
+ override fun startInWriteAction(): Boolean = false
+
+ override fun getText(): String = "Copy AW entry"
+
+ override fun getFamilyName(): String = "Copy AW entry for inaccessible element"
+
+ override fun isAvailable(project: Project, editor: Editor?, file: PsiFile?): Boolean = true
+
+ override fun invoke(project: Project, editor: Editor?, file: PsiFile?) {
+ CopyAwAction.Util.doCopy(target, element, editor, null)
+ }
+}
Index: src/main/kotlin/platform/minecraft/ct/inspections/DuplicateAwEntryInspection.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/inspections/DuplicateAwEntryInspection.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/inspections/DuplicateAwEntryInspection.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,81 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.inspections
+
+import com.demonwav.mcdev.platform.minecraft.ct.CtFile
+import com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtAwEntryMixin
+import com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtAwMemberNameMixin
+import com.demonwav.mcdev.util.childOfType
+import com.intellij.codeInspection.InspectionManager
+import com.intellij.codeInspection.LocalInspectionTool
+import com.intellij.codeInspection.ProblemDescriptor
+import com.intellij.codeInspection.ProblemHighlightType
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiFile
+import com.intellij.psi.PsiNamedElement
+import com.jetbrains.rd.util.getOrCreate
+import org.jetbrains.plugins.groovy.codeInspection.fixes.RemoveElementQuickFix
+
+class DuplicateAwEntryInspection : LocalInspectionTool() {
+
+ override fun checkFile(file: PsiFile, manager: InspectionManager, isOnTheFly: Boolean): Array? {
+ if (file !is CtFile) {
+ return null
+ }
+ val collected = HashMap, MutableList>()
+ file.entries.filterIsInstance().forEach {
+ val target = it.childOfType()?.resolve()
+ val accessKind = it.accessKind
+ if (target != null && accessKind != null) {
+ (collected.getOrCreate(Pair(target, accessKind)) { ArrayList() }) += it
+ }
+ }
+ val problems = ArrayList()
+ collected.forEach { (sort, matches) ->
+ if (sort.first is PsiNamedElement) {
+ if (matches.size > 1) {
+ for (match in matches)
+ problems += manager.createProblemDescriptor(
+ match,
+ "Duplicate entry for \"${sort.second} ${(sort.first as PsiNamedElement).name}\"",
+ RemoveElementQuickFix("Remove duplicate"),
+ ProblemHighlightType.WARNING,
+ isOnTheFly,
+ )
+ }
+ }
+ }
+ return problems.toTypedArray()
+ }
+
+ override fun runForWholeFile(): Boolean {
+ return true
+ }
+
+ override fun getDisplayName(): String {
+ return "Duplicate AW entry"
+ }
+
+ override fun getStaticDescription(): String {
+ return "Warns when the same element has its accessibility, mutability, " +
+ "or extensibility changed multiple times in one file."
+ }
+}
Index: src/main/kotlin/platform/minecraft/ct/inspections/UnknownCtNamespaceInspection.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/inspections/UnknownCtNamespaceInspection.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/inspections/UnknownCtNamespaceInspection.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,51 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.inspections
+
+import com.demonwav.mcdev.facet.MinecraftFacet
+import com.demonwav.mcdev.platform.fabric.FabricModuleType
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtHeader
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtVisitor
+import com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtHeaderMixin
+import com.demonwav.mcdev.util.findModule
+import com.intellij.codeInspection.LocalInspectionTool
+import com.intellij.codeInspection.ProblemsHolder
+
+class UnknownCtNamespaceInspection : LocalInspectionTool() {
+ override fun getDisplayName() = "Unknown CT namespace"
+ override fun getStaticDescription() = "Reports an unknown namespace in a ClassTweaker header"
+
+ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = object : CtVisitor() {
+ override fun visitHeaderMixin(header: CtHeaderMixin) {
+ val namespace = header.namespaceString ?: return
+
+ val module = header.findModule() ?: return
+ val fabricModule = MinecraftFacet.getInstance(module, FabricModuleType) ?: return
+
+ if (namespace !in fabricModule.mappingNamespaces) {
+ holder.registerProblem(
+ (header as CtHeader).namespaceElement ?: header,
+ "Unrecognized namespace"
+ )
+ }
+ }
+ }
+}
Index: src/main/kotlin/platform/minecraft/ct/psi/CtElement.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/CtElement.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/CtElement.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,25 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi
+
+import com.intellij.psi.PsiElement
+
+interface CtElement : PsiElement
Index: src/main/kotlin/platform/minecraft/ct/psi/CtElementType.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/CtElementType.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/CtElementType.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,27 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi
+
+import com.demonwav.mcdev.platform.minecraft.ct.CtLanguage
+import com.intellij.psi.tree.IElementType
+import org.jetbrains.annotations.NonNls
+
+class CtElementType(@NonNls debugName: String) : IElementType(debugName, CtLanguage)
Index: src/main/kotlin/platform/minecraft/ct/psi/CtTokenType.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/CtTokenType.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/CtTokenType.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,27 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi
+
+import com.demonwav.mcdev.platform.minecraft.ct.CtLanguage
+import com.intellij.psi.tree.IElementType
+import org.jetbrains.annotations.NonNls
+
+class CtTokenType(@NonNls debugName: String) : IElementType(debugName, CtLanguage)
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwClassEntryMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwClassEntryMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwClassEntryMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,23 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins
+
+interface CtAwClassEntryMixin : CtAwEntryMixin
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwClassNameMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwClassNameMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwClassNameMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,26 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins
+
+import com.demonwav.mcdev.platform.minecraft.ct.psi.CtElement
+import com.intellij.psi.PsiReference
+
+interface CtAwClassNameMixin : CtElement, PsiReference
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwDescElementMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwDescElementMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwDescElementMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,26 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins
+
+import com.demonwav.mcdev.platform.minecraft.ct.psi.CtElement
+import com.intellij.psi.PsiReference
+
+interface CtAwDescElementMixin : CtElement, PsiReference
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwEntryMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwEntryMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwEntryMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,27 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins
+
+interface CtAwEntryMixin : CtEntryMixin {
+
+ val accessKind: String?
+ val targetClassName: String?
+}
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwFieldEntryMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwFieldEntryMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwFieldEntryMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,27 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins
+
+interface CtAwFieldEntryMixin : CtAwEntryMixin {
+
+ val fieldName: String?
+ val fieldDescriptor: String?
+}
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwMemberNameMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwMemberNameMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwMemberNameMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,26 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins
+
+import com.demonwav.mcdev.platform.minecraft.ct.psi.CtElement
+import com.intellij.psi.PsiReference
+
+interface CtAwMemberNameMixin : CtElement, PsiReference
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwMethodEntryMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwMethodEntryMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/CtAwMethodEntryMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,27 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins
+
+interface CtAwMethodEntryMixin : CtAwEntryMixin {
+
+ val methodName: String?
+ val methodDescriptor: String?
+}
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/CtEntryMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/CtEntryMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/CtEntryMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,25 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins
+
+import com.demonwav.mcdev.platform.minecraft.ct.psi.CtElement
+
+interface CtEntryMixin : CtElement
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/CtExtendEnumEntryMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/CtExtendEnumEntryMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/CtExtendEnumEntryMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,23 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins
+
+interface CtExtendEnumEntryMixin : CtEntryMixin
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/CtHeaderMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/CtHeaderMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/CtHeaderMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,36 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins
+
+import com.demonwav.mcdev.platform.minecraft.ct.psi.CtElement
+import com.intellij.psi.PsiElement
+
+interface CtHeaderMixin : CtElement {
+
+ val nameElement: PsiElement
+ val nameString: String
+ val versionElement: PsiElement?
+ val versionString: String?
+ val namespaceElement: PsiElement?
+ val namespaceString: String?
+ // Effective version, AW is 1 and 2; CT starts with 3, so CT v1 has effective version 3.
+ val effectiveVersion: Int?
+}
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/CtItfEntryMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/CtItfEntryMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/CtItfEntryMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,23 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins
+
+interface CtItfEntryMixin : CtEntryMixin
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwClassEntryImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwClassEntryImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwClassEntryImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,26 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtAwClassEntryMixin
+import com.intellij.lang.ASTNode
+
+abstract class CtAwClassEntryImplMixin(node: ASTNode) : CtAwEntryImplMixin(node), CtAwClassEntryMixin
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwClassNameImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwClassNameImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwClassNameImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,62 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtAwClassNameMixin
+import com.demonwav.mcdev.util.cached
+import com.demonwav.mcdev.util.findQualifiedClass
+import com.intellij.extapi.psi.ASTWrapperPsiElement
+import com.intellij.lang.ASTNode
+import com.intellij.openapi.util.TextRange
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiReference
+import com.intellij.psi.util.PsiModificationTracker
+import com.intellij.util.IncorrectOperationException
+
+abstract class CtAwClassNameImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), CtAwClassNameMixin {
+
+ override fun getElement(): PsiElement = this
+
+ override fun getReference(): PsiReference? = this
+
+ override fun resolve(): PsiElement? {
+ return cached(PsiModificationTracker.MODIFICATION_COUNT) { findQualifiedClass(text.replace('/', '.'), this) }
+ }
+
+ override fun getRangeInElement(): TextRange = TextRange(0, text.length)
+
+ override fun getCanonicalText(): String = text
+
+ override fun handleElementRename(newElementName: String): PsiElement {
+ throw IncorrectOperationException()
+ }
+
+ override fun bindToElement(element: PsiElement): PsiElement {
+ throw IncorrectOperationException()
+ }
+
+ override fun isReferenceTo(element: PsiElement): Boolean {
+ return element is PsiClass && element.qualifiedName == text.replace('/', '.')
+ }
+
+ override fun isSoft(): Boolean = false
+}
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwDescElementImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwDescElementImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwDescElementImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,70 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtAwDescElementMixin
+import com.demonwav.mcdev.util.cached
+import com.demonwav.mcdev.util.findQualifiedClass
+import com.intellij.extapi.psi.ASTWrapperPsiElement
+import com.intellij.lang.ASTNode
+import com.intellij.openapi.util.TextRange
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiReference
+import com.intellij.psi.util.PsiModificationTracker
+import com.intellij.util.IncorrectOperationException
+
+abstract class CtAwDescElementImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), CtAwDescElementMixin {
+
+ override fun getElement(): PsiElement = this
+
+ override fun getReference(): PsiReference? = this
+
+ override fun resolve(): PsiElement? = cached(PsiModificationTracker.MODIFICATION_COUNT) {
+ val name = asQualifiedName() ?: return@cached null
+ return@cached findQualifiedClass(name, this)
+ }
+
+ override fun getRangeInElement(): TextRange = TextRange(0, text.length)
+
+ override fun getCanonicalText(): String = text
+
+ override fun handleElementRename(newElementName: String): PsiElement {
+ throw IncorrectOperationException()
+ }
+
+ override fun bindToElement(element: PsiElement): PsiElement {
+ throw IncorrectOperationException()
+ }
+
+ override fun isReferenceTo(element: PsiElement): Boolean {
+ return element is PsiClass && element.qualifiedName == asQualifiedName()
+ }
+
+ private fun asQualifiedName(): String? =
+ if (text.length > 1) {
+ text.substring(1, text.length - 1).replace('/', '.')
+ } else {
+ null
+ }
+
+ override fun isSoft(): Boolean = false
+}
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwEntryImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwEntryImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwEntryImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,35 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtTypes
+import com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtAwEntryMixin
+import com.intellij.lang.ASTNode
+import com.intellij.psi.PsiElement
+
+abstract class CtAwEntryImplMixin(node: ASTNode) : CtEntryImplMixin(node), CtAwEntryMixin {
+
+ override val accessKind: String?
+ get() = findChildByType(CtTypes.ACCESS)?.text
+
+ override val targetClassName: String?
+ get() = findChildByType(CtTypes.CLASS_NAME)?.text
+}
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwFieldEntryImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwFieldEntryImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwFieldEntryImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,34 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtTypes
+import com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtAwFieldEntryMixin
+import com.intellij.lang.ASTNode
+import com.intellij.psi.PsiElement
+
+abstract class CtAwFieldEntryImplMixin(node: ASTNode) : CtAwEntryImplMixin(node), CtAwFieldEntryMixin {
+ override val fieldName: String?
+ get() = findChildByType(CtTypes.MEMBER_NAME)?.text
+
+ override val fieldDescriptor: String?
+ get() = findChildByType(CtTypes.FIELD_DESC)?.text
+}
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwMemberNameImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwMemberNameImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwMemberNameImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,105 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtAwFieldEntry
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtAwMethodEntry
+import com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtAwEntryMixin
+import com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtAwMemberNameMixin
+import com.demonwav.mcdev.util.MemberReference
+import com.demonwav.mcdev.util.cached
+import com.intellij.codeInsight.completion.JavaLookupElementBuilder
+import com.intellij.extapi.psi.ASTWrapperPsiElement
+import com.intellij.lang.ASTNode
+import com.intellij.openapi.util.TextRange
+import com.intellij.psi.JavaPsiFacade
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiMethod
+import com.intellij.psi.PsiReference
+import com.intellij.psi.PsiSubstitutor
+import com.intellij.psi.util.PsiModificationTracker
+import com.intellij.psi.util.parentOfType
+import com.intellij.util.ArrayUtil
+import com.intellij.util.IncorrectOperationException
+import com.intellij.util.containers.map2Array
+
+abstract class CtAwMemberNameImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), CtAwMemberNameMixin {
+
+ override fun getElement(): PsiElement = this
+
+ override fun getReference(): PsiReference? = this
+
+ override fun resolve(): PsiElement? = cached(PsiModificationTracker.MODIFICATION_COUNT) {
+ val entry = this.parentOfType() ?: return@cached null
+ val owner = entry.targetClassName?.replace('/', '.')
+ return@cached when (entry) {
+ is CtAwMethodEntry -> {
+ val name = entry.methodName ?: return@cached null
+ val desc = entry.methodDescriptor
+ MemberReference(name, desc, owner).resolveMember(project, resolveScope)
+ // fallback if descriptor is invalid
+ ?: MemberReference(name, null, owner).resolveMember(project, resolveScope)
+ }
+ is CtAwFieldEntry -> {
+ val name = entry.fieldName ?: return@cached null
+ MemberReference(name, null, owner)
+ .resolveMember(project, resolveScope)
+ }
+ else -> null
+ }
+ }
+
+ override fun getVariants(): Array<*> {
+ val entry = this.parentOfType() ?: return ArrayUtil.EMPTY_OBJECT_ARRAY
+ val targetClassName = entry.targetClassName?.replace('/', '.')?.replace('$', '.')
+ ?: return ArrayUtil.EMPTY_OBJECT_ARRAY
+ val targetClass = JavaPsiFacade.getInstance(project)?.findClass(targetClassName, resolveScope)
+ ?: return ArrayUtil.EMPTY_OBJECT_ARRAY
+
+ return when (entry) {
+ is CtAwMethodEntry -> targetClass.methods.map2Array(::methodLookupElement)
+ is CtAwFieldEntry -> targetClass.fields
+ else -> ArrayUtil.EMPTY_OBJECT_ARRAY
+ }
+ }
+
+ private fun methodLookupElement(it: PsiMethod) =
+ JavaLookupElementBuilder.forMethod(it, if (it.isConstructor) "" else it.name, PsiSubstitutor.EMPTY, null)
+
+ override fun getRangeInElement(): TextRange = TextRange(0, text.length)
+
+ override fun getCanonicalText(): String = text
+
+ override fun handleElementRename(newElementName: String): PsiElement {
+ throw IncorrectOperationException()
+ }
+
+ override fun bindToElement(element: PsiElement): PsiElement {
+ throw IncorrectOperationException()
+ }
+
+ override fun isReferenceTo(element: PsiElement): Boolean {
+ return element is PsiClass && element.qualifiedName == text.replace('/', '.')
+ }
+
+ override fun isSoft(): Boolean = false
+}
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwMethodEntryImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwMethodEntryImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtAwMethodEntryImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,34 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtTypes
+import com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtAwMethodEntryMixin
+import com.intellij.lang.ASTNode
+import com.intellij.psi.PsiElement
+
+abstract class CtAwMethodEntryImplMixin(node: ASTNode) : CtAwEntryImplMixin(node), CtAwMethodEntryMixin {
+ override val methodName: String?
+ get() = findChildByType(CtTypes.MEMBER_NAME)?.text
+
+ override val methodDescriptor: String?
+ get() = findChildByType(CtTypes.METHOD_DESC)?.text
+}
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtEntryImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtEntryImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtEntryImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,27 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtEntryMixin
+import com.intellij.extapi.psi.ASTWrapperPsiElement
+import com.intellij.lang.ASTNode
+
+abstract class CtEntryImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), CtEntryMixin
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtExtendEnumEntryImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtExtendEnumEntryImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtExtendEnumEntryImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,26 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtExtendEnumEntryMixin
+import com.intellij.lang.ASTNode
+
+abstract class CtExtendEnumEntryImplMixin(node: ASTNode): CtEntryImplMixin(node), CtExtendEnumEntryMixin
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtHeaderImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtHeaderImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtHeaderImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,65 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.ct.gen.psi.CtTypes
+import com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtHeaderMixin
+import com.intellij.extapi.psi.ASTWrapperPsiElement
+import com.intellij.lang.ASTNode
+import com.intellij.openapi.diagnostic.logger
+import com.intellij.psi.PsiElement
+
+abstract class CtHeaderImplMixin(node: ASTNode) : ASTWrapperPsiElement(node), CtHeaderMixin {
+ companion object {
+ private val LOG = logger()
+ }
+
+ override val nameElement: PsiElement
+ get() = findNotNullChildByType(CtTypes.HEADER_NAME)
+
+ override val nameString: String
+ get() = nameElement.text
+
+ override val versionElement: PsiElement?
+ get() = findChildByType(CtTypes.HEADER_VERSION_ELEMENT)
+
+ override val versionString: String?
+ get() = versionElement?.text
+
+ override val namespaceElement: PsiElement?
+ get() = findChildByType(CtTypes.HEADER_NAMESPACE_ELEMENT)
+
+ override val namespaceString: String?
+ get() = namespaceElement?.text
+
+ override val effectiveVersion: Int?
+ get() {
+ val version = versionString?.removePrefix("v")?.toIntOrNull() ?: return null
+ return when (nameString) {
+ "accessWidener" -> version
+ "classTweaker" -> version + 2
+ else -> {
+ LOG.error("Unknown header name: $nameString")
+ null
+ }
+ }
+ }
+}
Index: src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtItfEntryImplMixin.kt
===================================================================
--- src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtItfEntryImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/ct/psi/mixins/impl/CtItfEntryImplMixin.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,26 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.impl
+
+import com.demonwav.mcdev.platform.minecraft.ct.psi.mixins.CtItfEntryMixin
+import com.intellij.lang.ASTNode
+
+abstract class CtItfEntryImplMixin(node: ASTNode): CtEntryImplMixin(node), CtItfEntryMixin
Index: src/main/kotlin/platform/minecraft/debug/MinecraftRunConfigurationExtension.kt
===================================================================
--- src/main/kotlin/platform/minecraft/debug/MinecraftRunConfigurationExtension.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/debug/MinecraftRunConfigurationExtension.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,56 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.debug
+
+import com.demonwav.mcdev.facet.MinecraftFacet
+import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType
+import com.demonwav.mcdev.util.ModuleDebugRunConfigurationExtension
+import com.intellij.debugger.DebuggerManager
+import com.intellij.debugger.engine.DebugProcess
+import com.intellij.debugger.engine.DebugProcessImpl
+import com.intellij.debugger.engine.DebugProcessListener
+import com.intellij.execution.process.ProcessHandler
+import com.intellij.openapi.module.Module
+
+class MinecraftRunConfigurationExtension : ModuleDebugRunConfigurationExtension() {
+
+ override fun attachToProcess(handler: ProcessHandler, module: Module) {
+ if (MinecraftFacet.getInstance(module)?.isOfType(MinecraftModuleType) == true) {
+ DebuggerManager.getInstance(module.project)
+ .addDebugProcessListener(handler, MyProcessListener())
+ }
+ }
+
+ private inner class MyProcessListener : DebugProcessListener {
+
+ override fun processAttached(process: DebugProcess) {
+ if (process !is DebugProcessImpl) {
+ return
+ }
+
+ // Add session listener
+ process.xdebugProcess?.session?.addSessionListener(UngrabMouseDebugSessionListener(process))
+
+ // We don't need any further events
+ process.removeDebugProcessListener(this)
+ }
+ }
+}
Index: src/main/kotlin/platform/minecraft/debug/UngrabMouseDebugSessionListener.kt
===================================================================
--- src/main/kotlin/platform/minecraft/debug/UngrabMouseDebugSessionListener.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/debug/UngrabMouseDebugSessionListener.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,128 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.debug
+
+import com.intellij.debugger.engine.DebugProcessImpl
+import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
+import com.intellij.debugger.jdi.VirtualMachineProxyImpl
+import com.intellij.xdebugger.XDebugSessionListener
+import com.sun.jdi.BooleanValue
+import com.sun.jdi.ClassType
+import com.sun.jdi.Field
+import com.sun.jdi.Method
+import com.sun.jdi.ObjectReference
+import com.sun.jdi.ReferenceType
+
+class UngrabMouseDebugSessionListener(private val process: DebugProcessImpl) : XDebugSessionListener {
+
+ private fun ungrabMouse() {
+ val suspendContextImpl = process.debuggerContext.suspendContext ?: return
+ if (suspendContextImpl.thread?.isSuspended != true) {
+ return
+ }
+
+ val frameProxy = suspendContextImpl.frameProxy ?: return
+ val debugProcess = suspendContextImpl.debugProcess
+ val virtualMachine = debugProcess.virtualMachineProxy
+ val evaluationContext = EvaluationContextImpl(suspendContextImpl, frameProxy)
+
+ val mouseClass = virtualMachine.classesByName("org.lwjgl.input.Mouse")?.singleOrNull() as? ClassType
+ // LWJGL 3 does not have the Mouse class, Minecraft uses its own MouseHelper instead
+ if (mouseClass != null) {
+ ungrab2(mouseClass, virtualMachine, debugProcess, evaluationContext)
+ } else {
+ ungrab3(virtualMachine, debugProcess, evaluationContext)
+ }
+ }
+
+ private fun ungrab2(
+ mouseClass: ClassType,
+ virtualMachine: VirtualMachineProxyImpl,
+ debugProcess: DebugProcessImpl,
+ evaluationContext: EvaluationContextImpl,
+ ) {
+ val isGrabbed = mouseClass.methodsByName("isGrabbed", "()Z")?.singleOrNull() ?: return
+ val setGrabbed = mouseClass.methodsByName("setGrabbed", "(Z)V")?.singleOrNull() ?: return
+ val grabValue = virtualMachine.mirrorOf(false)
+
+ val currentState = debugProcess.invokeMethod(evaluationContext, mouseClass, isGrabbed, emptyList())
+ if ((currentState as? BooleanValue)?.value() == true) {
+ debugProcess.invokeMethod(evaluationContext, mouseClass, setGrabbed, listOf(grabValue))
+ }
+ }
+
+ private fun ungrab3(
+ virtualMachine: VirtualMachineProxyImpl,
+ debugProcess: DebugProcessImpl,
+ evaluationContext: EvaluationContextImpl,
+ ) {
+ fun findClass(vararg names: String): ClassType? {
+ for (name in names) {
+ (virtualMachine.classesByName(name)?.singleOrNull() as? ClassType)?.let { return it }
+ }
+ return null
+ }
+
+ fun ClassType.fieldByName(vararg names: String): Field? {
+ for (name in names) {
+ this.fieldByName(name)?.let { return it }
+ }
+ return null
+ }
+
+ fun ReferenceType.methodByName(vararg names: Pair): Method? {
+ for ((name, signature) in names) {
+ this.methodsByName(name, signature)?.singleOrNull()?.let { return it }
+ }
+ return null
+ }
+
+ val minecraftClass = findClass(
+ "net.minecraft.client.Minecraft",
+ "net.minecraft.client.MinecraftClient",
+ ) ?: return
+ val minecraftGetter = minecraftClass.methodByName(
+ "getInstance" to "()Lnet/minecraft/client/Minecraft;",
+ "getInstance" to "()Lnet/minecraft/client/MinecraftClient;",
+ ) ?: return
+ val minecraft = debugProcess.invokeMethod(
+ evaluationContext,
+ minecraftClass,
+ minecraftGetter,
+ emptyList(),
+ ) as? ObjectReference ?: return
+
+ val mouseHelperField = minecraftClass.fieldByName("mouseHandler", "mouse", "mouseHelper") ?: return
+ val mouseHelper = minecraft.getValue(mouseHelperField) as? ObjectReference ?: return
+
+ val ungrabMouse = mouseHelper.referenceType().methodByName(
+ "releaseMouse" to "()V",
+ "unlockCursor" to "()V",
+ "ungrabMouse" to "()V",
+ ) ?: return
+
+ debugProcess.invokeMethod(evaluationContext, mouseHelper, ungrabMouse, emptyList())
+ }
+
+ override fun sessionPaused() {
+ ungrabMouse()
+ }
+}
Index: src/main/kotlin/platform/minecraft/fabricloom/FabricLoomData.kt
===================================================================
--- src/main/kotlin/platform/minecraft/fabricloom/FabricLoomData.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/fabricloom/FabricLoomData.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,41 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2025 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.fabricloom
+
+import com.intellij.openapi.externalSystem.model.Key
+import com.intellij.openapi.externalSystem.model.ProjectKeys
+import com.intellij.openapi.externalSystem.model.project.AbstractExternalEntityData
+import com.intellij.openapi.externalSystem.model.project.ModuleData
+import java.io.File
+
+data class FabricLoomData(
+ val module: ModuleData,
+ val tinyMappings: File?,
+ val decompileTasks: Map>,
+ val splitMinecraftJar: Boolean,
+) : AbstractExternalEntityData(module.owner) {
+
+ data class Decompiler(val name: String, val taskName: String, val sourcesPath: String)
+
+ companion object {
+ val KEY = Key.create(FabricLoomData::class.java, ProjectKeys.TASK.processingWeight + 1)
+ }
+}
Index: src/main/kotlin/platform/minecraft/fabricloom/FabricLoomDataService.kt
===================================================================
--- src/main/kotlin/platform/minecraft/fabricloom/FabricLoomDataService.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
+++ src/main/kotlin/platform/minecraft/fabricloom/FabricLoomDataService.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc)
@@ -0,0 +1,248 @@
+/*
+ * Minecraft Development for IntelliJ
+ *
+ * https://mcdev.io/
+ *
+ * Copyright (C) 2026 minecraft-dev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, version 3.0 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.demonwav.mcdev.platform.minecraft.fabricloom
+
+import com.demonwav.mcdev.asset.MCDevBundle
+import com.demonwav.mcdev.platform.fabric.EntryPoint
+import com.demonwav.mcdev.platform.fabric.creator.MAGIC_DEFERRED_INIT_FILE
+import com.demonwav.mcdev.util.addImplements
+import com.demonwav.mcdev.util.addMethod
+import com.demonwav.mcdev.util.ifNotBlank
+import com.demonwav.mcdev.util.invokeLater
+import com.demonwav.mcdev.util.runWriteAction
+import com.demonwav.mcdev.util.runWriteTaskInSmartMode
+import com.intellij.codeInsight.actions.ReformatCodeProcessor
+import com.intellij.codeInsight.generation.OverrideImplementUtil
+import com.intellij.ide.util.EditorHelper
+import com.intellij.json.psi.JsonArray
+import com.intellij.json.psi.JsonElementGenerator
+import com.intellij.json.psi.JsonFile
+import com.intellij.json.psi.JsonObject
+import com.intellij.openapi.externalSystem.model.DataNode
+import com.intellij.openapi.externalSystem.model.Key
+import com.intellij.openapi.externalSystem.model.project.ProjectData
+import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
+import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService
+import com.intellij.openapi.fileEditor.impl.NonProjectFileWritingAccessProvider
+import com.intellij.openapi.module.Module
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.project.guessProjectDir
+import com.intellij.openapi.ui.Messages
+import com.intellij.openapi.util.text.StringUtil
+import com.intellij.openapi.vfs.VfsUtil
+import com.intellij.psi.JavaDirectoryService
+import com.intellij.psi.JavaPsiFacade
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiManager
+import com.intellij.psi.search.GlobalSearchScope
+import com.intellij.util.IncorrectOperationException
+import java.nio.file.Path
+import kotlin.io.path.deleteIfExists
+import kotlin.io.path.div
+import kotlin.io.path.isRegularFile
+import kotlin.io.path.readLines
+import org.jetbrains.plugins.gradle.util.GradleConstants
+
+class FabricLoomDataService : AbstractProjectDataService() {
+
+ override fun getTargetDataKey(): Key