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 = 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/minecraft/fabricloom/FabricLoomDecompileSourceProvider.kt =================================================================== --- src/main/kotlin/platform/minecraft/fabricloom/FabricLoomDecompileSourceProvider.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/fabricloom/FabricLoomDecompileSourceProvider.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,122 @@ +/* + * 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.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/minecraft/fabricloom/FabricLoomProjectResolverExtension.kt =================================================================== --- src/main/kotlin/platform/minecraft/fabricloom/FabricLoomProjectResolverExtension.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/fabricloom/FabricLoomProjectResolverExtension.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,76 @@ +/* + * 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.demonwav.mcdev.platform.minecraft.MinecraftModuleSettings +import com.demonwav.mcdev.platform.minecraft.gradle.MinecraftModelData +import com.demonwav.mcdev.platform.minecraft.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 minecraftData = MinecraftModelData( + ideModule.data, + MinecraftModuleSettings.State( + minecraftVersion = loomData.minecraftVersion, + ), + null, + null + ) + ideModule.createChild(MinecraftModelData.KEY, minecraftData) + + for (child in ideModule.children) { + val childData = child.data + if (childData is GradleSourceSetData) { + child.createChild(MinecraftModelData.KEY, minecraftData.copy(module = childData)) + } + } + } + + super.populateModuleExtraModels(gradleModule, ideModule) + } +} Index: src/main/kotlin/platform/minecraft/fabricloom/TinyUnscrambler.kt =================================================================== --- src/main/kotlin/platform/minecraft/fabricloom/TinyUnscrambler.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/fabricloom/TinyUnscrambler.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,194 @@ +/* + * 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.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/minecraft/framework/MinecraftLibraryKind.kt =================================================================== --- src/main/kotlin/platform/minecraft/framework/MinecraftLibraryKind.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/framework/MinecraftLibraryKind.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.framework + +import com.demonwav.mcdev.util.libraryKind +import com.intellij.openapi.roots.libraries.LibraryKind + +val MINECRAFT_LIBRARY_KIND: LibraryKind by libraryKind("minecraft-library") Index: src/main/kotlin/platform/minecraft/framework/MinecraftPresentationProvider.kt =================================================================== --- src/main/kotlin/platform/minecraft/framework/MinecraftPresentationProvider.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/framework/MinecraftPresentationProvider.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.framework + +import com.demonwav.mcdev.asset.PlatformAssets +import com.demonwav.mcdev.platform.minecraft.util.MinecraftConstants +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 MinecraftPresentationProvider : LibraryPresentationProvider(MINECRAFT_LIBRARY_KIND) { + + override fun getIcon(properties: LibraryVersionProperties?) = PlatformAssets.MINECRAFT_ICON + + override fun detect(classesRoots: List): LibraryVersionProperties? { + for (classesRoot in classesRoots) { + val file = classesRoot.localFile + + if (JarUtil.containsClass(file, MinecraftConstants.MINECRAFT_SERVER)) { + return LibraryVersionProperties() + } + } + return null + } +} Index: src/main/kotlin/platform/minecraft/gradle/MinecraftDataService.kt =================================================================== --- src/main/kotlin/platform/minecraft/gradle/MinecraftDataService.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/gradle/MinecraftDataService.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,59 @@ +/* + * 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 + +import com.demonwav.mcdev.facet.MinecraftFacet +import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType +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 MinecraftDataService : AbstractProjectDataService() { + + override fun getTargetDataKey(): Key = MinecraftModelData.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 minecraftModule = MinecraftFacet.getInstance(module, MinecraftModuleType) + if (minecraftModule != null) { + // Update the local settings and recompute the SRG map + minecraftModule.updateSettings(data.settings) + continue + } + } + } +} Index: src/main/kotlin/platform/minecraft/gradle/MinecraftModelData.kt =================================================================== --- src/main/kotlin/platform/minecraft/gradle/MinecraftModelData.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/gradle/MinecraftModelData.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.gradle + +import com.demonwav.mcdev.platform.minecraft.MinecraftModuleSettings +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 MinecraftModelData( + val module: ModuleData, + val settings: MinecraftModuleSettings.State, + val taskName: String?, + val accessTransformers: List?, +) : AbstractExternalEntityData(module.owner) { + companion object { + // Process MinecraftModelData after builtin services (e.g. dependency or module data) + val KEY = Key.create(MinecraftModelData::class.java, ProjectKeys.TASK.processingWeight + 1) + } +} Index: src/main/kotlin/platform/minecraft/gradle/MinecraftProjectResolverExtension.kt =================================================================== --- src/main/kotlin/platform/minecraft/gradle/MinecraftProjectResolverExtension.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/gradle/MinecraftProjectResolverExtension.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,98 @@ +/* + * 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 + +import com.demonwav.mcdev.platform.minecraft.gradle.datahandler.MinecraftModelFG2Handler +import com.demonwav.mcdev.platform.minecraft.gradle.datahandler.MinecraftModelFG3Handler +import com.demonwav.mcdev.platform.minecraft.gradle.datahandler.MinecraftModelNG7Handler +import com.demonwav.mcdev.platform.minecraft.gradle.datahandler.MinecraftModelNMDHandler +import com.demonwav.mcdev.platform.minecraft.gradle.tooling.MinecraftModelFG2 +import com.demonwav.mcdev.platform.minecraft.gradle.tooling.MinecraftModelFG3 +import com.demonwav.mcdev.platform.minecraft.gradle.tooling.MinecraftModelNG7 +import com.demonwav.mcdev.platform.minecraft.gradle.tooling.MinecraftModelNMD +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 MinecraftProjectResolverExtension : AbstractProjectResolverExtension() { + + // Register our custom Gradle tooling API model in IntelliJ's project resolver + override fun getExtraProjectModelClasses(): Set> = + setOf(MinecraftModelFG2::class.java, MinecraftModelFG3::class.java, MinecraftModelNG7::class.java, MinecraftModelNMD::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 MinecraftModelData) { + 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(MinecraftModelFG2Handler, MinecraftModelFG3Handler, MinecraftModelNG7Handler, MinecraftModelNMDHandler) + } +} Index: src/main/kotlin/platform/minecraft/gradle/datahandler/MinecraftModelDataHandler.kt =================================================================== --- src/main/kotlin/platform/minecraft/gradle/datahandler/MinecraftModelDataHandler.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/gradle/datahandler/MinecraftModelDataHandler.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.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 MinecraftModelDataHandler { + fun build(gradleModule: IdeaModule, node: DataNode, resolverCtx: ProjectResolverContext) +} Index: src/main/kotlin/platform/minecraft/gradle/datahandler/MinecraftModelFG2Handler.kt =================================================================== --- src/main/kotlin/platform/minecraft/gradle/datahandler/MinecraftModelFG2Handler.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/gradle/datahandler/MinecraftModelFG2Handler.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,78 @@ +/* + * 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.datahandler + +import com.demonwav.mcdev.platform.minecraft.MinecraftModuleSettings +import com.demonwav.mcdev.platform.minecraft.gradle.MinecraftModelData +import com.demonwav.mcdev.platform.minecraft.gradle.tooling.MinecraftModelFG2 +import com.demonwav.mcdev.platform.minecraft.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 MinecraftModelFG2Handler : MinecraftModelDataHandler { + + override fun build( + gradleModule: IdeaModule, + node: DataNode, + resolverCtx: ProjectResolverContext, + ) { + val data = resolverCtx.getExtraProject(gradleModule, MinecraftModelFG2::class.java) ?: return + + val state = MinecraftModuleSettings.State( + data.minecraftVersion, + data.mcpVersion, + data.mappingFiles.find { it.endsWith("mcp-srg.srg") }, + SrgType.SRG, + ) + + val modelData = MinecraftModelData( + node.data, + state, + null, + null, + ) + + node.createChild( + MinecraftModelData.KEY, + MinecraftModelData( + node.data, + MinecraftModuleSettings.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(MinecraftModelData.KEY, modelData.copy(module = childData)) + } + } + } +} Index: src/main/kotlin/platform/minecraft/gradle/datahandler/MinecraftModelFG3Handler.kt =================================================================== --- src/main/kotlin/platform/minecraft/gradle/datahandler/MinecraftModelFG3Handler.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/gradle/datahandler/MinecraftModelFG3Handler.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,98 @@ +/* + * 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.datahandler + +import com.demonwav.mcdev.platform.minecraft.MinecraftModuleSettings +import com.demonwav.mcdev.platform.minecraft.at.AtFileType +import com.demonwav.mcdev.platform.minecraft.gradle.MinecraftModelData +import com.demonwav.mcdev.platform.minecraft.gradle.tooling.MinecraftModelFG3 +import com.demonwav.mcdev.platform.minecraft.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 MinecraftModelFG3Handler : MinecraftModelDataHandler { + + override fun build( + gradleModule: IdeaModule, + node: DataNode, + resolverCtx: ProjectResolverContext, + ) { + val data = resolverCtx.getExtraProject(gradleModule, MinecraftModelFG3::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 = MinecraftModuleSettings.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 = MinecraftModelData(node.data, state, taskName, data.accessTransformers) + node.createChild(MinecraftModelData.KEY, modelData) + + for (child in node.children) { + val childData = child.data + if (childData is GradleSourceSetData) { + child.createChild(MinecraftModelData.KEY, modelData.copy(module = childData)) + } + } + } +} Index: src/main/kotlin/platform/minecraft/gradle/datahandler/MinecraftModelNG7Handler.kt =================================================================== --- src/main/kotlin/platform/minecraft/gradle/datahandler/MinecraftModelNG7Handler.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/gradle/datahandler/MinecraftModelNG7Handler.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,77 @@ +/* + * 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.datahandler + +import com.demonwav.mcdev.platform.minecraft.MinecraftModuleSettings +import com.demonwav.mcdev.platform.minecraft.at.AtFileType +import com.demonwav.mcdev.platform.minecraft.gradle.MinecraftModelData +import com.demonwav.mcdev.platform.minecraft.gradle.tooling.MinecraftModelNG7 +import com.demonwav.mcdev.platform.minecraft.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 MinecraftModelNG7Handler : MinecraftModelDataHandler { + + override fun build( + gradleModule: IdeaModule, + node: DataNode, + resolverCtx: ProjectResolverContext, + ) { + val data = resolverCtx.getExtraProject(gradleModule, MinecraftModelNG7::class.java) ?: return + + val state = MinecraftModuleSettings.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 = MinecraftModelData(node.data, state, null, data.accessTransformers) + node.createChild(MinecraftModelData.KEY, modelData) + + for (child in node.children) { + val childData = child.data + if (childData is GradleSourceSetData) { + child.createChild(MinecraftModelData.KEY, modelData.copy(module = childData)) + } + } + } +} Index: src/main/kotlin/platform/minecraft/gradle/datahandler/MinecraftModelNMDHandler.kt =================================================================== --- src/main/kotlin/platform/minecraft/gradle/datahandler/MinecraftModelNMDHandler.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/gradle/datahandler/MinecraftModelNMDHandler.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,83 @@ +/* + * 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.datahandler + +import com.demonwav.mcdev.platform.minecraft.MinecraftModuleSettings +import com.demonwav.mcdev.platform.minecraft.at.AtFileType +import com.demonwav.mcdev.platform.minecraft.gradle.MinecraftModelData +import com.demonwav.mcdev.platform.minecraft.gradle.tooling.MinecraftModelNMD +import com.demonwav.mcdev.platform.minecraft.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 MinecraftModelNMDHandler : MinecraftModelDataHandler { + + override fun build( + gradleModule: IdeaModule, + node: DataNode, + resolverCtx: ProjectResolverContext, + ) { + val data = resolverCtx.getExtraProject(gradleModule, MinecraftModelNMD::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 = MinecraftModuleSettings.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 = MinecraftModelData(node.data, state, null, data.accessTransformers) + node.createChild(MinecraftModelData.KEY, modelData) + + for (child in node.children) { + val childData = child.data + if (childData is GradleSourceSetData) { + child.createChild(MinecraftModelData.KEY, modelData.copy(module = childData)) + } + } + } +} Index: src/main/kotlin/platform/minecraft/inspections/StackEmptyInspection.kt =================================================================== --- src/main/kotlin/platform/minecraft/inspections/StackEmptyInspection.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/inspections/StackEmptyInspection.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,131 @@ +/* + * 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.inspections + +import com.demonwav.mcdev.platform.minecraft.mappings.getMappedClass +import com.demonwav.mcdev.platform.minecraft.mappings.getMappedField +import com.demonwav.mcdev.platform.minecraft.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/minecraft/mappings/HardcodedYarnToMojmap.kt =================================================================== --- src/main/kotlin/platform/minecraft/mappings/HardcodedYarnToMojmap.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/mappings/HardcodedYarnToMojmap.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.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/minecraft/mappings/HasCustomNamedMappings.kt =================================================================== --- src/main/kotlin/platform/minecraft/mappings/HasCustomNamedMappings.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/mappings/HasCustomNamedMappings.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.mappings + +interface HasCustomNamedMappings { + val namedToMojangManager: MappingsManager? +} Index: src/main/kotlin/platform/minecraft/mappings/Mappings.kt =================================================================== --- src/main/kotlin/platform/minecraft/mappings/Mappings.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/mappings/Mappings.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,139 @@ +/* + * 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.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/minecraft/mappings/MappingsManager.kt =================================================================== --- src/main/kotlin/platform/minecraft/mappings/MappingsManager.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/mappings/MappingsManager.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,100 @@ +/* + * 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.mappings + +import com.demonwav.mcdev.facet.MinecraftFacet +import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType +import com.demonwav.mcdev.platform.minecraft.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, MinecraftModuleType)?.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/minecraft/navigation/SrgMemberChooseByNameContributor.kt =================================================================== --- src/main/kotlin/platform/minecraft/navigation/SrgMemberChooseByNameContributor.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/navigation/SrgMemberChooseByNameContributor.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,103 @@ +/* + * 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.navigation + +import com.demonwav.mcdev.facet.MinecraftFacet +import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType +import com.demonwav.mcdev.platform.minecraft.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 minecraftModule = MinecraftFacet.getInstance(module, MinecraftModuleType) ?: continue + srgMap = minecraftModule.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/minecraft/srg/McpUnscrambler.kt =================================================================== --- src/main/kotlin/platform/minecraft/srg/McpUnscrambler.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/srg/McpUnscrambler.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,38 @@ +/* + * 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.srg + +import com.demonwav.mcdev.platform.minecraft.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/minecraft/srg/SrgMemberReference.kt =================================================================== --- src/main/kotlin/platform/minecraft/srg/SrgMemberReference.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/srg/SrgMemberReference.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.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/minecraft/srg/SrgParser.kt =================================================================== --- src/main/kotlin/platform/minecraft/srg/SrgParser.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/srg/SrgParser.kt (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.srg + +import com.demonwav.mcdev.platform.minecraft.mappings.Mappings +import java.nio.file.Path + +interface SrgParser { + fun parseSrg(path: Path): Mappings +} Index: src/main/kotlin/platform/minecraft/srg/SrgType.kt =================================================================== --- src/main/kotlin/platform/minecraft/srg/SrgType.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/srg/SrgType.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.srg + +enum class SrgType(val srgParser: SrgParser) { + SRG(StandardSrgParser), + TSRG(TinySrgParser), + ; +} Index: src/main/kotlin/platform/minecraft/srg/StandardSrgParser.kt =================================================================== --- src/main/kotlin/platform/minecraft/srg/StandardSrgParser.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/srg/StandardSrgParser.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,61 @@ +/* + * 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.srg + +import com.demonwav.mcdev.platform.minecraft.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/minecraft/srg/TinySrgParser.kt =================================================================== --- src/main/kotlin/platform/minecraft/srg/TinySrgParser.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/srg/TinySrgParser.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,183 @@ +/* + * 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.srg + +import com.demonwav.mcdev.platform.minecraft.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/minecraft/util/MinecraftConstants.kt =================================================================== --- src/main/kotlin/platform/minecraft/util/MinecraftConstants.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/util/MinecraftConstants.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.util + +object MinecraftConstants { + + 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/minecraft/vanillagradle/VanillaGradleData.kt =================================================================== --- src/main/kotlin/platform/minecraft/vanillagradle/VanillaGradleData.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/vanillagradle/VanillaGradleData.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.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/minecraft/vanillagradle/VanillaGradleDataService.kt =================================================================== --- src/main/kotlin/platform/minecraft/vanillagradle/VanillaGradleDataService.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/vanillagradle/VanillaGradleDataService.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,43 @@ +/* + * 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.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/minecraft/vanillagradle/VanillaGradleDecompileSourceProvider.kt =================================================================== --- src/main/kotlin/platform/minecraft/vanillagradle/VanillaGradleDecompileSourceProvider.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/vanillagradle/VanillaGradleDecompileSourceProvider.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,97 @@ +/* + * 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.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/minecraft/vanillagradle/VanillaGradleProjectResolverExtension.kt =================================================================== --- src/main/kotlin/platform/minecraft/vanillagradle/VanillaGradleProjectResolverExtension.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/main/kotlin/platform/minecraft/vanillagradle/VanillaGradleProjectResolverExtension.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.vanillagradle + +import com.demonwav.mcdev.platform.minecraft.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/toml/platform/forge/inspections/ModsTomlValidationInspection.kt =================================================================== --- src/main/kotlin/toml/platform/forge/inspections/ModsTomlValidationInspection.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/main/kotlin/toml/platform/forge/inspections/ModsTomlValidationInspection.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -28,7 +28,7 @@ import com.demonwav.mcdev.toml.tomlType import com.demonwav.mcdev.toml.unquoteKey import com.demonwav.mcdev.util.SemanticVersion -import com.demonwav.mcdev.util.findMcpModule +import com.demonwav.mcdev.util.findMinecraftModule import com.intellij.codeInspection.InspectionManager import com.intellij.codeInspection.LocalInspectionTool import com.intellij.codeInspection.ProblemDescriptor @@ -90,7 +90,7 @@ } val forgeVersion = runCatching { - keyValue.findMcpModule()?.getSettings()?.platformVersion?.let(SemanticVersion::parse) + keyValue.findMinecraftModule()?.getSettings()?.platformVersion?.let(SemanticVersion::parse) }.getOrNull() val minVersion = ForgeConstants.DISPLAY_TEST_MANIFEST_VERSION if (forgeVersion != null && forgeVersion < minVersion) { @@ -115,7 +115,7 @@ } "clientSideOnly" -> { val forgeVersion = runCatching { - keyValue.findMcpModule()?.getSettings()?.platformVersion?.let(SemanticVersion::parse) + keyValue.findMinecraftModule()?.getSettings()?.platformVersion?.let(SemanticVersion::parse) }.getOrNull() val minVersion = ForgeConstants.CLIENT_ONLY_MANIFEST_VERSION if (forgeVersion != null && forgeVersion < minVersion) { Index: src/main/kotlin/translations/TranslationEditorNotificationProvider.kt =================================================================== --- src/main/kotlin/translations/TranslationEditorNotificationProvider.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/main/kotlin/translations/TranslationEditorNotificationProvider.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -24,7 +24,7 @@ import com.demonwav.mcdev.translations.sorting.Ordering import com.demonwav.mcdev.translations.sorting.TranslationSorter import com.demonwav.mcdev.util.applyWriteAction -import com.demonwav.mcdev.util.findMcpModule +import com.demonwav.mcdev.util.findMinecraftModule import com.demonwav.mcdev.util.mcDomain import com.intellij.notification.Notification import com.intellij.notification.NotificationType @@ -60,15 +60,15 @@ return null } - val hasMcpModule = file.findPsiFile(project)?.findMcpModule() != null + val hasMinecraftModule = file.findPsiFile(project)?.findMinecraftModule() != null return Function { - createNotificationPanel(missingTranslations, hasMcpModule, file, project) + createNotificationPanel(missingTranslations, hasMinecraftModule, file, project) } } private fun createNotificationPanel( missingTranslations: Sequence, - hasMcpModule: Boolean, + hasMinecraftModule: Boolean, file: VirtualFile, project: Project ): InfoPanel { @@ -86,8 +86,8 @@ EditorNotifications.updateAll() } - if (!hasMcpModule) { - // TranslationSorter.query requires an MCP module to work + if (!hasMinecraftModule) { + // TranslationSorter.query requires a Minecraft module to work return@createActionLabel } Index: src/main/kotlin/translations/identification/TranslationAnnotationsLocationProvider.kt =================================================================== --- src/main/kotlin/translations/identification/TranslationAnnotationsLocationProvider.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/main/kotlin/translations/identification/TranslationAnnotationsLocationProvider.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -20,7 +20,7 @@ package com.demonwav.mcdev.translations.identification -import com.demonwav.mcdev.platform.mcp.framework.MCP_LIBRARY_KIND +import com.demonwav.mcdev.platform.minecraft.framework.MINECRAFT_LIBRARY_KIND import com.intellij.codeInsight.externalAnnotation.location.AnnotationsLocation import com.intellij.codeInsight.externalAnnotation.location.AnnotationsLocationProvider import com.intellij.openapi.project.Project @@ -38,7 +38,7 @@ ): Collection { val isMinecraftLibrary = LibraryPresentationManager.getInstance().isLibraryOfKind( library.getFiles(OrderRootType.CLASSES).toList(), - MCP_LIBRARY_KIND + MINECRAFT_LIBRARY_KIND ) if (isMinecraftLibrary) { return listOf(TranslationExternalAnnotationsArtifactsResolver.Util.fakeMavenLocation) Index: src/main/kotlin/translations/identification/TranslationIdentifier.kt =================================================================== --- src/main/kotlin/translations/identification/TranslationIdentifier.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/main/kotlin/translations/identification/TranslationIdentifier.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -20,8 +20,8 @@ package com.demonwav.mcdev.translations.identification -import com.demonwav.mcdev.platform.mcp.mappings.getMappedClass -import com.demonwav.mcdev.platform.mcp.mappings.getMappedMethod +import com.demonwav.mcdev.platform.minecraft.mappings.getMappedClass +import com.demonwav.mcdev.platform.minecraft.mappings.getMappedMethod import com.demonwav.mcdev.translations.DeprecatedTranslations import com.demonwav.mcdev.translations.TranslationConstants import com.demonwav.mcdev.translations.identification.TranslationInstance.FormattingError Index: src/main/kotlin/translations/inspections/TranslationInspection.kt =================================================================== --- src/main/kotlin/translations/inspections/TranslationInspection.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/main/kotlin/translations/inspections/TranslationInspection.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -20,7 +20,7 @@ package com.demonwav.mcdev.translations.inspections -import com.demonwav.mcdev.platform.mcp.McpModuleType +import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType import com.intellij.codeInspection.InspectionManager import com.intellij.codeInspection.LocalInspectionTool import com.intellij.codeInspection.ProblemDescriptor @@ -32,7 +32,7 @@ protected abstract fun buildVisitor(holder: ProblemsHolder): PsiElementVisitor final override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { - if (McpModuleType.isInModule(holder.file)) { + if (MinecraftModuleType.isInModule(holder.file)) { return buildVisitor(holder) } @@ -40,7 +40,7 @@ } final override fun processFile(file: PsiFile, manager: InspectionManager): List { - return if (McpModuleType.isInModule(file)) { + return if (MinecraftModuleType.isInModule(file)) { super.processFile(file, manager) } else { listOf() Index: src/main/kotlin/translations/inspections/WrongTypeInTranslationArgsInspection.kt =================================================================== --- src/main/kotlin/translations/inspections/WrongTypeInTranslationArgsInspection.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/main/kotlin/translations/inspections/WrongTypeInTranslationArgsInspection.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -20,8 +20,8 @@ package com.demonwav.mcdev.translations.inspections -import com.demonwav.mcdev.platform.mcp.mappings.getMappedClass -import com.demonwav.mcdev.platform.mcp.mappings.getMappedMethod +import com.demonwav.mcdev.platform.minecraft.mappings.getMappedClass +import com.demonwav.mcdev.platform.minecraft.mappings.getMappedMethod import com.demonwav.mcdev.translations.identification.TranslationIdentifier import com.demonwav.mcdev.util.findModule import com.intellij.codeInsight.intention.FileModifier Index: src/main/kotlin/translations/intentions/ConvertToTranslationIntention.kt =================================================================== --- src/main/kotlin/translations/intentions/ConvertToTranslationIntention.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/main/kotlin/translations/intentions/ConvertToTranslationIntention.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -21,7 +21,7 @@ package com.demonwav.mcdev.translations.intentions import com.demonwav.mcdev.TranslationSettings -import com.demonwav.mcdev.platform.mcp.mappings.getMappedMethodCall +import com.demonwav.mcdev.platform.minecraft.mappings.getMappedMethodCall import com.demonwav.mcdev.translations.TranslationFiles import com.demonwav.mcdev.util.findModule import com.demonwav.mcdev.util.runWriteAction Index: src/main/kotlin/util/ModuleDebugRunConfigurationExtension.kt =================================================================== --- src/main/kotlin/util/ModuleDebugRunConfigurationExtension.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/main/kotlin/util/ModuleDebugRunConfigurationExtension.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -21,7 +21,7 @@ package com.demonwav.mcdev.util import com.demonwav.mcdev.facet.MinecraftFacet -import com.demonwav.mcdev.platform.mcp.McpModuleType +import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType import com.intellij.execution.RunConfigurationExtension import com.intellij.execution.configurations.DebuggingRunnerData import com.intellij.execution.configurations.JavaParameters @@ -66,11 +66,11 @@ attachToProcess(handler, module) } is GradleRunConfiguration -> { - // Loose way to confirm we are in an MCP project, this is fine for now because we don't rely on specific + // Loose way to confirm we are in a Minecraft project, this is fine for now because we don't rely on specific // information to ungrab (like MC version) // Ideally we would find the module matching the run's sourceSet as defined in the build script val module = configuration.project.modules.firstOrNull { - MinecraftFacet.getInstance(it)?.isOfType(McpModuleType) == true + MinecraftFacet.getInstance(it)?.isOfType(MinecraftModuleType) == true } ?: return attachToProcess(handler, module) } Index: src/main/kotlin/util/psi-utils.kt =================================================================== --- src/main/kotlin/util/psi-utils.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/main/kotlin/util/psi-utils.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -21,8 +21,8 @@ package com.demonwav.mcdev.util import com.demonwav.mcdev.facet.MinecraftFacet -import com.demonwav.mcdev.platform.mcp.McpModule -import com.demonwav.mcdev.platform.mcp.McpModuleType +import com.demonwav.mcdev.platform.minecraft.MinecraftModule +import com.demonwav.mcdev.platform.minecraft.MinecraftModuleType import com.demonwav.mcdev.platform.mixin.handlers.desugar.DesugarUtil import com.intellij.debugger.impl.DebuggerUtilsEx import com.intellij.ide.highlighter.JavaClassFileType @@ -336,7 +336,7 @@ } } -fun PsiElement.findMcpModule() = this.cached { +fun PsiElement.findMinecraftModule() = this.cached { val file = containingFile?.viewProvider?.virtualFile ?: return@cached null val index = ProjectFileIndex.getInstance(project) val modules = if (index.isInLibrary(file)) { @@ -350,13 +350,13 @@ sequenceOf(this.findModule()) } - modules.firstNotNullOfOrNull { it?.findMcpModule() } + modules.firstNotNullOfOrNull { it?.findMinecraftModule() } } -private fun Module.findMcpModule(): McpModule? { - var result: McpModule? = null +private fun Module.findMinecraftModule(): MinecraftModule? { + var result: MinecraftModule? = null ModuleUtilCore.visitMeAndDependentModules(this) { - result = MinecraftFacet.getInstance(it, McpModuleType) + result = MinecraftFacet.getInstance(it, MinecraftModuleType) result == null } return result @@ -364,7 +364,7 @@ val PsiElement.mcVersion: SemanticVersion? get() = this.cached { - findMcpModule()?.let { + findMinecraftModule()?.let { SemanticVersion.tryParse(it.getSettings().minecraftVersion ?: return@let null) } } Index: src/main/resources/META-INF/plugin.xml =================================================================== --- src/main/resources/META-INF/plugin.xml (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/main/resources/META-INF/plugin.xml (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -355,7 +355,7 @@ * Forge * NeoForge * Fabric - * MCP + * Minecraft * Mixin * Velocity * BungeeCord @@ -641,63 +641,63 @@ implementation="com.demonwav.mcdev.platform.architectury.framework.ArchitecturyPresentationProvider"/> - + - - + + + implementation="com.demonwav.mcdev.platform.minecraft.vanillagradle.VanillaGradleDataService"/> + implementation="com.demonwav.mcdev.platform.minecraft.framework.MinecraftPresentationProvider"/> - + + implementation="com.demonwav.mcdev.platform.minecraft.fabricloom.FabricLoomDecompileSourceProvider"/> + implementation="com.demonwav.mcdev.platform.minecraft.vanillagradle.VanillaGradleDecompileSourceProvider"/> + implementationClass="com.demonwav.mcdev.platform.minecraft.at.AtParserDefinition"/> - + implementationClass="com.demonwav.mcdev.platform.minecraft.at.AtSyntaxHighlighterFactory"/> + - + implementationClass="com.demonwav.mcdev.platform.minecraft.at.AtCommenter"/> + - - + implementationClass="com.demonwav.mcdev.platform.minecraft.at.completion.AtCompletionContributor"/> + + + implementationClass="com.demonwav.mcdev.platform.minecraft.ct.CtParserDefinition"/> - - - + implementationClass="com.demonwav.mcdev.platform.minecraft.ct.CtSyntaxHighlighterFactory"/> + + + + implementationClass="com.demonwav.mcdev.platform.minecraft.ct.CtCompletionContributor"/> + implementation="com.demonwav.mcdev.platform.minecraft.ct.fixes.CopyAwAccessibleEntryFix$Provider"/> - + - - + implementation="com.demonwav.mcdev.platform.minecraft.navigation.SrgMemberChooseByNameContributor"/> + + @@ -1049,35 +1049,35 @@ implementationClass="com.demonwav.mcdev.platform.fabric.inspection.FabricEntrypointsInspection"/> - + + implementationClass="com.demonwav.mcdev.platform.minecraft.at.AtUsageInspection"/> + implementationClass="com.demonwav.mcdev.platform.minecraft.inspections.StackEmptyInspection"/> + implementationClass="com.demonwav.mcdev.platform.minecraft.ct.inspections.DuplicateAwEntryInspection"/> + implementationClass="com.demonwav.mcdev.platform.minecraft.ct.inspections.UnknownCtNamespaceInspection"/> @@ -1665,10 +1665,10 @@ - + - + implementation="com.demonwav.mcdev.platform.minecraft.vanillagradle.VanillaGradleProjectResolverExtension"/> + @@ -1734,27 +1734,27 @@ popup="true"> - - - - - @@ -1768,7 +1768,7 @@ text="Minecraft Class" description="Create skeleton classes used in Minecraft Mods"> - Index: src/test/kotlin/platform/mcp/at/AtCommenterTest.kt =================================================================== --- src/test/kotlin/platform/mcp/at/AtCommenterTest.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/test/kotlin/platform/mcp/at/AtCommenterTest.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.at - -import com.demonwav.mcdev.framework.CommenterTest -import com.demonwav.mcdev.framework.EdtInterceptor -import com.demonwav.mcdev.framework.ProjectBuilder -import org.intellij.lang.annotations.Language -import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith - -@ExtendWith(EdtInterceptor::class) -@DisplayName("Access Transformer Commenter Tests") -class AtCommenterTest : CommenterTest() { - - private fun doTest( - @Language("Access Transformers") before: String, - @Language("Access Transformers") after: String, - ) { - doTest(before, after, "_at.cfg", ProjectBuilder::at) - } - - @Test - @DisplayName("Single Line Comment Test") - fun singleLineCommentTest() = doTest( - """ - public net.minecraft.entity.Entity field_190534_ay # fire - public net.minecraft.entity.Entity field_70152_a # nextEntityID - """, - """ - #public net.minecraft.entity.Entity field_190534_ay # fire - public net.minecraft.entity.Entity field_70152_a # nextEntityID - """, - ) - - @Test - @DisplayName("Multi Line Comment Test") - fun multiLineCommentTest() = doTest( - """ - public net.minecraft.command.CommandHandler func_71559_a([Ljava/lang/String;)[Ljava/lang/String; # dropFirstString - public net.minecraft.command.CommandHandler func_82370_a(Lnet/minecraft/command/ICommand;[Ljava/lang/String;)I # getUsernameIndex - public net.minecraft.command.EntitySelector func_82381_h(Ljava/lang/String;)Ljava/util/Map; # getArgumentMap - """, - """ - #public net.minecraft.command.CommandHandler func_71559_a([Ljava/lang/String;)[Ljava/lang/String; # dropFirstString - #public net.minecraft.command.CommandHandler func_82370_a(Lnet/minecraft/command/ICommand;[Ljava/lang/String;)I # getUsernameIndex - public net.minecraft.command.EntitySelector func_82381_h(Ljava/lang/String;)Ljava/util/Map; # getArgumentMap - """, - ) - - @Test - @DisplayName("Single Line Uncomment Test") - fun singleLineUncommentTest() = doTest( - """ - public net.minecraft.entity.Entity field_70152_a # nextEntityID - public net.minecraft.entity.Entity func_190531_bD()I - #public net.minecraft.entity.EntityHanging func_174859_a(Lnet/minecraft/util/EnumFacing;)V # updateFacingWithBoundingBox - #public net.minecraft.entity.EntityList field_180126_g # stringToIDMapping - """, - """ - public net.minecraft.entity.Entity field_70152_a # nextEntityID - #public net.minecraft.entity.Entity func_190531_bD()I - #public net.minecraft.entity.EntityHanging func_174859_a(Lnet/minecraft/util/EnumFacing;)V # updateFacingWithBoundingBox - #public net.minecraft.entity.EntityList field_180126_g # stringToIDMapping - """, - ) - - @Test - @DisplayName("Multi Line Uncomment") - fun multiLineUncommentTest() = doTest( - """ - #public net.minecraft.entity.EntityLivingBase field_70752_e # potionsNeedUpdate - #public net.minecraft.entity.EntityLivingBase field_70755_b # entityLivingToAttack - public net.minecraft.entity.EntityLivingBase func_184583_d(Lnet/minecraft/util/DamageSource;)Z # canBlockDamageSource - """, - """ - public net.minecraft.entity.EntityLivingBase field_70752_e # potionsNeedUpdate - public net.minecraft.entity.EntityLivingBase field_70755_b # entityLivingToAttack - public net.minecraft.entity.EntityLivingBase func_184583_d(Lnet/minecraft/util/DamageSource;)Z # canBlockDamageSource - """, - ) - - @Test - @DisplayName("Multi Line Comment With Comments Test") - fun multiLineCommentWithCommentsTest() = doTest( - """ - public net.minecraft.entity.EntityLivingBase field_184621_as # HAND_STATES - #public net.minecraft.entity.EntityLivingBase field_184632_c # HEALTH - public net.minecraft.entity.EntityLivingBase field_184633_f # POTION_EFFECTS - #public net.minecraft.entity.EntityLivingBase field_184634_g # HIDE_PARTICLES - #public net.minecraft.entity.EntityLivingBase field_184635_h # ARROW_COUNT_IN_ENTITY - """, - """ - public net.minecraft.entity.EntityLivingBase field_184621_as # HAND_STATES - ##public net.minecraft.entity.EntityLivingBase field_184632_c # HEALTH - #public net.minecraft.entity.EntityLivingBase field_184633_f # POTION_EFFECTS - ##public net.minecraft.entity.EntityLivingBase field_184634_g # HIDE_PARTICLES - ##public net.minecraft.entity.EntityLivingBase field_184635_h # ARROW_COUNT_IN_ENTITY - """, - ) -} Index: src/test/kotlin/platform/mcp/at/AtLexerTest.kt =================================================================== --- src/test/kotlin/platform/mcp/at/AtLexerTest.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/test/kotlin/platform/mcp/at/AtLexerTest.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 - -import com.demonwav.mcdev.framework.testLexer -import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Test - -@DisplayName("Access Transformer Lexing Tests") -class AtLexerTest { - - @Test - @DisplayName("Spigot Mappings Lexing Test") - fun spigotMappingsTest() = testLexer("lexer/fixtures/spigot_mappings_at.cfg", AtLexerAdapter()) -} Index: src/test/kotlin/platform/mcp/at/AtParsingTest.kt =================================================================== --- src/test/kotlin/platform/mcp/at/AtParsingTest.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/test/kotlin/platform/mcp/at/AtParsingTest.kt (revision 533678d90250de5d335d0d7478938b9a27b2b056) @@ -1,58 +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.framework.EdtInterceptor -import com.demonwav.mcdev.framework.ProjectBuilder -import com.demonwav.mcdev.framework.ProjectBuilderTest -import com.demonwav.mcdev.framework.testParser -import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith - -@ExtendWith(EdtInterceptor::class) -@DisplayName("Access Transformer Parsing Tests") -class AtParsingTest : ProjectBuilderTest() { - - @Test - @DisplayName("Asterisks Parsing Test") - fun asterisksTest() = testParser("parser/fixtures/asterisks_at.cfg", ProjectBuilder::at) - - @Test - @DisplayName("Comments Parsing Test") - fun commentsTest() = testParser("parser/fixtures/comments_at.cfg", ProjectBuilder::at) - - @Test - @DisplayName("Fields Parsing Test") - fun fieldsTest() = testParser("parser/fixtures/fields_at.cfg", ProjectBuilder::at) - - @Test - @DisplayName("Funcs Parsing Test") - fun funcsTest() = testParser("parser/fixtures/funcs_at.cfg", ProjectBuilder::at) - - @Test - @DisplayName("Keywords Parsing Test") - fun keywordsTest() = testParser("parser/fixtures/keywords_at.cfg", ProjectBuilder::at) - - @Test - @DisplayName("Empty Value Parsing Test") - fun noValueTest() = testParser("parser/fixtures/no_value_at.cfg", ProjectBuilder::at) -} Index: src/test/kotlin/platform/minecraft/at/AtCommenterTest.kt =================================================================== --- src/test/kotlin/platform/minecraft/at/AtCommenterTest.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/test/kotlin/platform/minecraft/at/AtCommenterTest.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.at + +import com.demonwav.mcdev.framework.CommenterTest +import com.demonwav.mcdev.framework.EdtInterceptor +import com.demonwav.mcdev.framework.ProjectBuilder +import org.intellij.lang.annotations.Language +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(EdtInterceptor::class) +@DisplayName("Access Transformer Commenter Tests") +class AtCommenterTest : CommenterTest() { + + private fun doTest( + @Language("Access Transformers") before: String, + @Language("Access Transformers") after: String, + ) { + doTest(before, after, "_at.cfg", ProjectBuilder::at) + } + + @Test + @DisplayName("Single Line Comment Test") + fun singleLineCommentTest() = doTest( + """ + public net.minecraft.entity.Entity field_190534_ay # fire + public net.minecraft.entity.Entity field_70152_a # nextEntityID + """, + """ + #public net.minecraft.entity.Entity field_190534_ay # fire + public net.minecraft.entity.Entity field_70152_a # nextEntityID + """, + ) + + @Test + @DisplayName("Multi Line Comment Test") + fun multiLineCommentTest() = doTest( + """ + public net.minecraft.command.CommandHandler func_71559_a([Ljava/lang/String;)[Ljava/lang/String; # dropFirstString + public net.minecraft.command.CommandHandler func_82370_a(Lnet/minecraft/command/ICommand;[Ljava/lang/String;)I # getUsernameIndex + public net.minecraft.command.EntitySelector func_82381_h(Ljava/lang/String;)Ljava/util/Map; # getArgumentMap + """, + """ + #public net.minecraft.command.CommandHandler func_71559_a([Ljava/lang/String;)[Ljava/lang/String; # dropFirstString + #public net.minecraft.command.CommandHandler func_82370_a(Lnet/minecraft/command/ICommand;[Ljava/lang/String;)I # getUsernameIndex + public net.minecraft.command.EntitySelector func_82381_h(Ljava/lang/String;)Ljava/util/Map; # getArgumentMap + """, + ) + + @Test + @DisplayName("Single Line Uncomment Test") + fun singleLineUncommentTest() = doTest( + """ + public net.minecraft.entity.Entity field_70152_a # nextEntityID + public net.minecraft.entity.Entity func_190531_bD()I + #public net.minecraft.entity.EntityHanging func_174859_a(Lnet/minecraft/util/EnumFacing;)V # updateFacingWithBoundingBox + #public net.minecraft.entity.EntityList field_180126_g # stringToIDMapping + """, + """ + public net.minecraft.entity.Entity field_70152_a # nextEntityID + #public net.minecraft.entity.Entity func_190531_bD()I + #public net.minecraft.entity.EntityHanging func_174859_a(Lnet/minecraft/util/EnumFacing;)V # updateFacingWithBoundingBox + #public net.minecraft.entity.EntityList field_180126_g # stringToIDMapping + """, + ) + + @Test + @DisplayName("Multi Line Uncomment") + fun multiLineUncommentTest() = doTest( + """ + #public net.minecraft.entity.EntityLivingBase field_70752_e # potionsNeedUpdate + #public net.minecraft.entity.EntityLivingBase field_70755_b # entityLivingToAttack + public net.minecraft.entity.EntityLivingBase func_184583_d(Lnet/minecraft/util/DamageSource;)Z # canBlockDamageSource + """, + """ + public net.minecraft.entity.EntityLivingBase field_70752_e # potionsNeedUpdate + public net.minecraft.entity.EntityLivingBase field_70755_b # entityLivingToAttack + public net.minecraft.entity.EntityLivingBase func_184583_d(Lnet/minecraft/util/DamageSource;)Z # canBlockDamageSource + """, + ) + + @Test + @DisplayName("Multi Line Comment With Comments Test") + fun multiLineCommentWithCommentsTest() = doTest( + """ + public net.minecraft.entity.EntityLivingBase field_184621_as # HAND_STATES + #public net.minecraft.entity.EntityLivingBase field_184632_c # HEALTH + public net.minecraft.entity.EntityLivingBase field_184633_f # POTION_EFFECTS + #public net.minecraft.entity.EntityLivingBase field_184634_g # HIDE_PARTICLES + #public net.minecraft.entity.EntityLivingBase field_184635_h # ARROW_COUNT_IN_ENTITY + """, + """ + public net.minecraft.entity.EntityLivingBase field_184621_as # HAND_STATES + ##public net.minecraft.entity.EntityLivingBase field_184632_c # HEALTH + #public net.minecraft.entity.EntityLivingBase field_184633_f # POTION_EFFECTS + ##public net.minecraft.entity.EntityLivingBase field_184634_g # HIDE_PARTICLES + ##public net.minecraft.entity.EntityLivingBase field_184635_h # ARROW_COUNT_IN_ENTITY + """, + ) +} Index: src/test/kotlin/platform/minecraft/at/AtLexerTest.kt =================================================================== --- src/test/kotlin/platform/minecraft/at/AtLexerTest.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/test/kotlin/platform/minecraft/at/AtLexerTest.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 + +import com.demonwav.mcdev.framework.testLexer +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test + +@DisplayName("Access Transformer Lexing Tests") +class AtLexerTest { + + @Test + @DisplayName("Spigot Mappings Lexing Test") + fun spigotMappingsTest() = testLexer("lexer/fixtures/spigot_mappings_at.cfg", AtLexerAdapter()) +} Index: src/test/kotlin/platform/minecraft/at/AtParsingTest.kt =================================================================== --- src/test/kotlin/platform/minecraft/at/AtParsingTest.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/test/kotlin/platform/minecraft/at/AtParsingTest.kt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,58 @@ +/* + * 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.framework.EdtInterceptor +import com.demonwav.mcdev.framework.ProjectBuilder +import com.demonwav.mcdev.framework.ProjectBuilderTest +import com.demonwav.mcdev.framework.testParser +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(EdtInterceptor::class) +@DisplayName("Access Transformer Parsing Tests") +class AtParsingTest : ProjectBuilderTest() { + + @Test + @DisplayName("Asterisks Parsing Test") + fun asterisksTest() = testParser("parser/fixtures/asterisks_at.cfg", ProjectBuilder::at) + + @Test + @DisplayName("Comments Parsing Test") + fun commentsTest() = testParser("parser/fixtures/comments_at.cfg", ProjectBuilder::at) + + @Test + @DisplayName("Fields Parsing Test") + fun fieldsTest() = testParser("parser/fixtures/fields_at.cfg", ProjectBuilder::at) + + @Test + @DisplayName("Funcs Parsing Test") + fun funcsTest() = testParser("parser/fixtures/funcs_at.cfg", ProjectBuilder::at) + + @Test + @DisplayName("Keywords Parsing Test") + fun keywordsTest() = testParser("parser/fixtures/keywords_at.cfg", ProjectBuilder::at) + + @Test + @DisplayName("Empty Value Parsing Test") + fun noValueTest() = testParser("parser/fixtures/no_value_at.cfg", ProjectBuilder::at) +} Index: src/test/resources/com/demonwav/mcdev/platform/mcp/at/lexer/fixtures/spigot_mappings_at.cfg =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/mcp/at/lexer/fixtures/spigot_mappings_at.cfg (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/test/resources/com/demonwav/mcdev/platform/mcp/at/lexer/fixtures/spigot_mappings_at.cfg (revision 533678d90250de5d335d0d7478938b9a27b2b056) @@ -1,214 +0,0 @@ -public net.minecraft.server.EntityPlayer containerCounter -public net.minecraft.server.EntityPlayer nextContainerCounter()V -public net.minecraft.server.ShapelessRecipes ingredients -public net.minecraft.server.EntityVillager$IMerchantRecipeOption -protected bip d -protected bip e -protected bip g -protected bip i #asdf -protected bip j -protected bip a(IZ)F -protected bip b(CZ)F -protected biq * -protected biq *() -public-f net.minecraft.server.WorldType types -public bzf k -public net.minecraft.server.AdvancementDataWorld DESERIALIZER -protected net.minecraft.server.MinecraftServer ab -public bja f -public bja g -public net.minecraft.server.RecipiesShield$Decoration -public net.minecraft.server.PacketStatusOutServerInfo a -public-f bje i -public-f bje j -protected bzu a(Lnet/minecraft/server/ItemStack;)I -public bjd d()V -public net.minecraft.server.EntityVillager$MerchantRecipeOptionProcess -public net.minecraft.server.EntityVillager$MerchantRecipeOptionEnchant -public net.minecraft.server.EntityVillager$MerchantRecipeOptionBuy -public bjr b -public bjr c -public bjr t -public bjr d -public bjr e -public bjr f -public bjr g -public bjr h -public bsb b(Lnet/minecraft/server/Entity;)V -public bsb c(Lnet/minecraft/server/Entity;)V -public net.minecraft.server.BiomeBigHills *() -public net.minecraft.server.Item a(Z)Lnet/minecraft/server/Item; -public net.minecraft.server.Item setMaxDurability(I)Lnet/minecraft/server/Item; -public net.minecraft.server.ContainerAnvil k -public net.minecraft.server.RecipesBanner$AddRecipe -public net.minecraft.server.BiomeIcePlains *() -public net.minecraft.server.TileEntity a(Ljava/lang/String;Ljava/lang/Class;)V -public+f net.minecraft.server.ShapedRecipes width -public+f net.minecraft.server.ShapedRecipes items -public+f net.minecraft.server.ShapedRecipes height -public net.minecraft.server.WorldGenStrongholdPieces$WorldGenStrongholdPiece -protected net.minecraft.server.EntityHuman d -protected net.minecraft.server.EntityHuman e -public net.minecraft.server.EntityHuman closeInventory()V -public net.minecraft.server.EntityHuman a(Lnet/minecraft/server/EntityItem;)Lnet/minecraft/server/ItemStack; -public net.minecraft.server.EntityInsentient targetSelector -public net.minecraft.server.EntityInsentient goalSelector -public net.minecraft.server.EnumDirection n -public net.minecraft.server.EnumDirection o -public net.minecraft.server.BiomePlains *() -protected net.minecraft.server.RegistryBlockID a -protected net.minecraft.server.RegistryBlockID b -public net.minecraft.server.RecipesBanner$DuplicateRecipe -public net.minecraft.server.BlockStateList$BlockData -protected net.minecraft.server.BlockStateList$BlockData c -protected net.minecraft.server.BlockStateList$BlockData (Lnet/minecraft/block/Block;Lcom/google/common/collect/ImmutableMap;)V -public net.minecraft.server.Block j()Lnet/minecraft/server/Block; -public net.minecraft.server.Block a(Z)Lnet/minecraft/server/Block; -public net.minecraft.server.Block c(F)Lnet/minecraft/server/Block; -public net.minecraft.server.Block b(F)Lnet/minecraft/server/Block; -public net.minecraft.server.Block e(I)Lnet/minecraft/server/Block; -public net.minecraft.server.Block (Lnet/minecraft/block/material/Material;)V -public net.minecraft.server.Block dropExperience(Lnet/minecraft/server/World;Lnet/minecraft/server/BlockPosition;I)V -public net.minecraft.server.Block a(F)Lnet/minecraft/server/Block; -public net.minecraft.server.WorldGenFactory a(Ljava/lang/Class;Ljava/lang/String;)V -public net.minecraft.server.WorldGenFactory b(Ljava/lang/Class;Ljava/lang/String;)V -public net.minecraft.server.RecipeTippedArrow -public net.minecraft.server.WorldServer b(Lnet/minecraft/server/Entity;)V -public net.minecraft.server.WorldServer c(Lnet/minecraft/server/Entity;)V -public blk j -public net.minecraft.server.BlockFire f(Lnet/minecraft/server/Block;)I -public net.minecraft.server.BlockFire e(Lnet/minecraft/server/Block;)I -public net.minecraft.server.WeightedRandom$WeightedRandomChoice a -public net.minecraft.server.EntityVillager$MerchantOptionRandomRange -public net.minecraft.server.EntityVillager$MerchantRecipeOptionSell -protected net.minecraft.server.EntitySkeletonStray p()Lnet/minecraft/server/SoundEffect; -public bud a(Lnet/minecraft/server/EntityItem;)Lnet/minecraft/server/ItemStack; -public net.minecraft.server.World p -public net.minecraft.server.World q -public-f net.minecraft.server.World villages -public net.minecraft.server.World n -public net.minecraft.server.World o -public net.minecraft.server.World E(Lnet/minecraft/server/BlockPosition;)Z -public net.minecraft.server.World isValidLocation(Lnet/minecraft/server/BlockPosition;)Z -public net.minecraft.server.World b(Lnet/minecraft/server/Entity;)V -public net.minecraft.server.World c(Lnet/minecraft/server/Entity;)V -public net.minecraft.server.DataConverterManager d -public net.minecraft.server.BiomeDecorator * -public buk c(IIII)V -public buk c(I)I -public net.minecraft.server.BiomeBase$a *() -public-f net.minecraft.server.WorldGenVillage a -public buq a(Lnet/minecraft/server/MinecraftKey;)V -public net.minecraft.server.NBTNumber -protected cgb p -public cgb a -protected cgb r -protected cgb b -protected cgb s -protected cgb g -protected cgb h -protected cgb l -protected cgb m -protected cgb a(Lnet/minecraft/server/Item;)Ljava/util/List; -protected cgb h()V -protected cgb g()V -protected cgb f()V -protected cgb c(Lbvu;)Z -protected cgb b(Lbvu;)Z -protected cgb d(Lnet/minecraft/server/MinecraftKey;)Lnet/minecraft/server/MinecraftKey; -protected cgb a(Lbvv;Lcgd;)V -protected cgb d(Lbvu;)Lbvu; -protected cgb c(Lnet/minecraft/server/MinecraftKey;)Lbvu; -protected cgb a(Ljava/lang/String;)Lnet/minecraft/server/MinecraftKey; -protected cgb a(Lcgd;Lbwd;)V -protected cgb a(Lbvu;)Ljava/util/Set; -protected cgb e()V -protected cgb c()V -protected cgb b()V -protected cgb a(Lnet/minecraft/server/MinecraftKey;)Lbvv; -public net.minecraft.server.PathfinderGoalSelector$PathfinderGoalSelectorItem -protected buv c -protected net.minecraft.server.EntitySkeleton p()Lnet/minecraft/server/SoundEffect; -public net.minecraft.server.BiomeTaiga *() -public net.minecraft.server.BiomeMesa *() -public net.minecraft.server.TileEntityHopper K()Z -protected net.minecraft.server.TileEntityHopper o()Z -public net.minecraft.server.TileEntityHopper setCooldown(I)V -public bvu c -public bvu d -public bvu i -public bvu f()Ljava/util/List; -private-f net.minecraft.server.LootSelector c -private-f net.minecraft.server.LootSelector d -protected net.minecraft.server.PortalTravelAgent b -protected net.minecraft.server.PortalTravelAgent world -protected net.minecraft.server.PortalTravelAgent c -protected net.minecraft.server.RecipeItemStack ([Lnet/minecraft/item/ItemStack;)V -public chm d -public net.minecraft.server.PacketPlayOutBlockChange block -public net.minecraft.server.DamageSource *() -protected net.minecraft.server.EntitySkeletonAbstract p()Lnet/minecraft/server/SoundEffect; -protected net.minecraft.server.EntitySkeletonWither p()Lnet/minecraft/server/SoundEffect; -public net.minecraft.server.DedicatedServer serverCommandQueue -public net.minecraft.server.WorldGenVillagePieces$WorldGenVillagePiece -public net.minecraft.server.BiomeBase *() -public net.minecraft.server.ChunkProviderServer chunkGenerator -public net.minecraft.server.ChunkProviderServer world -public net.minecraft.server.ChunkProviderServer chunkLoader -public net.minecraft.server.ChunkProviderServer chunks -public net.minecraft.server.ChunkRegionLoader d -public caa a(Lccg;)Z -public bwx n -public bwx o -private-f net.minecraft.server.PlayerChunk dirtyBlocks -private-f net.minecraft.server.ChunkProviderGenerate A -private-f net.minecraft.server.ChunkProviderGenerate B -private-f net.minecraft.server.ChunkProviderGenerate C -private-f net.minecraft.server.ChunkProviderGenerate v -private-f net.minecraft.server.ChunkProviderGenerate w -private-f net.minecraft.server.ChunkProviderGenerate x -private-f net.minecraft.server.ChunkProviderGenerate y -private-f net.minecraft.server.ChunkProviderGenerate j -private-f net.minecraft.server.ChunkProviderGenerate z -private-f net.minecraft.server.ChunkProviderGenerate k -private-f net.minecraft.server.ChunkProviderGenerate l -private-f net.minecraft.server.ChunkProviderGenerate m -public net.minecraft.server.PotionBrewer a(Lnet/minecraft/server/ItemPotion;)V -public net.minecraft.server.PotionBrewer a(Lnet/minecraft/server/PotionRegistry;Lnet/minecraft/server/Item;Lnet/minecraft/server/PotionRegistry;)V -public net.minecraft.server.PotionBrewer a(Lnet/minecraft/server/ItemPotion;Lnet/minecraft/server/Item;Lnet/minecraft/server/ItemPotion;)V -public net.minecraft.server.PotionBrewer a(Lnet/minecraft/server/PotionRegistry;Lnet/minecraft/server/RecipeItemStack;Lnet/minecraft/server/PotionRegistry;)V -public net.minecraft.server.CriterionTriggers a(Lnet/minecraft/server/CriterionTrigger;)Lnet/minecraft/server/CriterionTrigger; -public net.minecraft.server.EntityVillager$MerchantRecipeOptionBook -public-f net.minecraft.server.CreativeModeTab a -private-f net.minecraft.server.ChunkProviderHell u -private-f net.minecraft.server.ChunkProviderHell v -public-f net.minecraft.server.ChunkProviderHell g -private-f net.minecraft.server.ChunkProviderHell w -public-f net.minecraft.server.ChunkProviderHell h -private-f net.minecraft.server.ChunkProviderHell x -private-f net.minecraft.server.ChunkProviderHell I -private-f net.minecraft.server.ChunkProviderHell y -private-f net.minecraft.server.ChunkProviderHell J -public net.minecraft.server.BiomeSavanna *() -private-f net.minecraft.server.ChunkProviderTheEnd p -private-f net.minecraft.server.ChunkProviderTheEnd i -private-f net.minecraft.server.ChunkProviderTheEnd j -private-f net.minecraft.server.ChunkProviderTheEnd k -private-f net.minecraft.server.ChunkProviderTheEnd o -public net.minecraft.server.BiomeForest *() -public net.minecraft.server.EntityTrackerEntry trackedPlayers -public+f net.minecraft.server.WorldGenStronghold a -public net.minecraft.server.PotionBrewer$PredicatedCombination -public net.minecraft.server.WorldLoader a -public net.minecraft.server.MinecraftKey a(Ljava/lang/String;)[Ljava/lang/String; -default net.minecraft.server.ItemStack damage -public net.minecraft.server.EntityExperienceOrb value -public net.minecraft.server.EntityMinecartContainer b -public bib Q -public bib aE -public bib a(Lnet/minecraft/server/ItemStack;Lnet/minecraft/server/TileEntity;)Lnet/minecraft/server/ItemStack; -public bib a(II)V -public bib ar()V -public bib a(Lcdr;)V -public net.minecraft.server.PathfinderGoalSelector b -public net.minecraft.server.PlayerSelector c(Ljava/lang/String;)Ljava/lang/String; Index: src/test/resources/com/demonwav/mcdev/platform/mcp/at/lexer/fixtures/spigot_mappings_at.txt =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/mcp/at/lexer/fixtures/spigot_mappings_at.txt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/test/resources/com/demonwav/mcdev/platform/mcp/at/lexer/fixtures/spigot_mappings_at.txt (revision 533678d90250de5d335d0d7478938b9a27b2b056) @@ -1,1546 +0,0 @@ -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityPlayer') -WHITE_SPACE (' ') -NAME_ELEMENT ('containerCounter') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityPlayer') -WHITE_SPACE (' ') -NAME_ELEMENT ('nextContainerCounter') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ShapelessRecipes') -WHITE_SPACE (' ') -NAME_ELEMENT ('ingredients') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityVillager$IMerchantRecipeOption') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bip') -WHITE_SPACE (' ') -NAME_ELEMENT ('d') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bip') -WHITE_SPACE (' ') -NAME_ELEMENT ('e') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bip') -WHITE_SPACE (' ') -NAME_ELEMENT ('g') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bip') -WHITE_SPACE (' ') -NAME_ELEMENT ('i') -WHITE_SPACE (' ') -COMMENT ('#asdf') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bip') -WHITE_SPACE (' ') -NAME_ELEMENT ('j') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bip') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -PRIMITIVE ('I') -PRIMITIVE ('Z') -CLOSE_PAREN (')') -PRIMITIVE ('F') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bip') -WHITE_SPACE (' ') -NAME_ELEMENT ('b') -OPEN_PAREN ('(') -PRIMITIVE ('C') -PRIMITIVE ('Z') -CLOSE_PAREN (')') -PRIMITIVE ('F') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('biq') -WHITE_SPACE (' ') -ASTERISK_ELEMENT ('*') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('biq') -WHITE_SPACE (' ') -ASTERISK_ELEMENT ('*()') -CRLF ('\n') -KEYWORD_ELEMENT ('public-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.WorldType') -WHITE_SPACE (' ') -NAME_ELEMENT ('types') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bzf') -WHITE_SPACE (' ') -NAME_ELEMENT ('k') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.AdvancementDataWorld') -WHITE_SPACE (' ') -NAME_ELEMENT ('DESERIALIZER') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.MinecraftServer') -WHITE_SPACE (' ') -NAME_ELEMENT ('ab') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bja') -WHITE_SPACE (' ') -NAME_ELEMENT ('f') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bja') -WHITE_SPACE (' ') -NAME_ELEMENT ('g') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.RecipiesShield$Decoration') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.PacketStatusOutServerInfo') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -CRLF ('\n') -KEYWORD_ELEMENT ('public-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bje') -WHITE_SPACE (' ') -NAME_ELEMENT ('i') -CRLF ('\n') -KEYWORD_ELEMENT ('public-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bje') -WHITE_SPACE (' ') -NAME_ELEMENT ('j') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bzu') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/ItemStack;') -CLOSE_PAREN (')') -PRIMITIVE ('I') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bjd') -WHITE_SPACE (' ') -NAME_ELEMENT ('d') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityVillager$MerchantRecipeOptionProcess') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityVillager$MerchantRecipeOptionEnchant') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityVillager$MerchantRecipeOptionBuy') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bjr') -WHITE_SPACE (' ') -NAME_ELEMENT ('b') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bjr') -WHITE_SPACE (' ') -NAME_ELEMENT ('c') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bjr') -WHITE_SPACE (' ') -NAME_ELEMENT ('t') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bjr') -WHITE_SPACE (' ') -NAME_ELEMENT ('d') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bjr') -WHITE_SPACE (' ') -NAME_ELEMENT ('e') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bjr') -WHITE_SPACE (' ') -NAME_ELEMENT ('f') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bjr') -WHITE_SPACE (' ') -NAME_ELEMENT ('g') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bjr') -WHITE_SPACE (' ') -NAME_ELEMENT ('h') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bsb') -WHITE_SPACE (' ') -NAME_ELEMENT ('b') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/Entity;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bsb') -WHITE_SPACE (' ') -NAME_ELEMENT ('c') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/Entity;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeBigHills') -WHITE_SPACE (' ') -ASTERISK_ELEMENT ('*()') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.Item') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -PRIMITIVE ('Z') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/Item;') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.Item') -WHITE_SPACE (' ') -NAME_ELEMENT ('setMaxDurability') -OPEN_PAREN ('(') -PRIMITIVE ('I') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/Item;') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ContainerAnvil') -WHITE_SPACE (' ') -NAME_ELEMENT ('k') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.RecipesBanner$AddRecipe') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeIcePlains') -WHITE_SPACE (' ') -ASTERISK_ELEMENT ('*()') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.TileEntity') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Ljava/lang/String;') -CLASS_VALUE ('Ljava/lang/Class;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public+f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ShapedRecipes') -WHITE_SPACE (' ') -NAME_ELEMENT ('width') -CRLF ('\n') -KEYWORD_ELEMENT ('public+f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ShapedRecipes') -WHITE_SPACE (' ') -NAME_ELEMENT ('items') -CRLF ('\n') -KEYWORD_ELEMENT ('public+f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ShapedRecipes') -WHITE_SPACE (' ') -NAME_ELEMENT ('height') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.WorldGenStrongholdPieces$WorldGenStrongholdPiece') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityHuman') -WHITE_SPACE (' ') -NAME_ELEMENT ('d') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityHuman') -WHITE_SPACE (' ') -NAME_ELEMENT ('e') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityHuman') -WHITE_SPACE (' ') -NAME_ELEMENT ('closeInventory') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityHuman') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/EntityItem;') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/ItemStack;') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityInsentient') -WHITE_SPACE (' ') -NAME_ELEMENT ('targetSelector') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityInsentient') -WHITE_SPACE (' ') -NAME_ELEMENT ('goalSelector') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EnumDirection') -WHITE_SPACE (' ') -NAME_ELEMENT ('n') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EnumDirection') -WHITE_SPACE (' ') -NAME_ELEMENT ('o') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.BiomePlains') -WHITE_SPACE (' ') -ASTERISK_ELEMENT ('*()') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.RegistryBlockID') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.RegistryBlockID') -WHITE_SPACE (' ') -NAME_ELEMENT ('b') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.RecipesBanner$DuplicateRecipe') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.BlockStateList$BlockData') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.BlockStateList$BlockData') -WHITE_SPACE (' ') -NAME_ELEMENT ('c') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.BlockStateList$BlockData') -WHITE_SPACE (' ') -NAME_ELEMENT ('') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/block/Block;') -CLASS_VALUE ('Lcom/google/common/collect/ImmutableMap;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.Block') -WHITE_SPACE (' ') -NAME_ELEMENT ('j') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/Block;') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.Block') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -PRIMITIVE ('Z') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/Block;') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.Block') -WHITE_SPACE (' ') -NAME_ELEMENT ('c') -OPEN_PAREN ('(') -PRIMITIVE ('F') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/Block;') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.Block') -WHITE_SPACE (' ') -NAME_ELEMENT ('b') -OPEN_PAREN ('(') -PRIMITIVE ('F') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/Block;') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.Block') -WHITE_SPACE (' ') -NAME_ELEMENT ('e') -OPEN_PAREN ('(') -PRIMITIVE ('I') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/Block;') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.Block') -WHITE_SPACE (' ') -NAME_ELEMENT ('') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/block/material/Material;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.Block') -WHITE_SPACE (' ') -NAME_ELEMENT ('dropExperience') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/World;') -CLASS_VALUE ('Lnet/minecraft/server/BlockPosition;') -PRIMITIVE ('I') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.Block') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -PRIMITIVE ('F') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/Block;') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.WorldGenFactory') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Ljava/lang/Class;') -CLASS_VALUE ('Ljava/lang/String;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.WorldGenFactory') -WHITE_SPACE (' ') -NAME_ELEMENT ('b') -OPEN_PAREN ('(') -CLASS_VALUE ('Ljava/lang/Class;') -CLASS_VALUE ('Ljava/lang/String;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.RecipeTippedArrow') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.WorldServer') -WHITE_SPACE (' ') -NAME_ELEMENT ('b') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/Entity;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.WorldServer') -WHITE_SPACE (' ') -NAME_ELEMENT ('c') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/Entity;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('blk') -WHITE_SPACE (' ') -NAME_ELEMENT ('j') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.BlockFire') -WHITE_SPACE (' ') -NAME_ELEMENT ('f') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/Block;') -CLOSE_PAREN (')') -PRIMITIVE ('I') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.BlockFire') -WHITE_SPACE (' ') -NAME_ELEMENT ('e') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/Block;') -CLOSE_PAREN (')') -PRIMITIVE ('I') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.WeightedRandom$WeightedRandomChoice') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityVillager$MerchantOptionRandomRange') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityVillager$MerchantRecipeOptionSell') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntitySkeletonStray') -WHITE_SPACE (' ') -NAME_ELEMENT ('p') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/SoundEffect;') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bud') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/EntityItem;') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/ItemStack;') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.World') -WHITE_SPACE (' ') -NAME_ELEMENT ('p') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.World') -WHITE_SPACE (' ') -NAME_ELEMENT ('q') -CRLF ('\n') -KEYWORD_ELEMENT ('public-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.World') -WHITE_SPACE (' ') -NAME_ELEMENT ('villages') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.World') -WHITE_SPACE (' ') -NAME_ELEMENT ('n') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.World') -WHITE_SPACE (' ') -NAME_ELEMENT ('o') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.World') -WHITE_SPACE (' ') -NAME_ELEMENT ('E') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/BlockPosition;') -CLOSE_PAREN (')') -PRIMITIVE ('Z') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.World') -WHITE_SPACE (' ') -NAME_ELEMENT ('isValidLocation') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/BlockPosition;') -CLOSE_PAREN (')') -PRIMITIVE ('Z') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.World') -WHITE_SPACE (' ') -NAME_ELEMENT ('b') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/Entity;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.World') -WHITE_SPACE (' ') -NAME_ELEMENT ('c') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/Entity;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.DataConverterManager') -WHITE_SPACE (' ') -NAME_ELEMENT ('d') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeDecorator') -WHITE_SPACE (' ') -ASTERISK_ELEMENT ('*') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('buk') -WHITE_SPACE (' ') -NAME_ELEMENT ('c') -OPEN_PAREN ('(') -PRIMITIVE ('I') -PRIMITIVE ('I') -PRIMITIVE ('I') -PRIMITIVE ('I') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('buk') -WHITE_SPACE (' ') -NAME_ELEMENT ('c') -OPEN_PAREN ('(') -PRIMITIVE ('I') -CLOSE_PAREN (')') -PRIMITIVE ('I') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeBase$a') -WHITE_SPACE (' ') -ASTERISK_ELEMENT ('*()') -CRLF ('\n') -KEYWORD_ELEMENT ('public-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.WorldGenVillage') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('buq') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/MinecraftKey;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.NBTNumber') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('p') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('r') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('b') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('s') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('g') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('h') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('l') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('m') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/Item;') -CLOSE_PAREN (')') -CLASS_VALUE ('Ljava/util/List;') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('h') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('g') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('f') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('c') -OPEN_PAREN ('(') -CLASS_VALUE ('Lbvu;') -CLOSE_PAREN (')') -PRIMITIVE ('Z') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('b') -OPEN_PAREN ('(') -CLASS_VALUE ('Lbvu;') -CLOSE_PAREN (')') -PRIMITIVE ('Z') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('d') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/MinecraftKey;') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/MinecraftKey;') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Lbvv;') -CLASS_VALUE ('Lcgd;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('d') -OPEN_PAREN ('(') -CLASS_VALUE ('Lbvu;') -CLOSE_PAREN (')') -CLASS_VALUE ('Lbvu;') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('c') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/MinecraftKey;') -CLOSE_PAREN (')') -CLASS_VALUE ('Lbvu;') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Ljava/lang/String;') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/MinecraftKey;') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Lcgd;') -CLASS_VALUE ('Lbwd;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Lbvu;') -CLOSE_PAREN (')') -CLASS_VALUE ('Ljava/util/Set;') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('e') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('c') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('b') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('cgb') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/MinecraftKey;') -CLOSE_PAREN (')') -CLASS_VALUE ('Lbvv;') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.PathfinderGoalSelector$PathfinderGoalSelectorItem') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('buv') -WHITE_SPACE (' ') -NAME_ELEMENT ('c') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntitySkeleton') -WHITE_SPACE (' ') -NAME_ELEMENT ('p') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/SoundEffect;') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeTaiga') -WHITE_SPACE (' ') -ASTERISK_ELEMENT ('*()') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeMesa') -WHITE_SPACE (' ') -ASTERISK_ELEMENT ('*()') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.TileEntityHopper') -WHITE_SPACE (' ') -NAME_ELEMENT ('K') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -PRIMITIVE ('Z') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.TileEntityHopper') -WHITE_SPACE (' ') -NAME_ELEMENT ('o') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -PRIMITIVE ('Z') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.TileEntityHopper') -WHITE_SPACE (' ') -NAME_ELEMENT ('setCooldown') -OPEN_PAREN ('(') -PRIMITIVE ('I') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bvu') -WHITE_SPACE (' ') -NAME_ELEMENT ('c') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bvu') -WHITE_SPACE (' ') -NAME_ELEMENT ('d') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bvu') -WHITE_SPACE (' ') -NAME_ELEMENT ('i') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bvu') -WHITE_SPACE (' ') -NAME_ELEMENT ('f') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -CLASS_VALUE ('Ljava/util/List;') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.LootSelector') -WHITE_SPACE (' ') -NAME_ELEMENT ('c') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.LootSelector') -WHITE_SPACE (' ') -NAME_ELEMENT ('d') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.PortalTravelAgent') -WHITE_SPACE (' ') -NAME_ELEMENT ('b') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.PortalTravelAgent') -WHITE_SPACE (' ') -NAME_ELEMENT ('world') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.PortalTravelAgent') -WHITE_SPACE (' ') -NAME_ELEMENT ('c') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.RecipeItemStack') -WHITE_SPACE (' ') -NAME_ELEMENT ('') -OPEN_PAREN ('(') -CLASS_VALUE ('[Lnet/minecraft/item/ItemStack;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('chm') -WHITE_SPACE (' ') -NAME_ELEMENT ('d') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.PacketPlayOutBlockChange') -WHITE_SPACE (' ') -NAME_ELEMENT ('block') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.DamageSource') -WHITE_SPACE (' ') -ASTERISK_ELEMENT ('*()') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntitySkeletonAbstract') -WHITE_SPACE (' ') -NAME_ELEMENT ('p') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/SoundEffect;') -CRLF ('\n') -KEYWORD_ELEMENT ('protected') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntitySkeletonWither') -WHITE_SPACE (' ') -NAME_ELEMENT ('p') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/SoundEffect;') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.DedicatedServer') -WHITE_SPACE (' ') -NAME_ELEMENT ('serverCommandQueue') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.WorldGenVillagePieces$WorldGenVillagePiece') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeBase') -WHITE_SPACE (' ') -ASTERISK_ELEMENT ('*()') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderServer') -WHITE_SPACE (' ') -NAME_ELEMENT ('chunkGenerator') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderServer') -WHITE_SPACE (' ') -NAME_ELEMENT ('world') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderServer') -WHITE_SPACE (' ') -NAME_ELEMENT ('chunkLoader') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderServer') -WHITE_SPACE (' ') -NAME_ELEMENT ('chunks') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkRegionLoader') -WHITE_SPACE (' ') -NAME_ELEMENT ('d') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('caa') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Lccg;') -CLOSE_PAREN (')') -PRIMITIVE ('Z') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bwx') -WHITE_SPACE (' ') -NAME_ELEMENT ('n') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bwx') -WHITE_SPACE (' ') -NAME_ELEMENT ('o') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.PlayerChunk') -WHITE_SPACE (' ') -NAME_ELEMENT ('dirtyBlocks') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') -WHITE_SPACE (' ') -NAME_ELEMENT ('A') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') -WHITE_SPACE (' ') -NAME_ELEMENT ('B') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') -WHITE_SPACE (' ') -NAME_ELEMENT ('C') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') -WHITE_SPACE (' ') -NAME_ELEMENT ('v') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') -WHITE_SPACE (' ') -NAME_ELEMENT ('w') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') -WHITE_SPACE (' ') -NAME_ELEMENT ('x') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') -WHITE_SPACE (' ') -NAME_ELEMENT ('y') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') -WHITE_SPACE (' ') -NAME_ELEMENT ('j') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') -WHITE_SPACE (' ') -NAME_ELEMENT ('z') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') -WHITE_SPACE (' ') -NAME_ELEMENT ('k') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') -WHITE_SPACE (' ') -NAME_ELEMENT ('l') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') -WHITE_SPACE (' ') -NAME_ELEMENT ('m') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.PotionBrewer') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/ItemPotion;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.PotionBrewer') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/PotionRegistry;') -CLASS_VALUE ('Lnet/minecraft/server/Item;') -CLASS_VALUE ('Lnet/minecraft/server/PotionRegistry;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.PotionBrewer') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/ItemPotion;') -CLASS_VALUE ('Lnet/minecraft/server/Item;') -CLASS_VALUE ('Lnet/minecraft/server/ItemPotion;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.PotionBrewer') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/PotionRegistry;') -CLASS_VALUE ('Lnet/minecraft/server/RecipeItemStack;') -CLASS_VALUE ('Lnet/minecraft/server/PotionRegistry;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.CriterionTriggers') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/CriterionTrigger;') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/CriterionTrigger;') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityVillager$MerchantRecipeOptionBook') -CRLF ('\n') -KEYWORD_ELEMENT ('public-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.CreativeModeTab') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') -WHITE_SPACE (' ') -NAME_ELEMENT ('u') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') -WHITE_SPACE (' ') -NAME_ELEMENT ('v') -CRLF ('\n') -KEYWORD_ELEMENT ('public-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') -WHITE_SPACE (' ') -NAME_ELEMENT ('g') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') -WHITE_SPACE (' ') -NAME_ELEMENT ('w') -CRLF ('\n') -KEYWORD_ELEMENT ('public-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') -WHITE_SPACE (' ') -NAME_ELEMENT ('h') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') -WHITE_SPACE (' ') -NAME_ELEMENT ('x') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') -WHITE_SPACE (' ') -NAME_ELEMENT ('I') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') -WHITE_SPACE (' ') -NAME_ELEMENT ('y') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') -WHITE_SPACE (' ') -NAME_ELEMENT ('J') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeSavanna') -WHITE_SPACE (' ') -ASTERISK_ELEMENT ('*()') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderTheEnd') -WHITE_SPACE (' ') -NAME_ELEMENT ('p') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderTheEnd') -WHITE_SPACE (' ') -NAME_ELEMENT ('i') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderTheEnd') -WHITE_SPACE (' ') -NAME_ELEMENT ('j') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderTheEnd') -WHITE_SPACE (' ') -NAME_ELEMENT ('k') -CRLF ('\n') -KEYWORD_ELEMENT ('private-f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderTheEnd') -WHITE_SPACE (' ') -NAME_ELEMENT ('o') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeForest') -WHITE_SPACE (' ') -ASTERISK_ELEMENT ('*()') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityTrackerEntry') -WHITE_SPACE (' ') -NAME_ELEMENT ('trackedPlayers') -CRLF ('\n') -KEYWORD_ELEMENT ('public+f') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.WorldGenStronghold') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.PotionBrewer$PredicatedCombination') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.WorldLoader') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.MinecraftKey') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Ljava/lang/String;') -CLOSE_PAREN (')') -CLASS_VALUE ('[Ljava/lang/String;') -CRLF ('\n') -KEYWORD_ELEMENT ('default') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.ItemStack') -WHITE_SPACE (' ') -NAME_ELEMENT ('damage') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityExperienceOrb') -WHITE_SPACE (' ') -NAME_ELEMENT ('value') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.EntityMinecartContainer') -WHITE_SPACE (' ') -NAME_ELEMENT ('b') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bib') -WHITE_SPACE (' ') -NAME_ELEMENT ('Q') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bib') -WHITE_SPACE (' ') -NAME_ELEMENT ('aE') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bib') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Lnet/minecraft/server/ItemStack;') -CLASS_VALUE ('Lnet/minecraft/server/TileEntity;') -CLOSE_PAREN (')') -CLASS_VALUE ('Lnet/minecraft/server/ItemStack;') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bib') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -PRIMITIVE ('I') -PRIMITIVE ('I') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bib') -WHITE_SPACE (' ') -NAME_ELEMENT ('ar') -OPEN_PAREN ('(') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('bib') -WHITE_SPACE (' ') -NAME_ELEMENT ('a') -OPEN_PAREN ('(') -CLASS_VALUE ('Lcdr;') -CLOSE_PAREN (')') -PRIMITIVE ('V') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.PathfinderGoalSelector') -WHITE_SPACE (' ') -NAME_ELEMENT ('b') -CRLF ('\n') -KEYWORD_ELEMENT ('public') -WHITE_SPACE (' ') -CLASS_NAME_ELEMENT ('net.minecraft.server.PlayerSelector') -WHITE_SPACE (' ') -NAME_ELEMENT ('c') -OPEN_PAREN ('(') -CLASS_VALUE ('Ljava/lang/String;') -CLOSE_PAREN (')') -CLASS_VALUE ('Ljava/lang/String;') Index: src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/asterisks_at.cfg =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/asterisks_at.cfg (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/asterisks_at.cfg (revision 533678d90250de5d335d0d7478938b9a27b2b056) @@ -1,2 +0,0 @@ -public net.minecraft.network.play.client.CPacketPlayer * -public net.minecraft.network.play.client.CPacketResourcePackStatus *() Index: src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/asterisks_at.txt =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/asterisks_at.txt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/asterisks_at.txt (revision 533678d90250de5d335d0d7478938b9a27b2b056) @@ -1,20 +0,0 @@ -Access transformers(0,127) - AtEntryImpl(ENTRY)(0,56) - AtKeywordImpl(KEYWORD)(0,6) - PsiElement(KEYWORD_ELEMENT)('public')(0,6) - PsiWhiteSpace(' ')(6,7) - AtClassNameImpl(CLASS_NAME)(7,54) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.network.play.client.CPacketPlayer')(7,54) - PsiWhiteSpace(' ')(54,55) - AtAsteriskImpl(ASTERISK)(55,56) - PsiElement(ASTERISK_ELEMENT)('*')(55,56) - PsiElement(CRLF)('\n')(56,57) - AtEntryImpl(ENTRY)(57,127) - AtKeywordImpl(KEYWORD)(57,63) - PsiElement(KEYWORD_ELEMENT)('public')(57,63) - PsiWhiteSpace(' ')(63,64) - AtClassNameImpl(CLASS_NAME)(64,123) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.network.play.client.CPacketResourcePackStatus')(64,123) - PsiWhiteSpace(' ')(123,124) - AtAsteriskImpl(ASTERISK)(124,127) - PsiElement(ASTERISK_ELEMENT)('*()')(124,127) Index: src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/comments_at.cfg =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/comments_at.cfg (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/comments_at.cfg (revision 533678d90250de5d335d0d7478938b9a27b2b056) @@ -1,6 +0,0 @@ -# Comment one -# Comment two -private-f net.minecraft.network.ServerStatusResponse$PlayerCountData field_151334_b # Comment after method -public-f net.minecraft.item.ItemStack # Comment after no value -public net.minecraft.network.play.client.CPacketPlayer * # Comment after asterisk -public net.minecraft.item.ItemTool field_77864_a # Comment after field Index: src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/comments_at.txt =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/comments_at.txt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/comments_at.txt (revision 533678d90250de5d335d0d7478938b9a27b2b056) @@ -1,49 +0,0 @@ -Access transformers(0,350) - PsiComment(COMMENT)('# Comment one')(0,13) - PsiElement(CRLF)('\n')(13,14) - PsiComment(COMMENT)('# Comment two')(14,27) - PsiElement(CRLF)('\n')(27,28) - AtEntryImpl(ENTRY)(28,111) - AtKeywordImpl(KEYWORD)(28,37) - PsiElement(KEYWORD_ELEMENT)('private-f')(28,37) - PsiWhiteSpace(' ')(37,38) - AtClassNameImpl(CLASS_NAME)(38,96) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.network.ServerStatusResponse$PlayerCountData')(38,96) - PsiWhiteSpace(' ')(96,97) - AtFieldNameImpl(FIELD_NAME)(97,111) - PsiElement(NAME_ELEMENT)('field_151334_b')(97,111) - PsiWhiteSpace(' ')(111,112) - PsiComment(COMMENT)('# Comment after method')(112,134) - PsiElement(CRLF)('\n')(134,135) - AtEntryImpl(ENTRY)(135,172) - AtKeywordImpl(KEYWORD)(135,143) - PsiElement(KEYWORD_ELEMENT)('public-f')(135,143) - PsiWhiteSpace(' ')(143,144) - AtClassNameImpl(CLASS_NAME)(144,172) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.item.ItemStack')(144,172) - PsiWhiteSpace(' ')(172,173) - PsiComment(COMMENT)('# Comment after no value')(173,197) - PsiElement(CRLF)('\n')(197,198) - AtEntryImpl(ENTRY)(198,254) - AtKeywordImpl(KEYWORD)(198,204) - PsiElement(KEYWORD_ELEMENT)('public')(198,204) - PsiWhiteSpace(' ')(204,205) - AtClassNameImpl(CLASS_NAME)(205,252) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.network.play.client.CPacketPlayer')(205,252) - PsiWhiteSpace(' ')(252,253) - AtAsteriskImpl(ASTERISK)(253,254) - PsiElement(ASTERISK_ELEMENT)('*')(253,254) - PsiWhiteSpace(' ')(254,255) - PsiComment(COMMENT)('# Comment after asterisk')(255,279) - PsiElement(CRLF)('\n')(279,280) - AtEntryImpl(ENTRY)(280,328) - AtKeywordImpl(KEYWORD)(280,286) - PsiElement(KEYWORD_ELEMENT)('public')(280,286) - PsiWhiteSpace(' ')(286,287) - AtClassNameImpl(CLASS_NAME)(287,314) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.item.ItemTool')(287,314) - PsiWhiteSpace(' ')(314,315) - AtFieldNameImpl(FIELD_NAME)(315,328) - PsiElement(NAME_ELEMENT)('field_77864_a')(315,328) - PsiWhiteSpace(' ')(328,329) - PsiComment(COMMENT)('# Comment after field')(329,350) Index: src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/fields_at.cfg =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/fields_at.cfg (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/fields_at.cfg (revision 533678d90250de5d335d0d7478938b9a27b2b056) @@ -1,9 +0,0 @@ -public net.minecraft.entity.player.EntityPlayer field_184827_bp # PLAYER_MODEL_FLAG -public net.minecraft.entity.player.EntityPlayer field_184828_bq # MAIN_HAND -public net.minecraft.entity.player.EntityPlayer field_184829_a # field_184829_a -public net.minecraft.entity.player.EntityPlayer field_184830_b # PLAYER_SCORE -public net.minecraft.entity.player.EntityPlayer field_71078_a # theInventoryEnderChest -public net.minecraft.entity.player.EntityPlayerMP field_71144_ck # lastExperience -public net.minecraft.entity.player.InventoryPlayer field_184440_g # main_inventory -public net.minecraft.entity.player.PlayerCapabilities field_75096_f # flySpeed -public net.minecraft.entity.player.PlayerCapabilities field_75097_g # walkSpeed Index: src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/fields_at.txt =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/fields_at.txt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/fields_at.txt (revision 533678d90250de5d335d0d7478938b9a27b2b056) @@ -1,108 +0,0 @@ -Access transformers(0,728) - AtEntryImpl(ENTRY)(0,63) - AtKeywordImpl(KEYWORD)(0,6) - PsiElement(KEYWORD_ELEMENT)('public')(0,6) - PsiWhiteSpace(' ')(6,7) - AtClassNameImpl(CLASS_NAME)(7,47) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.EntityPlayer')(7,47) - PsiWhiteSpace(' ')(47,48) - AtFieldNameImpl(FIELD_NAME)(48,63) - PsiElement(NAME_ELEMENT)('field_184827_bp')(48,63) - PsiWhiteSpace(' ')(63,64) - PsiComment(COMMENT)('# PLAYER_MODEL_FLAG')(64,83) - PsiElement(CRLF)('\n')(83,84) - AtEntryImpl(ENTRY)(84,147) - AtKeywordImpl(KEYWORD)(84,90) - PsiElement(KEYWORD_ELEMENT)('public')(84,90) - PsiWhiteSpace(' ')(90,91) - AtClassNameImpl(CLASS_NAME)(91,131) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.EntityPlayer')(91,131) - PsiWhiteSpace(' ')(131,132) - AtFieldNameImpl(FIELD_NAME)(132,147) - PsiElement(NAME_ELEMENT)('field_184828_bq')(132,147) - PsiWhiteSpace(' ')(147,148) - PsiComment(COMMENT)('# MAIN_HAND')(148,159) - PsiElement(CRLF)('\n')(159,160) - AtEntryImpl(ENTRY)(160,222) - AtKeywordImpl(KEYWORD)(160,166) - PsiElement(KEYWORD_ELEMENT)('public')(160,166) - PsiWhiteSpace(' ')(166,167) - AtClassNameImpl(CLASS_NAME)(167,207) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.EntityPlayer')(167,207) - PsiWhiteSpace(' ')(207,208) - AtFieldNameImpl(FIELD_NAME)(208,222) - PsiElement(NAME_ELEMENT)('field_184829_a')(208,222) - PsiWhiteSpace(' ')(222,223) - PsiComment(COMMENT)('# field_184829_a')(223,239) - PsiElement(CRLF)('\n')(239,240) - AtEntryImpl(ENTRY)(240,302) - AtKeywordImpl(KEYWORD)(240,246) - PsiElement(KEYWORD_ELEMENT)('public')(240,246) - PsiWhiteSpace(' ')(246,247) - AtClassNameImpl(CLASS_NAME)(247,287) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.EntityPlayer')(247,287) - PsiWhiteSpace(' ')(287,288) - AtFieldNameImpl(FIELD_NAME)(288,302) - PsiElement(NAME_ELEMENT)('field_184830_b')(288,302) - PsiWhiteSpace(' ')(302,303) - PsiComment(COMMENT)('# PLAYER_SCORE')(303,317) - PsiElement(CRLF)('\n')(317,318) - AtEntryImpl(ENTRY)(318,379) - AtKeywordImpl(KEYWORD)(318,324) - PsiElement(KEYWORD_ELEMENT)('public')(318,324) - PsiWhiteSpace(' ')(324,325) - AtClassNameImpl(CLASS_NAME)(325,365) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.EntityPlayer')(325,365) - PsiWhiteSpace(' ')(365,366) - AtFieldNameImpl(FIELD_NAME)(366,379) - PsiElement(NAME_ELEMENT)('field_71078_a')(366,379) - PsiWhiteSpace(' ')(379,380) - PsiComment(COMMENT)('# theInventoryEnderChest')(380,404) - PsiElement(CRLF)('\n')(404,405) - AtEntryImpl(ENTRY)(405,469) - AtKeywordImpl(KEYWORD)(405,411) - PsiElement(KEYWORD_ELEMENT)('public')(405,411) - PsiWhiteSpace(' ')(411,412) - AtClassNameImpl(CLASS_NAME)(412,454) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.EntityPlayerMP')(412,454) - PsiWhiteSpace(' ')(454,455) - AtFieldNameImpl(FIELD_NAME)(455,469) - PsiElement(NAME_ELEMENT)('field_71144_ck')(455,469) - PsiWhiteSpace(' ')(469,470) - PsiComment(COMMENT)('# lastExperience')(470,486) - PsiElement(CRLF)('\n')(486,487) - AtEntryImpl(ENTRY)(487,552) - AtKeywordImpl(KEYWORD)(487,493) - PsiElement(KEYWORD_ELEMENT)('public')(487,493) - PsiWhiteSpace(' ')(493,494) - AtClassNameImpl(CLASS_NAME)(494,537) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.InventoryPlayer')(494,537) - PsiWhiteSpace(' ')(537,538) - AtFieldNameImpl(FIELD_NAME)(538,552) - PsiElement(NAME_ELEMENT)('field_184440_g')(538,552) - PsiWhiteSpace(' ')(552,553) - PsiComment(COMMENT)('# main_inventory')(553,569) - PsiElement(CRLF)('\n')(569,570) - AtEntryImpl(ENTRY)(570,637) - AtKeywordImpl(KEYWORD)(570,576) - PsiElement(KEYWORD_ELEMENT)('public')(570,576) - PsiWhiteSpace(' ')(576,577) - AtClassNameImpl(CLASS_NAME)(577,623) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.PlayerCapabilities')(577,623) - PsiWhiteSpace(' ')(623,624) - AtFieldNameImpl(FIELD_NAME)(624,637) - PsiElement(NAME_ELEMENT)('field_75096_f')(624,637) - PsiWhiteSpace(' ')(637,638) - PsiComment(COMMENT)('# flySpeed')(638,648) - PsiElement(CRLF)('\n')(648,649) - AtEntryImpl(ENTRY)(649,716) - AtKeywordImpl(KEYWORD)(649,655) - PsiElement(KEYWORD_ELEMENT)('public')(649,655) - PsiWhiteSpace(' ')(655,656) - AtClassNameImpl(CLASS_NAME)(656,702) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.PlayerCapabilities')(656,702) - PsiWhiteSpace(' ')(702,703) - AtFieldNameImpl(FIELD_NAME)(703,716) - PsiElement(NAME_ELEMENT)('field_75097_g')(703,716) - PsiWhiteSpace(' ')(716,717) - PsiComment(COMMENT)('# walkSpeed')(717,728) Index: src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/funcs_at.cfg =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/funcs_at.cfg (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/funcs_at.cfg (revision 533678d90250de5d335d0d7478938b9a27b2b056) @@ -1,20 +0,0 @@ -public net.minecraft.server.management.UserList func_152680_h()V # removeExpired -public net.minecraft.server.management.UserList func_152681_a(Lcom/mojang/authlib/GameProfile;)Ljava/lang/String; # getObjectKey -public net.minecraft.server.management.UserList func_152681_a(Ljava/lang/Object;)Ljava/lang/String; # getObjectKey -public net.minecraft.server.management.UserList func_152688_e()Ljava/util/Map; -public net.minecraft.server.management.UserListBans func_152681_a(Lcom/mojang/authlib/GameProfile;)Ljava/lang/String; # getObjectKey -public net.minecraft.server.management.UserListBans func_152681_a(Ljava/lang/Object;)Ljava/lang/String; # getObjectKey -public net.minecraft.server.management.UserListEntry func_152640_f()Ljava/lang/Object; # getValue -public net.minecraft.server.management.UserListIPBans func_152707_c(Ljava/net/SocketAddress;)Ljava/lang/String; # addressToString -public net.minecraft.server.management.UserListOps func_152681_a(Lcom/mojang/authlib/GameProfile;)Ljava/lang/String; # getObjectKey -public net.minecraft.server.management.UserListOps func_152681_a(Ljava/lang/Object;)Ljava/lang/String; # getObjectKey -public net.minecraft.server.management.UserListWhitelist func_152681_a(Lcom/mojang/authlib/GameProfile;)Ljava/lang/String; # getObjectKey -public net.minecraft.server.management.UserListWhitelist func_152681_a(Ljava/lang/Object;)Ljava/lang/String; # getObjectKey -public net.minecraft.util.DamageSource func_151518_m()Lnet/minecraft/util/DamageSource; # setDamageIsAbsolute -public net.minecraft.util.DamageSource func_76348_h()Lnet/minecraft/util/DamageSource; # setDamageBypassesArmor -public net.minecraft.util.DamageSource func_76359_i()Lnet/minecraft/util/DamageSource; # setDamageAllowedInCreativeMode -public net.minecraft.util.DamageSource func_76361_j()Lnet/minecraft/util/DamageSource; # setFireDamage -public net.minecraft.util.DamageSource (Ljava/lang/String;)V # protected DamageSource (String damageTypeIn) -public net.minecraft.world.World func_175663_a(IIIIIIZ)Z # isAreaLoaded -public net.minecraft.server.MinecraftServer func_175584_a(Ljava/lang/String;Lnet/minecraft/world/storage/ISaveHandler;)V # setResourcePackFromWorld -public net.minecraft.tileentity.MobSpawnerBaseLogic func_180613_a(Lnet/minecraft/entity/Entity;Z)Lnet/minecraft/entity/Entity; # spawnNewEntity Index: src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/funcs_at.txt =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/funcs_at.txt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/funcs_at.txt (revision 533678d90250de5d335d0d7478938b9a27b2b056) @@ -1,380 +0,0 @@ -Access transformers(0,2318) - AtEntryImpl(ENTRY)(0,64) - AtKeywordImpl(KEYWORD)(0,6) - PsiElement(KEYWORD_ELEMENT)('public')(0,6) - PsiWhiteSpace(' ')(6,7) - AtClassNameImpl(CLASS_NAME)(7,47) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserList')(7,47) - PsiWhiteSpace(' ')(47,48) - AtFunctionImpl(FUNCTION)(48,64) - AtFuncNameImpl(FUNC_NAME)(48,61) - PsiElement(NAME_ELEMENT)('func_152680_h')(48,61) - PsiElement(OPEN_PAREN)('(')(61,62) - PsiElement(CLOSE_PAREN)(')')(62,63) - AtReturnValueImpl(RETURN_VALUE)(63,64) - PsiElement(PRIMITIVE)('V')(63,64) - PsiWhiteSpace(' ')(64,65) - PsiComment(COMMENT)('# removeExpired')(65,80) - PsiElement(CRLF)('\n')(80,81) - AtEntryImpl(ENTRY)(81,194) - AtKeywordImpl(KEYWORD)(81,87) - PsiElement(KEYWORD_ELEMENT)('public')(81,87) - PsiWhiteSpace(' ')(87,88) - AtClassNameImpl(CLASS_NAME)(88,128) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserList')(88,128) - PsiWhiteSpace(' ')(128,129) - AtFunctionImpl(FUNCTION)(129,194) - AtFuncNameImpl(FUNC_NAME)(129,142) - PsiElement(NAME_ELEMENT)('func_152681_a')(129,142) - PsiElement(OPEN_PAREN)('(')(142,143) - AtArgumentImpl(ARGUMENT)(143,175) - PsiElement(CLASS_VALUE)('Lcom/mojang/authlib/GameProfile;')(143,175) - PsiElement(CLOSE_PAREN)(')')(175,176) - AtReturnValueImpl(RETURN_VALUE)(176,194) - PsiElement(CLASS_VALUE)('Ljava/lang/String;')(176,194) - PsiWhiteSpace(' ')(194,195) - PsiComment(COMMENT)('# getObjectKey')(195,209) - PsiElement(CRLF)('\n')(209,210) - AtEntryImpl(ENTRY)(210,309) - AtKeywordImpl(KEYWORD)(210,216) - PsiElement(KEYWORD_ELEMENT)('public')(210,216) - PsiWhiteSpace(' ')(216,217) - AtClassNameImpl(CLASS_NAME)(217,257) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserList')(217,257) - PsiWhiteSpace(' ')(257,258) - AtFunctionImpl(FUNCTION)(258,309) - AtFuncNameImpl(FUNC_NAME)(258,271) - PsiElement(NAME_ELEMENT)('func_152681_a')(258,271) - PsiElement(OPEN_PAREN)('(')(271,272) - AtArgumentImpl(ARGUMENT)(272,290) - PsiElement(CLASS_VALUE)('Ljava/lang/Object;')(272,290) - PsiElement(CLOSE_PAREN)(')')(290,291) - AtReturnValueImpl(RETURN_VALUE)(291,309) - PsiElement(CLASS_VALUE)('Ljava/lang/String;')(291,309) - PsiWhiteSpace(' ')(309,310) - PsiComment(COMMENT)('# getObjectKey')(310,324) - PsiElement(CRLF)('\n')(324,325) - AtEntryImpl(ENTRY)(325,403) - AtKeywordImpl(KEYWORD)(325,331) - PsiElement(KEYWORD_ELEMENT)('public')(325,331) - PsiWhiteSpace(' ')(331,332) - AtClassNameImpl(CLASS_NAME)(332,372) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserList')(332,372) - PsiWhiteSpace(' ')(372,373) - AtFunctionImpl(FUNCTION)(373,403) - AtFuncNameImpl(FUNC_NAME)(373,386) - PsiElement(NAME_ELEMENT)('func_152688_e')(373,386) - PsiElement(OPEN_PAREN)('(')(386,387) - PsiElement(CLOSE_PAREN)(')')(387,388) - AtReturnValueImpl(RETURN_VALUE)(388,403) - PsiElement(CLASS_VALUE)('Ljava/util/Map;')(388,403) - PsiElement(CRLF)('\n')(403,404) - AtEntryImpl(ENTRY)(404,521) - AtKeywordImpl(KEYWORD)(404,410) - PsiElement(KEYWORD_ELEMENT)('public')(404,410) - PsiWhiteSpace(' ')(410,411) - AtClassNameImpl(CLASS_NAME)(411,455) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserListBans')(411,455) - PsiWhiteSpace(' ')(455,456) - AtFunctionImpl(FUNCTION)(456,521) - AtFuncNameImpl(FUNC_NAME)(456,469) - PsiElement(NAME_ELEMENT)('func_152681_a')(456,469) - PsiElement(OPEN_PAREN)('(')(469,470) - AtArgumentImpl(ARGUMENT)(470,502) - PsiElement(CLASS_VALUE)('Lcom/mojang/authlib/GameProfile;')(470,502) - PsiElement(CLOSE_PAREN)(')')(502,503) - AtReturnValueImpl(RETURN_VALUE)(503,521) - PsiElement(CLASS_VALUE)('Ljava/lang/String;')(503,521) - PsiWhiteSpace(' ')(521,522) - PsiComment(COMMENT)('# getObjectKey')(522,536) - PsiElement(CRLF)('\n')(536,537) - AtEntryImpl(ENTRY)(537,640) - AtKeywordImpl(KEYWORD)(537,543) - PsiElement(KEYWORD_ELEMENT)('public')(537,543) - PsiWhiteSpace(' ')(543,544) - AtClassNameImpl(CLASS_NAME)(544,588) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserListBans')(544,588) - PsiWhiteSpace(' ')(588,589) - AtFunctionImpl(FUNCTION)(589,640) - AtFuncNameImpl(FUNC_NAME)(589,602) - PsiElement(NAME_ELEMENT)('func_152681_a')(589,602) - PsiElement(OPEN_PAREN)('(')(602,603) - AtArgumentImpl(ARGUMENT)(603,621) - PsiElement(CLASS_VALUE)('Ljava/lang/Object;')(603,621) - PsiElement(CLOSE_PAREN)(')')(621,622) - AtReturnValueImpl(RETURN_VALUE)(622,640) - PsiElement(CLASS_VALUE)('Ljava/lang/String;')(622,640) - PsiWhiteSpace(' ')(640,641) - PsiComment(COMMENT)('# getObjectKey')(641,655) - PsiElement(CRLF)('\n')(655,656) - AtEntryImpl(ENTRY)(656,742) - AtKeywordImpl(KEYWORD)(656,662) - PsiElement(KEYWORD_ELEMENT)('public')(656,662) - PsiWhiteSpace(' ')(662,663) - AtClassNameImpl(CLASS_NAME)(663,708) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserListEntry')(663,708) - PsiWhiteSpace(' ')(708,709) - AtFunctionImpl(FUNCTION)(709,742) - AtFuncNameImpl(FUNC_NAME)(709,722) - PsiElement(NAME_ELEMENT)('func_152640_f')(709,722) - PsiElement(OPEN_PAREN)('(')(722,723) - PsiElement(CLOSE_PAREN)(')')(723,724) - AtReturnValueImpl(RETURN_VALUE)(724,742) - PsiElement(CLASS_VALUE)('Ljava/lang/Object;')(724,742) - PsiWhiteSpace(' ')(742,743) - PsiComment(COMMENT)('# getValue')(743,753) - PsiElement(CRLF)('\n')(753,754) - AtEntryImpl(ENTRY)(754,865) - AtKeywordImpl(KEYWORD)(754,760) - PsiElement(KEYWORD_ELEMENT)('public')(754,760) - PsiWhiteSpace(' ')(760,761) - AtClassNameImpl(CLASS_NAME)(761,807) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserListIPBans')(761,807) - PsiWhiteSpace(' ')(807,808) - AtFunctionImpl(FUNCTION)(808,865) - AtFuncNameImpl(FUNC_NAME)(808,821) - PsiElement(NAME_ELEMENT)('func_152707_c')(808,821) - PsiElement(OPEN_PAREN)('(')(821,822) - AtArgumentImpl(ARGUMENT)(822,846) - PsiElement(CLASS_VALUE)('Ljava/net/SocketAddress;')(822,846) - PsiElement(CLOSE_PAREN)(')')(846,847) - AtReturnValueImpl(RETURN_VALUE)(847,865) - PsiElement(CLASS_VALUE)('Ljava/lang/String;')(847,865) - PsiWhiteSpace(' ')(865,866) - PsiComment(COMMENT)('# addressToString')(866,883) - PsiElement(CRLF)('\n')(883,884) - AtEntryImpl(ENTRY)(884,1000) - AtKeywordImpl(KEYWORD)(884,890) - PsiElement(KEYWORD_ELEMENT)('public')(884,890) - PsiWhiteSpace(' ')(890,891) - AtClassNameImpl(CLASS_NAME)(891,934) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserListOps')(891,934) - PsiWhiteSpace(' ')(934,935) - AtFunctionImpl(FUNCTION)(935,1000) - AtFuncNameImpl(FUNC_NAME)(935,948) - PsiElement(NAME_ELEMENT)('func_152681_a')(935,948) - PsiElement(OPEN_PAREN)('(')(948,949) - AtArgumentImpl(ARGUMENT)(949,981) - PsiElement(CLASS_VALUE)('Lcom/mojang/authlib/GameProfile;')(949,981) - PsiElement(CLOSE_PAREN)(')')(981,982) - AtReturnValueImpl(RETURN_VALUE)(982,1000) - PsiElement(CLASS_VALUE)('Ljava/lang/String;')(982,1000) - PsiWhiteSpace(' ')(1000,1001) - PsiComment(COMMENT)('# getObjectKey')(1001,1015) - PsiElement(CRLF)('\n')(1015,1016) - AtEntryImpl(ENTRY)(1016,1118) - AtKeywordImpl(KEYWORD)(1016,1022) - PsiElement(KEYWORD_ELEMENT)('public')(1016,1022) - PsiWhiteSpace(' ')(1022,1023) - AtClassNameImpl(CLASS_NAME)(1023,1066) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserListOps')(1023,1066) - PsiWhiteSpace(' ')(1066,1067) - AtFunctionImpl(FUNCTION)(1067,1118) - AtFuncNameImpl(FUNC_NAME)(1067,1080) - PsiElement(NAME_ELEMENT)('func_152681_a')(1067,1080) - PsiElement(OPEN_PAREN)('(')(1080,1081) - AtArgumentImpl(ARGUMENT)(1081,1099) - PsiElement(CLASS_VALUE)('Ljava/lang/Object;')(1081,1099) - PsiElement(CLOSE_PAREN)(')')(1099,1100) - AtReturnValueImpl(RETURN_VALUE)(1100,1118) - PsiElement(CLASS_VALUE)('Ljava/lang/String;')(1100,1118) - PsiWhiteSpace(' ')(1118,1119) - PsiComment(COMMENT)('# getObjectKey')(1119,1133) - PsiElement(CRLF)('\n')(1133,1134) - AtEntryImpl(ENTRY)(1134,1256) - AtKeywordImpl(KEYWORD)(1134,1140) - PsiElement(KEYWORD_ELEMENT)('public')(1134,1140) - PsiWhiteSpace(' ')(1140,1141) - AtClassNameImpl(CLASS_NAME)(1141,1190) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserListWhitelist')(1141,1190) - PsiWhiteSpace(' ')(1190,1191) - AtFunctionImpl(FUNCTION)(1191,1256) - AtFuncNameImpl(FUNC_NAME)(1191,1204) - PsiElement(NAME_ELEMENT)('func_152681_a')(1191,1204) - PsiElement(OPEN_PAREN)('(')(1204,1205) - AtArgumentImpl(ARGUMENT)(1205,1237) - PsiElement(CLASS_VALUE)('Lcom/mojang/authlib/GameProfile;')(1205,1237) - PsiElement(CLOSE_PAREN)(')')(1237,1238) - AtReturnValueImpl(RETURN_VALUE)(1238,1256) - PsiElement(CLASS_VALUE)('Ljava/lang/String;')(1238,1256) - PsiWhiteSpace(' ')(1256,1257) - PsiComment(COMMENT)('# getObjectKey')(1257,1271) - PsiElement(CRLF)('\n')(1271,1272) - AtEntryImpl(ENTRY)(1272,1380) - AtKeywordImpl(KEYWORD)(1272,1278) - PsiElement(KEYWORD_ELEMENT)('public')(1272,1278) - PsiWhiteSpace(' ')(1278,1279) - AtClassNameImpl(CLASS_NAME)(1279,1328) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserListWhitelist')(1279,1328) - PsiWhiteSpace(' ')(1328,1329) - AtFunctionImpl(FUNCTION)(1329,1380) - AtFuncNameImpl(FUNC_NAME)(1329,1342) - PsiElement(NAME_ELEMENT)('func_152681_a')(1329,1342) - PsiElement(OPEN_PAREN)('(')(1342,1343) - AtArgumentImpl(ARGUMENT)(1343,1361) - PsiElement(CLASS_VALUE)('Ljava/lang/Object;')(1343,1361) - PsiElement(CLOSE_PAREN)(')')(1361,1362) - AtReturnValueImpl(RETURN_VALUE)(1362,1380) - PsiElement(CLASS_VALUE)('Ljava/lang/String;')(1362,1380) - PsiWhiteSpace(' ')(1380,1381) - PsiComment(COMMENT)('# getObjectKey')(1381,1395) - PsiElement(CRLF)('\n')(1395,1396) - AtEntryImpl(ENTRY)(1396,1483) - AtKeywordImpl(KEYWORD)(1396,1402) - PsiElement(KEYWORD_ELEMENT)('public')(1396,1402) - PsiWhiteSpace(' ')(1402,1403) - AtClassNameImpl(CLASS_NAME)(1403,1434) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.util.DamageSource')(1403,1434) - PsiWhiteSpace(' ')(1434,1435) - AtFunctionImpl(FUNCTION)(1435,1483) - AtFuncNameImpl(FUNC_NAME)(1435,1448) - PsiElement(NAME_ELEMENT)('func_151518_m')(1435,1448) - PsiElement(OPEN_PAREN)('(')(1448,1449) - PsiElement(CLOSE_PAREN)(')')(1449,1450) - AtReturnValueImpl(RETURN_VALUE)(1450,1483) - PsiElement(CLASS_VALUE)('Lnet/minecraft/util/DamageSource;')(1450,1483) - PsiWhiteSpace(' ')(1483,1484) - PsiComment(COMMENT)('# setDamageIsAbsolute')(1484,1505) - PsiElement(CRLF)('\n')(1505,1506) - AtEntryImpl(ENTRY)(1506,1592) - AtKeywordImpl(KEYWORD)(1506,1512) - PsiElement(KEYWORD_ELEMENT)('public')(1506,1512) - PsiWhiteSpace(' ')(1512,1513) - AtClassNameImpl(CLASS_NAME)(1513,1544) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.util.DamageSource')(1513,1544) - PsiWhiteSpace(' ')(1544,1545) - AtFunctionImpl(FUNCTION)(1545,1592) - AtFuncNameImpl(FUNC_NAME)(1545,1557) - PsiElement(NAME_ELEMENT)('func_76348_h')(1545,1557) - PsiElement(OPEN_PAREN)('(')(1557,1558) - PsiElement(CLOSE_PAREN)(')')(1558,1559) - AtReturnValueImpl(RETURN_VALUE)(1559,1592) - PsiElement(CLASS_VALUE)('Lnet/minecraft/util/DamageSource;')(1559,1592) - PsiWhiteSpace(' ')(1592,1593) - PsiComment(COMMENT)('# setDamageBypassesArmor')(1593,1617) - PsiElement(CRLF)('\n')(1617,1618) - AtEntryImpl(ENTRY)(1618,1704) - AtKeywordImpl(KEYWORD)(1618,1624) - PsiElement(KEYWORD_ELEMENT)('public')(1618,1624) - PsiWhiteSpace(' ')(1624,1625) - AtClassNameImpl(CLASS_NAME)(1625,1656) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.util.DamageSource')(1625,1656) - PsiWhiteSpace(' ')(1656,1657) - AtFunctionImpl(FUNCTION)(1657,1704) - AtFuncNameImpl(FUNC_NAME)(1657,1669) - PsiElement(NAME_ELEMENT)('func_76359_i')(1657,1669) - PsiElement(OPEN_PAREN)('(')(1669,1670) - PsiElement(CLOSE_PAREN)(')')(1670,1671) - AtReturnValueImpl(RETURN_VALUE)(1671,1704) - PsiElement(CLASS_VALUE)('Lnet/minecraft/util/DamageSource;')(1671,1704) - PsiWhiteSpace(' ')(1704,1705) - PsiComment(COMMENT)('# setDamageAllowedInCreativeMode')(1705,1737) - PsiElement(CRLF)('\n')(1737,1738) - AtEntryImpl(ENTRY)(1738,1824) - AtKeywordImpl(KEYWORD)(1738,1744) - PsiElement(KEYWORD_ELEMENT)('public')(1738,1744) - PsiWhiteSpace(' ')(1744,1745) - AtClassNameImpl(CLASS_NAME)(1745,1776) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.util.DamageSource')(1745,1776) - PsiWhiteSpace(' ')(1776,1777) - AtFunctionImpl(FUNCTION)(1777,1824) - AtFuncNameImpl(FUNC_NAME)(1777,1789) - PsiElement(NAME_ELEMENT)('func_76361_j')(1777,1789) - PsiElement(OPEN_PAREN)('(')(1789,1790) - PsiElement(CLOSE_PAREN)(')')(1790,1791) - AtReturnValueImpl(RETURN_VALUE)(1791,1824) - PsiElement(CLASS_VALUE)('Lnet/minecraft/util/DamageSource;')(1791,1824) - PsiWhiteSpace(' ')(1824,1825) - PsiComment(COMMENT)('# setFireDamage')(1825,1840) - PsiElement(CRLF)('\n')(1840,1841) - AtEntryImpl(ENTRY)(1841,1907) - AtKeywordImpl(KEYWORD)(1841,1847) - PsiElement(KEYWORD_ELEMENT)('public')(1841,1847) - PsiWhiteSpace(' ')(1847,1848) - AtClassNameImpl(CLASS_NAME)(1848,1879) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.util.DamageSource')(1848,1879) - PsiWhiteSpace(' ')(1879,1880) - AtFunctionImpl(FUNCTION)(1880,1907) - AtFuncNameImpl(FUNC_NAME)(1880,1886) - PsiElement(NAME_ELEMENT)('')(1880,1886) - PsiElement(OPEN_PAREN)('(')(1886,1887) - AtArgumentImpl(ARGUMENT)(1887,1905) - PsiElement(CLASS_VALUE)('Ljava/lang/String;')(1887,1905) - PsiElement(CLOSE_PAREN)(')')(1905,1906) - AtReturnValueImpl(RETURN_VALUE)(1906,1907) - PsiElement(PRIMITIVE)('V')(1906,1907) - PsiWhiteSpace(' ')(1907,1908) - PsiComment(COMMENT)('# protected DamageSource (String damageTypeIn)')(1908,1954) - PsiElement(CRLF)('\n')(1954,1955) - AtEntryImpl(ENTRY)(1955,2011) - AtKeywordImpl(KEYWORD)(1955,1961) - PsiElement(KEYWORD_ELEMENT)('public')(1955,1961) - PsiWhiteSpace(' ')(1961,1962) - AtClassNameImpl(CLASS_NAME)(1962,1987) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.world.World')(1962,1987) - PsiWhiteSpace(' ')(1987,1988) - AtFunctionImpl(FUNCTION)(1988,2011) - AtFuncNameImpl(FUNC_NAME)(1988,2001) - PsiElement(NAME_ELEMENT)('func_175663_a')(1988,2001) - PsiElement(OPEN_PAREN)('(')(2001,2002) - AtArgumentImpl(ARGUMENT)(2002,2003) - PsiElement(PRIMITIVE)('I')(2002,2003) - AtArgumentImpl(ARGUMENT)(2003,2004) - PsiElement(PRIMITIVE)('I')(2003,2004) - AtArgumentImpl(ARGUMENT)(2004,2005) - PsiElement(PRIMITIVE)('I')(2004,2005) - AtArgumentImpl(ARGUMENT)(2005,2006) - PsiElement(PRIMITIVE)('I')(2005,2006) - AtArgumentImpl(ARGUMENT)(2006,2007) - PsiElement(PRIMITIVE)('I')(2006,2007) - AtArgumentImpl(ARGUMENT)(2007,2008) - PsiElement(PRIMITIVE)('I')(2007,2008) - AtArgumentImpl(ARGUMENT)(2008,2009) - PsiElement(PRIMITIVE)('Z')(2008,2009) - PsiElement(CLOSE_PAREN)(')')(2009,2010) - AtReturnValueImpl(RETURN_VALUE)(2010,2011) - PsiElement(PRIMITIVE)('Z')(2010,2011) - PsiWhiteSpace(' ')(2011,2012) - PsiComment(COMMENT)('# isAreaLoaded')(2012,2026) - PsiElement(CRLF)('\n')(2026,2027) - AtEntryImpl(ENTRY)(2027,2147) - AtKeywordImpl(KEYWORD)(2027,2033) - PsiElement(KEYWORD_ELEMENT)('public')(2027,2033) - PsiWhiteSpace(' ')(2033,2034) - AtClassNameImpl(CLASS_NAME)(2034,2070) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.MinecraftServer')(2034,2070) - PsiWhiteSpace(' ')(2070,2071) - AtFunctionImpl(FUNCTION)(2071,2147) - AtFuncNameImpl(FUNC_NAME)(2071,2084) - PsiElement(NAME_ELEMENT)('func_175584_a')(2071,2084) - PsiElement(OPEN_PAREN)('(')(2084,2085) - AtArgumentImpl(ARGUMENT)(2085,2103) - PsiElement(CLASS_VALUE)('Ljava/lang/String;')(2085,2103) - AtArgumentImpl(ARGUMENT)(2103,2145) - PsiElement(CLASS_VALUE)('Lnet/minecraft/world/storage/ISaveHandler;')(2103,2145) - PsiElement(CLOSE_PAREN)(')')(2145,2146) - AtReturnValueImpl(RETURN_VALUE)(2146,2147) - PsiElement(PRIMITIVE)('V')(2146,2147) - PsiWhiteSpace(' ')(2147,2148) - PsiComment(COMMENT)('# setResourcePackFromWorld')(2148,2174) - PsiElement(CRLF)('\n')(2174,2175) - AtEntryImpl(ENTRY)(2175,2301) - AtKeywordImpl(KEYWORD)(2175,2181) - PsiElement(KEYWORD_ELEMENT)('public')(2175,2181) - PsiWhiteSpace(' ')(2181,2182) - AtClassNameImpl(CLASS_NAME)(2182,2226) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.tileentity.MobSpawnerBaseLogic')(2182,2226) - PsiWhiteSpace(' ')(2226,2227) - AtFunctionImpl(FUNCTION)(2227,2301) - AtFuncNameImpl(FUNC_NAME)(2227,2240) - PsiElement(NAME_ELEMENT)('func_180613_a')(2227,2240) - PsiElement(OPEN_PAREN)('(')(2240,2241) - AtArgumentImpl(ARGUMENT)(2241,2270) - PsiElement(CLASS_VALUE)('Lnet/minecraft/entity/Entity;')(2241,2270) - AtArgumentImpl(ARGUMENT)(2270,2271) - PsiElement(PRIMITIVE)('Z')(2270,2271) - PsiElement(CLOSE_PAREN)(')')(2271,2272) - AtReturnValueImpl(RETURN_VALUE)(2272,2301) - PsiElement(CLASS_VALUE)('Lnet/minecraft/entity/Entity;')(2272,2301) - PsiWhiteSpace(' ')(2301,2302) - PsiComment(COMMENT)('# spawnNewEntity')(2302,2318) Index: src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/keywords_at.cfg =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/keywords_at.cfg (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/keywords_at.cfg (revision 533678d90250de5d335d0d7478938b9a27b2b056) @@ -1,12 +0,0 @@ -public package.class field -public-f package.class field -public+f package.class field -private package.class field -private-f package.class field -private+f package.class field -protected package.class field -protected-f package.class field -protected+f package.class field -default package.class field -default-f package.class field -default+f package.class field Index: src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/keywords_at.txt =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/keywords_at.txt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/keywords_at.txt (revision 533678d90250de5d335d0d7478938b9a27b2b056) @@ -1,120 +0,0 @@ -Access transformers(0,354) - AtEntryImpl(ENTRY)(0,26) - AtKeywordImpl(KEYWORD)(0,6) - PsiElement(KEYWORD_ELEMENT)('public')(0,6) - PsiWhiteSpace(' ')(6,7) - AtClassNameImpl(CLASS_NAME)(7,20) - PsiElement(CLASS_NAME_ELEMENT)('package.class')(7,20) - PsiWhiteSpace(' ')(20,21) - AtFieldNameImpl(FIELD_NAME)(21,26) - PsiElement(NAME_ELEMENT)('field')(21,26) - PsiElement(CRLF)('\n')(26,27) - AtEntryImpl(ENTRY)(27,55) - AtKeywordImpl(KEYWORD)(27,35) - PsiElement(KEYWORD_ELEMENT)('public-f')(27,35) - PsiWhiteSpace(' ')(35,36) - AtClassNameImpl(CLASS_NAME)(36,49) - PsiElement(CLASS_NAME_ELEMENT)('package.class')(36,49) - PsiWhiteSpace(' ')(49,50) - AtFieldNameImpl(FIELD_NAME)(50,55) - PsiElement(NAME_ELEMENT)('field')(50,55) - PsiElement(CRLF)('\n')(55,56) - AtEntryImpl(ENTRY)(56,84) - AtKeywordImpl(KEYWORD)(56,64) - PsiElement(KEYWORD_ELEMENT)('public+f')(56,64) - PsiWhiteSpace(' ')(64,65) - AtClassNameImpl(CLASS_NAME)(65,78) - PsiElement(CLASS_NAME_ELEMENT)('package.class')(65,78) - PsiWhiteSpace(' ')(78,79) - AtFieldNameImpl(FIELD_NAME)(79,84) - PsiElement(NAME_ELEMENT)('field')(79,84) - PsiElement(CRLF)('\n')(84,85) - AtEntryImpl(ENTRY)(85,112) - AtKeywordImpl(KEYWORD)(85,92) - PsiElement(KEYWORD_ELEMENT)('private')(85,92) - PsiWhiteSpace(' ')(92,93) - AtClassNameImpl(CLASS_NAME)(93,106) - PsiElement(CLASS_NAME_ELEMENT)('package.class')(93,106) - PsiWhiteSpace(' ')(106,107) - AtFieldNameImpl(FIELD_NAME)(107,112) - PsiElement(NAME_ELEMENT)('field')(107,112) - PsiElement(CRLF)('\n')(112,113) - AtEntryImpl(ENTRY)(113,142) - AtKeywordImpl(KEYWORD)(113,122) - PsiElement(KEYWORD_ELEMENT)('private-f')(113,122) - PsiWhiteSpace(' ')(122,123) - AtClassNameImpl(CLASS_NAME)(123,136) - PsiElement(CLASS_NAME_ELEMENT)('package.class')(123,136) - PsiWhiteSpace(' ')(136,137) - AtFieldNameImpl(FIELD_NAME)(137,142) - PsiElement(NAME_ELEMENT)('field')(137,142) - PsiElement(CRLF)('\n')(142,143) - AtEntryImpl(ENTRY)(143,172) - AtKeywordImpl(KEYWORD)(143,152) - PsiElement(KEYWORD_ELEMENT)('private+f')(143,152) - PsiWhiteSpace(' ')(152,153) - AtClassNameImpl(CLASS_NAME)(153,166) - PsiElement(CLASS_NAME_ELEMENT)('package.class')(153,166) - PsiWhiteSpace(' ')(166,167) - AtFieldNameImpl(FIELD_NAME)(167,172) - PsiElement(NAME_ELEMENT)('field')(167,172) - PsiElement(CRLF)('\n')(172,173) - AtEntryImpl(ENTRY)(173,202) - AtKeywordImpl(KEYWORD)(173,182) - PsiElement(KEYWORD_ELEMENT)('protected')(173,182) - PsiWhiteSpace(' ')(182,183) - AtClassNameImpl(CLASS_NAME)(183,196) - PsiElement(CLASS_NAME_ELEMENT)('package.class')(183,196) - PsiWhiteSpace(' ')(196,197) - AtFieldNameImpl(FIELD_NAME)(197,202) - PsiElement(NAME_ELEMENT)('field')(197,202) - PsiElement(CRLF)('\n')(202,203) - AtEntryImpl(ENTRY)(203,234) - AtKeywordImpl(KEYWORD)(203,214) - PsiElement(KEYWORD_ELEMENT)('protected-f')(203,214) - PsiWhiteSpace(' ')(214,215) - AtClassNameImpl(CLASS_NAME)(215,228) - PsiElement(CLASS_NAME_ELEMENT)('package.class')(215,228) - PsiWhiteSpace(' ')(228,229) - AtFieldNameImpl(FIELD_NAME)(229,234) - PsiElement(NAME_ELEMENT)('field')(229,234) - PsiElement(CRLF)('\n')(234,235) - AtEntryImpl(ENTRY)(235,266) - AtKeywordImpl(KEYWORD)(235,246) - PsiElement(KEYWORD_ELEMENT)('protected+f')(235,246) - PsiWhiteSpace(' ')(246,247) - AtClassNameImpl(CLASS_NAME)(247,260) - PsiElement(CLASS_NAME_ELEMENT)('package.class')(247,260) - PsiWhiteSpace(' ')(260,261) - AtFieldNameImpl(FIELD_NAME)(261,266) - PsiElement(NAME_ELEMENT)('field')(261,266) - PsiElement(CRLF)('\n')(266,267) - AtEntryImpl(ENTRY)(267,294) - AtKeywordImpl(KEYWORD)(267,274) - PsiElement(KEYWORD_ELEMENT)('default')(267,274) - PsiWhiteSpace(' ')(274,275) - AtClassNameImpl(CLASS_NAME)(275,288) - PsiElement(CLASS_NAME_ELEMENT)('package.class')(275,288) - PsiWhiteSpace(' ')(288,289) - AtFieldNameImpl(FIELD_NAME)(289,294) - PsiElement(NAME_ELEMENT)('field')(289,294) - PsiElement(CRLF)('\n')(294,295) - AtEntryImpl(ENTRY)(295,324) - AtKeywordImpl(KEYWORD)(295,304) - PsiElement(KEYWORD_ELEMENT)('default-f')(295,304) - PsiWhiteSpace(' ')(304,305) - AtClassNameImpl(CLASS_NAME)(305,318) - PsiElement(CLASS_NAME_ELEMENT)('package.class')(305,318) - PsiWhiteSpace(' ')(318,319) - AtFieldNameImpl(FIELD_NAME)(319,324) - PsiElement(NAME_ELEMENT)('field')(319,324) - PsiElement(CRLF)('\n')(324,325) - AtEntryImpl(ENTRY)(325,354) - AtKeywordImpl(KEYWORD)(325,334) - PsiElement(KEYWORD_ELEMENT)('default+f')(325,334) - PsiWhiteSpace(' ')(334,335) - AtClassNameImpl(CLASS_NAME)(335,348) - PsiElement(CLASS_NAME_ELEMENT)('package.class')(335,348) - PsiWhiteSpace(' ')(348,349) - AtFieldNameImpl(FIELD_NAME)(349,354) - PsiElement(NAME_ELEMENT)('field')(349,354) Index: src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/no_value_at.cfg =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/no_value_at.cfg (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/no_value_at.cfg (revision 533678d90250de5d335d0d7478938b9a27b2b056) @@ -1,3 +0,0 @@ -public-f net.minecraft.item.ItemStack -public net.minecraft.block.state.BlockStateContainer$StateImplementation -public net.minecraft.entity.ai.EntityAITasks$EntityAITaskEntry Index: src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/no_value_at.txt =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/no_value_at.txt (revision 533678d90250de5d335d0d7478938b9a27b2b056) +++ src/test/resources/com/demonwav/mcdev/platform/mcp/at/parser/fixtures/no_value_at.txt (revision 533678d90250de5d335d0d7478938b9a27b2b056) @@ -1,21 +0,0 @@ -Access transformers(0,173) - AtEntryImpl(ENTRY)(0,37) - AtKeywordImpl(KEYWORD)(0,8) - PsiElement(KEYWORD_ELEMENT)('public-f')(0,8) - PsiWhiteSpace(' ')(8,9) - AtClassNameImpl(CLASS_NAME)(9,37) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.item.ItemStack')(9,37) - PsiElement(CRLF)('\n')(37,38) - AtEntryImpl(ENTRY)(38,110) - AtKeywordImpl(KEYWORD)(38,44) - PsiElement(KEYWORD_ELEMENT)('public')(38,44) - PsiWhiteSpace(' ')(44,45) - AtClassNameImpl(CLASS_NAME)(45,110) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.block.state.BlockStateContainer$StateImplementation')(45,110) - PsiElement(CRLF)('\n')(110,111) - AtEntryImpl(ENTRY)(111,173) - AtKeywordImpl(KEYWORD)(111,117) - PsiElement(KEYWORD_ELEMENT)('public')(111,117) - PsiWhiteSpace(' ')(117,118) - AtClassNameImpl(CLASS_NAME)(118,173) - PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.ai.EntityAITasks$EntityAITaskEntry')(118,173) Index: src/test/resources/com/demonwav/mcdev/platform/minecraft/at/lexer/fixtures/spigot_mappings_at.cfg =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/minecraft/at/lexer/fixtures/spigot_mappings_at.cfg (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/test/resources/com/demonwav/mcdev/platform/minecraft/at/lexer/fixtures/spigot_mappings_at.cfg (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,214 @@ +public net.minecraft.server.EntityPlayer containerCounter +public net.minecraft.server.EntityPlayer nextContainerCounter()V +public net.minecraft.server.ShapelessRecipes ingredients +public net.minecraft.server.EntityVillager$IMerchantRecipeOption +protected bip d +protected bip e +protected bip g +protected bip i #asdf +protected bip j +protected bip a(IZ)F +protected bip b(CZ)F +protected biq * +protected biq *() +public-f net.minecraft.server.WorldType types +public bzf k +public net.minecraft.server.AdvancementDataWorld DESERIALIZER +protected net.minecraft.server.MinecraftServer ab +public bja f +public bja g +public net.minecraft.server.RecipiesShield$Decoration +public net.minecraft.server.PacketStatusOutServerInfo a +public-f bje i +public-f bje j +protected bzu a(Lnet/minecraft/server/ItemStack;)I +public bjd d()V +public net.minecraft.server.EntityVillager$MerchantRecipeOptionProcess +public net.minecraft.server.EntityVillager$MerchantRecipeOptionEnchant +public net.minecraft.server.EntityVillager$MerchantRecipeOptionBuy +public bjr b +public bjr c +public bjr t +public bjr d +public bjr e +public bjr f +public bjr g +public bjr h +public bsb b(Lnet/minecraft/server/Entity;)V +public bsb c(Lnet/minecraft/server/Entity;)V +public net.minecraft.server.BiomeBigHills *() +public net.minecraft.server.Item a(Z)Lnet/minecraft/server/Item; +public net.minecraft.server.Item setMaxDurability(I)Lnet/minecraft/server/Item; +public net.minecraft.server.ContainerAnvil k +public net.minecraft.server.RecipesBanner$AddRecipe +public net.minecraft.server.BiomeIcePlains *() +public net.minecraft.server.TileEntity a(Ljava/lang/String;Ljava/lang/Class;)V +public+f net.minecraft.server.ShapedRecipes width +public+f net.minecraft.server.ShapedRecipes items +public+f net.minecraft.server.ShapedRecipes height +public net.minecraft.server.WorldGenStrongholdPieces$WorldGenStrongholdPiece +protected net.minecraft.server.EntityHuman d +protected net.minecraft.server.EntityHuman e +public net.minecraft.server.EntityHuman closeInventory()V +public net.minecraft.server.EntityHuman a(Lnet/minecraft/server/EntityItem;)Lnet/minecraft/server/ItemStack; +public net.minecraft.server.EntityInsentient targetSelector +public net.minecraft.server.EntityInsentient goalSelector +public net.minecraft.server.EnumDirection n +public net.minecraft.server.EnumDirection o +public net.minecraft.server.BiomePlains *() +protected net.minecraft.server.RegistryBlockID a +protected net.minecraft.server.RegistryBlockID b +public net.minecraft.server.RecipesBanner$DuplicateRecipe +public net.minecraft.server.BlockStateList$BlockData +protected net.minecraft.server.BlockStateList$BlockData c +protected net.minecraft.server.BlockStateList$BlockData (Lnet/minecraft/block/Block;Lcom/google/common/collect/ImmutableMap;)V +public net.minecraft.server.Block j()Lnet/minecraft/server/Block; +public net.minecraft.server.Block a(Z)Lnet/minecraft/server/Block; +public net.minecraft.server.Block c(F)Lnet/minecraft/server/Block; +public net.minecraft.server.Block b(F)Lnet/minecraft/server/Block; +public net.minecraft.server.Block e(I)Lnet/minecraft/server/Block; +public net.minecraft.server.Block (Lnet/minecraft/block/material/Material;)V +public net.minecraft.server.Block dropExperience(Lnet/minecraft/server/World;Lnet/minecraft/server/BlockPosition;I)V +public net.minecraft.server.Block a(F)Lnet/minecraft/server/Block; +public net.minecraft.server.WorldGenFactory a(Ljava/lang/Class;Ljava/lang/String;)V +public net.minecraft.server.WorldGenFactory b(Ljava/lang/Class;Ljava/lang/String;)V +public net.minecraft.server.RecipeTippedArrow +public net.minecraft.server.WorldServer b(Lnet/minecraft/server/Entity;)V +public net.minecraft.server.WorldServer c(Lnet/minecraft/server/Entity;)V +public blk j +public net.minecraft.server.BlockFire f(Lnet/minecraft/server/Block;)I +public net.minecraft.server.BlockFire e(Lnet/minecraft/server/Block;)I +public net.minecraft.server.WeightedRandom$WeightedRandomChoice a +public net.minecraft.server.EntityVillager$MerchantOptionRandomRange +public net.minecraft.server.EntityVillager$MerchantRecipeOptionSell +protected net.minecraft.server.EntitySkeletonStray p()Lnet/minecraft/server/SoundEffect; +public bud a(Lnet/minecraft/server/EntityItem;)Lnet/minecraft/server/ItemStack; +public net.minecraft.server.World p +public net.minecraft.server.World q +public-f net.minecraft.server.World villages +public net.minecraft.server.World n +public net.minecraft.server.World o +public net.minecraft.server.World E(Lnet/minecraft/server/BlockPosition;)Z +public net.minecraft.server.World isValidLocation(Lnet/minecraft/server/BlockPosition;)Z +public net.minecraft.server.World b(Lnet/minecraft/server/Entity;)V +public net.minecraft.server.World c(Lnet/minecraft/server/Entity;)V +public net.minecraft.server.DataConverterManager d +public net.minecraft.server.BiomeDecorator * +public buk c(IIII)V +public buk c(I)I +public net.minecraft.server.BiomeBase$a *() +public-f net.minecraft.server.WorldGenVillage a +public buq a(Lnet/minecraft/server/MinecraftKey;)V +public net.minecraft.server.NBTNumber +protected cgb p +public cgb a +protected cgb r +protected cgb b +protected cgb s +protected cgb g +protected cgb h +protected cgb l +protected cgb m +protected cgb a(Lnet/minecraft/server/Item;)Ljava/util/List; +protected cgb h()V +protected cgb g()V +protected cgb f()V +protected cgb c(Lbvu;)Z +protected cgb b(Lbvu;)Z +protected cgb d(Lnet/minecraft/server/MinecraftKey;)Lnet/minecraft/server/MinecraftKey; +protected cgb a(Lbvv;Lcgd;)V +protected cgb d(Lbvu;)Lbvu; +protected cgb c(Lnet/minecraft/server/MinecraftKey;)Lbvu; +protected cgb a(Ljava/lang/String;)Lnet/minecraft/server/MinecraftKey; +protected cgb a(Lcgd;Lbwd;)V +protected cgb a(Lbvu;)Ljava/util/Set; +protected cgb e()V +protected cgb c()V +protected cgb b()V +protected cgb a(Lnet/minecraft/server/MinecraftKey;)Lbvv; +public net.minecraft.server.PathfinderGoalSelector$PathfinderGoalSelectorItem +protected buv c +protected net.minecraft.server.EntitySkeleton p()Lnet/minecraft/server/SoundEffect; +public net.minecraft.server.BiomeTaiga *() +public net.minecraft.server.BiomeMesa *() +public net.minecraft.server.TileEntityHopper K()Z +protected net.minecraft.server.TileEntityHopper o()Z +public net.minecraft.server.TileEntityHopper setCooldown(I)V +public bvu c +public bvu d +public bvu i +public bvu f()Ljava/util/List; +private-f net.minecraft.server.LootSelector c +private-f net.minecraft.server.LootSelector d +protected net.minecraft.server.PortalTravelAgent b +protected net.minecraft.server.PortalTravelAgent world +protected net.minecraft.server.PortalTravelAgent c +protected net.minecraft.server.RecipeItemStack ([Lnet/minecraft/item/ItemStack;)V +public chm d +public net.minecraft.server.PacketPlayOutBlockChange block +public net.minecraft.server.DamageSource *() +protected net.minecraft.server.EntitySkeletonAbstract p()Lnet/minecraft/server/SoundEffect; +protected net.minecraft.server.EntitySkeletonWither p()Lnet/minecraft/server/SoundEffect; +public net.minecraft.server.DedicatedServer serverCommandQueue +public net.minecraft.server.WorldGenVillagePieces$WorldGenVillagePiece +public net.minecraft.server.BiomeBase *() +public net.minecraft.server.ChunkProviderServer chunkGenerator +public net.minecraft.server.ChunkProviderServer world +public net.minecraft.server.ChunkProviderServer chunkLoader +public net.minecraft.server.ChunkProviderServer chunks +public net.minecraft.server.ChunkRegionLoader d +public caa a(Lccg;)Z +public bwx n +public bwx o +private-f net.minecraft.server.PlayerChunk dirtyBlocks +private-f net.minecraft.server.ChunkProviderGenerate A +private-f net.minecraft.server.ChunkProviderGenerate B +private-f net.minecraft.server.ChunkProviderGenerate C +private-f net.minecraft.server.ChunkProviderGenerate v +private-f net.minecraft.server.ChunkProviderGenerate w +private-f net.minecraft.server.ChunkProviderGenerate x +private-f net.minecraft.server.ChunkProviderGenerate y +private-f net.minecraft.server.ChunkProviderGenerate j +private-f net.minecraft.server.ChunkProviderGenerate z +private-f net.minecraft.server.ChunkProviderGenerate k +private-f net.minecraft.server.ChunkProviderGenerate l +private-f net.minecraft.server.ChunkProviderGenerate m +public net.minecraft.server.PotionBrewer a(Lnet/minecraft/server/ItemPotion;)V +public net.minecraft.server.PotionBrewer a(Lnet/minecraft/server/PotionRegistry;Lnet/minecraft/server/Item;Lnet/minecraft/server/PotionRegistry;)V +public net.minecraft.server.PotionBrewer a(Lnet/minecraft/server/ItemPotion;Lnet/minecraft/server/Item;Lnet/minecraft/server/ItemPotion;)V +public net.minecraft.server.PotionBrewer a(Lnet/minecraft/server/PotionRegistry;Lnet/minecraft/server/RecipeItemStack;Lnet/minecraft/server/PotionRegistry;)V +public net.minecraft.server.CriterionTriggers a(Lnet/minecraft/server/CriterionTrigger;)Lnet/minecraft/server/CriterionTrigger; +public net.minecraft.server.EntityVillager$MerchantRecipeOptionBook +public-f net.minecraft.server.CreativeModeTab a +private-f net.minecraft.server.ChunkProviderHell u +private-f net.minecraft.server.ChunkProviderHell v +public-f net.minecraft.server.ChunkProviderHell g +private-f net.minecraft.server.ChunkProviderHell w +public-f net.minecraft.server.ChunkProviderHell h +private-f net.minecraft.server.ChunkProviderHell x +private-f net.minecraft.server.ChunkProviderHell I +private-f net.minecraft.server.ChunkProviderHell y +private-f net.minecraft.server.ChunkProviderHell J +public net.minecraft.server.BiomeSavanna *() +private-f net.minecraft.server.ChunkProviderTheEnd p +private-f net.minecraft.server.ChunkProviderTheEnd i +private-f net.minecraft.server.ChunkProviderTheEnd j +private-f net.minecraft.server.ChunkProviderTheEnd k +private-f net.minecraft.server.ChunkProviderTheEnd o +public net.minecraft.server.BiomeForest *() +public net.minecraft.server.EntityTrackerEntry trackedPlayers +public+f net.minecraft.server.WorldGenStronghold a +public net.minecraft.server.PotionBrewer$PredicatedCombination +public net.minecraft.server.WorldLoader a +public net.minecraft.server.MinecraftKey a(Ljava/lang/String;)[Ljava/lang/String; +default net.minecraft.server.ItemStack damage +public net.minecraft.server.EntityExperienceOrb value +public net.minecraft.server.EntityMinecartContainer b +public bib Q +public bib aE +public bib a(Lnet/minecraft/server/ItemStack;Lnet/minecraft/server/TileEntity;)Lnet/minecraft/server/ItemStack; +public bib a(II)V +public bib ar()V +public bib a(Lcdr;)V +public net.minecraft.server.PathfinderGoalSelector b +public net.minecraft.server.PlayerSelector c(Ljava/lang/String;)Ljava/lang/String; Index: src/test/resources/com/demonwav/mcdev/platform/minecraft/at/lexer/fixtures/spigot_mappings_at.txt =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/minecraft/at/lexer/fixtures/spigot_mappings_at.txt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/test/resources/com/demonwav/mcdev/platform/minecraft/at/lexer/fixtures/spigot_mappings_at.txt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,1546 @@ +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityPlayer') +WHITE_SPACE (' ') +NAME_ELEMENT ('containerCounter') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityPlayer') +WHITE_SPACE (' ') +NAME_ELEMENT ('nextContainerCounter') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ShapelessRecipes') +WHITE_SPACE (' ') +NAME_ELEMENT ('ingredients') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityVillager$IMerchantRecipeOption') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bip') +WHITE_SPACE (' ') +NAME_ELEMENT ('d') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bip') +WHITE_SPACE (' ') +NAME_ELEMENT ('e') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bip') +WHITE_SPACE (' ') +NAME_ELEMENT ('g') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bip') +WHITE_SPACE (' ') +NAME_ELEMENT ('i') +WHITE_SPACE (' ') +COMMENT ('#asdf') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bip') +WHITE_SPACE (' ') +NAME_ELEMENT ('j') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bip') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +PRIMITIVE ('I') +PRIMITIVE ('Z') +CLOSE_PAREN (')') +PRIMITIVE ('F') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bip') +WHITE_SPACE (' ') +NAME_ELEMENT ('b') +OPEN_PAREN ('(') +PRIMITIVE ('C') +PRIMITIVE ('Z') +CLOSE_PAREN (')') +PRIMITIVE ('F') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('biq') +WHITE_SPACE (' ') +ASTERISK_ELEMENT ('*') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('biq') +WHITE_SPACE (' ') +ASTERISK_ELEMENT ('*()') +CRLF ('\n') +KEYWORD_ELEMENT ('public-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.WorldType') +WHITE_SPACE (' ') +NAME_ELEMENT ('types') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bzf') +WHITE_SPACE (' ') +NAME_ELEMENT ('k') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.AdvancementDataWorld') +WHITE_SPACE (' ') +NAME_ELEMENT ('DESERIALIZER') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.MinecraftServer') +WHITE_SPACE (' ') +NAME_ELEMENT ('ab') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bja') +WHITE_SPACE (' ') +NAME_ELEMENT ('f') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bja') +WHITE_SPACE (' ') +NAME_ELEMENT ('g') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.RecipiesShield$Decoration') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.PacketStatusOutServerInfo') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +CRLF ('\n') +KEYWORD_ELEMENT ('public-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bje') +WHITE_SPACE (' ') +NAME_ELEMENT ('i') +CRLF ('\n') +KEYWORD_ELEMENT ('public-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bje') +WHITE_SPACE (' ') +NAME_ELEMENT ('j') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bzu') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/ItemStack;') +CLOSE_PAREN (')') +PRIMITIVE ('I') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bjd') +WHITE_SPACE (' ') +NAME_ELEMENT ('d') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityVillager$MerchantRecipeOptionProcess') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityVillager$MerchantRecipeOptionEnchant') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityVillager$MerchantRecipeOptionBuy') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bjr') +WHITE_SPACE (' ') +NAME_ELEMENT ('b') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bjr') +WHITE_SPACE (' ') +NAME_ELEMENT ('c') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bjr') +WHITE_SPACE (' ') +NAME_ELEMENT ('t') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bjr') +WHITE_SPACE (' ') +NAME_ELEMENT ('d') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bjr') +WHITE_SPACE (' ') +NAME_ELEMENT ('e') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bjr') +WHITE_SPACE (' ') +NAME_ELEMENT ('f') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bjr') +WHITE_SPACE (' ') +NAME_ELEMENT ('g') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bjr') +WHITE_SPACE (' ') +NAME_ELEMENT ('h') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bsb') +WHITE_SPACE (' ') +NAME_ELEMENT ('b') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/Entity;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bsb') +WHITE_SPACE (' ') +NAME_ELEMENT ('c') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/Entity;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeBigHills') +WHITE_SPACE (' ') +ASTERISK_ELEMENT ('*()') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.Item') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +PRIMITIVE ('Z') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/Item;') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.Item') +WHITE_SPACE (' ') +NAME_ELEMENT ('setMaxDurability') +OPEN_PAREN ('(') +PRIMITIVE ('I') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/Item;') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ContainerAnvil') +WHITE_SPACE (' ') +NAME_ELEMENT ('k') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.RecipesBanner$AddRecipe') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeIcePlains') +WHITE_SPACE (' ') +ASTERISK_ELEMENT ('*()') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.TileEntity') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Ljava/lang/String;') +CLASS_VALUE ('Ljava/lang/Class;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public+f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ShapedRecipes') +WHITE_SPACE (' ') +NAME_ELEMENT ('width') +CRLF ('\n') +KEYWORD_ELEMENT ('public+f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ShapedRecipes') +WHITE_SPACE (' ') +NAME_ELEMENT ('items') +CRLF ('\n') +KEYWORD_ELEMENT ('public+f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ShapedRecipes') +WHITE_SPACE (' ') +NAME_ELEMENT ('height') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.WorldGenStrongholdPieces$WorldGenStrongholdPiece') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityHuman') +WHITE_SPACE (' ') +NAME_ELEMENT ('d') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityHuman') +WHITE_SPACE (' ') +NAME_ELEMENT ('e') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityHuman') +WHITE_SPACE (' ') +NAME_ELEMENT ('closeInventory') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityHuman') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/EntityItem;') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/ItemStack;') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityInsentient') +WHITE_SPACE (' ') +NAME_ELEMENT ('targetSelector') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityInsentient') +WHITE_SPACE (' ') +NAME_ELEMENT ('goalSelector') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EnumDirection') +WHITE_SPACE (' ') +NAME_ELEMENT ('n') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EnumDirection') +WHITE_SPACE (' ') +NAME_ELEMENT ('o') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.BiomePlains') +WHITE_SPACE (' ') +ASTERISK_ELEMENT ('*()') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.RegistryBlockID') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.RegistryBlockID') +WHITE_SPACE (' ') +NAME_ELEMENT ('b') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.RecipesBanner$DuplicateRecipe') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.BlockStateList$BlockData') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.BlockStateList$BlockData') +WHITE_SPACE (' ') +NAME_ELEMENT ('c') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.BlockStateList$BlockData') +WHITE_SPACE (' ') +NAME_ELEMENT ('') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/block/Block;') +CLASS_VALUE ('Lcom/google/common/collect/ImmutableMap;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.Block') +WHITE_SPACE (' ') +NAME_ELEMENT ('j') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/Block;') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.Block') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +PRIMITIVE ('Z') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/Block;') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.Block') +WHITE_SPACE (' ') +NAME_ELEMENT ('c') +OPEN_PAREN ('(') +PRIMITIVE ('F') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/Block;') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.Block') +WHITE_SPACE (' ') +NAME_ELEMENT ('b') +OPEN_PAREN ('(') +PRIMITIVE ('F') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/Block;') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.Block') +WHITE_SPACE (' ') +NAME_ELEMENT ('e') +OPEN_PAREN ('(') +PRIMITIVE ('I') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/Block;') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.Block') +WHITE_SPACE (' ') +NAME_ELEMENT ('') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/block/material/Material;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.Block') +WHITE_SPACE (' ') +NAME_ELEMENT ('dropExperience') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/World;') +CLASS_VALUE ('Lnet/minecraft/server/BlockPosition;') +PRIMITIVE ('I') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.Block') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +PRIMITIVE ('F') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/Block;') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.WorldGenFactory') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Ljava/lang/Class;') +CLASS_VALUE ('Ljava/lang/String;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.WorldGenFactory') +WHITE_SPACE (' ') +NAME_ELEMENT ('b') +OPEN_PAREN ('(') +CLASS_VALUE ('Ljava/lang/Class;') +CLASS_VALUE ('Ljava/lang/String;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.RecipeTippedArrow') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.WorldServer') +WHITE_SPACE (' ') +NAME_ELEMENT ('b') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/Entity;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.WorldServer') +WHITE_SPACE (' ') +NAME_ELEMENT ('c') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/Entity;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('blk') +WHITE_SPACE (' ') +NAME_ELEMENT ('j') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.BlockFire') +WHITE_SPACE (' ') +NAME_ELEMENT ('f') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/Block;') +CLOSE_PAREN (')') +PRIMITIVE ('I') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.BlockFire') +WHITE_SPACE (' ') +NAME_ELEMENT ('e') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/Block;') +CLOSE_PAREN (')') +PRIMITIVE ('I') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.WeightedRandom$WeightedRandomChoice') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityVillager$MerchantOptionRandomRange') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityVillager$MerchantRecipeOptionSell') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntitySkeletonStray') +WHITE_SPACE (' ') +NAME_ELEMENT ('p') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/SoundEffect;') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bud') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/EntityItem;') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/ItemStack;') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.World') +WHITE_SPACE (' ') +NAME_ELEMENT ('p') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.World') +WHITE_SPACE (' ') +NAME_ELEMENT ('q') +CRLF ('\n') +KEYWORD_ELEMENT ('public-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.World') +WHITE_SPACE (' ') +NAME_ELEMENT ('villages') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.World') +WHITE_SPACE (' ') +NAME_ELEMENT ('n') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.World') +WHITE_SPACE (' ') +NAME_ELEMENT ('o') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.World') +WHITE_SPACE (' ') +NAME_ELEMENT ('E') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/BlockPosition;') +CLOSE_PAREN (')') +PRIMITIVE ('Z') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.World') +WHITE_SPACE (' ') +NAME_ELEMENT ('isValidLocation') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/BlockPosition;') +CLOSE_PAREN (')') +PRIMITIVE ('Z') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.World') +WHITE_SPACE (' ') +NAME_ELEMENT ('b') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/Entity;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.World') +WHITE_SPACE (' ') +NAME_ELEMENT ('c') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/Entity;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.DataConverterManager') +WHITE_SPACE (' ') +NAME_ELEMENT ('d') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeDecorator') +WHITE_SPACE (' ') +ASTERISK_ELEMENT ('*') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('buk') +WHITE_SPACE (' ') +NAME_ELEMENT ('c') +OPEN_PAREN ('(') +PRIMITIVE ('I') +PRIMITIVE ('I') +PRIMITIVE ('I') +PRIMITIVE ('I') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('buk') +WHITE_SPACE (' ') +NAME_ELEMENT ('c') +OPEN_PAREN ('(') +PRIMITIVE ('I') +CLOSE_PAREN (')') +PRIMITIVE ('I') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeBase$a') +WHITE_SPACE (' ') +ASTERISK_ELEMENT ('*()') +CRLF ('\n') +KEYWORD_ELEMENT ('public-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.WorldGenVillage') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('buq') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/MinecraftKey;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.NBTNumber') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('p') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('r') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('b') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('s') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('g') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('h') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('l') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('m') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/Item;') +CLOSE_PAREN (')') +CLASS_VALUE ('Ljava/util/List;') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('h') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('g') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('f') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('c') +OPEN_PAREN ('(') +CLASS_VALUE ('Lbvu;') +CLOSE_PAREN (')') +PRIMITIVE ('Z') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('b') +OPEN_PAREN ('(') +CLASS_VALUE ('Lbvu;') +CLOSE_PAREN (')') +PRIMITIVE ('Z') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('d') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/MinecraftKey;') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/MinecraftKey;') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Lbvv;') +CLASS_VALUE ('Lcgd;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('d') +OPEN_PAREN ('(') +CLASS_VALUE ('Lbvu;') +CLOSE_PAREN (')') +CLASS_VALUE ('Lbvu;') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('c') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/MinecraftKey;') +CLOSE_PAREN (')') +CLASS_VALUE ('Lbvu;') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Ljava/lang/String;') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/MinecraftKey;') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Lcgd;') +CLASS_VALUE ('Lbwd;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Lbvu;') +CLOSE_PAREN (')') +CLASS_VALUE ('Ljava/util/Set;') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('e') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('c') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('b') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('cgb') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/MinecraftKey;') +CLOSE_PAREN (')') +CLASS_VALUE ('Lbvv;') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.PathfinderGoalSelector$PathfinderGoalSelectorItem') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('buv') +WHITE_SPACE (' ') +NAME_ELEMENT ('c') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntitySkeleton') +WHITE_SPACE (' ') +NAME_ELEMENT ('p') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/SoundEffect;') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeTaiga') +WHITE_SPACE (' ') +ASTERISK_ELEMENT ('*()') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeMesa') +WHITE_SPACE (' ') +ASTERISK_ELEMENT ('*()') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.TileEntityHopper') +WHITE_SPACE (' ') +NAME_ELEMENT ('K') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +PRIMITIVE ('Z') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.TileEntityHopper') +WHITE_SPACE (' ') +NAME_ELEMENT ('o') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +PRIMITIVE ('Z') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.TileEntityHopper') +WHITE_SPACE (' ') +NAME_ELEMENT ('setCooldown') +OPEN_PAREN ('(') +PRIMITIVE ('I') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bvu') +WHITE_SPACE (' ') +NAME_ELEMENT ('c') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bvu') +WHITE_SPACE (' ') +NAME_ELEMENT ('d') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bvu') +WHITE_SPACE (' ') +NAME_ELEMENT ('i') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bvu') +WHITE_SPACE (' ') +NAME_ELEMENT ('f') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +CLASS_VALUE ('Ljava/util/List;') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.LootSelector') +WHITE_SPACE (' ') +NAME_ELEMENT ('c') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.LootSelector') +WHITE_SPACE (' ') +NAME_ELEMENT ('d') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.PortalTravelAgent') +WHITE_SPACE (' ') +NAME_ELEMENT ('b') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.PortalTravelAgent') +WHITE_SPACE (' ') +NAME_ELEMENT ('world') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.PortalTravelAgent') +WHITE_SPACE (' ') +NAME_ELEMENT ('c') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.RecipeItemStack') +WHITE_SPACE (' ') +NAME_ELEMENT ('') +OPEN_PAREN ('(') +CLASS_VALUE ('[Lnet/minecraft/item/ItemStack;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('chm') +WHITE_SPACE (' ') +NAME_ELEMENT ('d') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.PacketPlayOutBlockChange') +WHITE_SPACE (' ') +NAME_ELEMENT ('block') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.DamageSource') +WHITE_SPACE (' ') +ASTERISK_ELEMENT ('*()') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntitySkeletonAbstract') +WHITE_SPACE (' ') +NAME_ELEMENT ('p') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/SoundEffect;') +CRLF ('\n') +KEYWORD_ELEMENT ('protected') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntitySkeletonWither') +WHITE_SPACE (' ') +NAME_ELEMENT ('p') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/SoundEffect;') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.DedicatedServer') +WHITE_SPACE (' ') +NAME_ELEMENT ('serverCommandQueue') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.WorldGenVillagePieces$WorldGenVillagePiece') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeBase') +WHITE_SPACE (' ') +ASTERISK_ELEMENT ('*()') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderServer') +WHITE_SPACE (' ') +NAME_ELEMENT ('chunkGenerator') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderServer') +WHITE_SPACE (' ') +NAME_ELEMENT ('world') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderServer') +WHITE_SPACE (' ') +NAME_ELEMENT ('chunkLoader') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderServer') +WHITE_SPACE (' ') +NAME_ELEMENT ('chunks') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkRegionLoader') +WHITE_SPACE (' ') +NAME_ELEMENT ('d') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('caa') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Lccg;') +CLOSE_PAREN (')') +PRIMITIVE ('Z') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bwx') +WHITE_SPACE (' ') +NAME_ELEMENT ('n') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bwx') +WHITE_SPACE (' ') +NAME_ELEMENT ('o') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.PlayerChunk') +WHITE_SPACE (' ') +NAME_ELEMENT ('dirtyBlocks') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') +WHITE_SPACE (' ') +NAME_ELEMENT ('A') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') +WHITE_SPACE (' ') +NAME_ELEMENT ('B') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') +WHITE_SPACE (' ') +NAME_ELEMENT ('C') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') +WHITE_SPACE (' ') +NAME_ELEMENT ('v') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') +WHITE_SPACE (' ') +NAME_ELEMENT ('w') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') +WHITE_SPACE (' ') +NAME_ELEMENT ('x') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') +WHITE_SPACE (' ') +NAME_ELEMENT ('y') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') +WHITE_SPACE (' ') +NAME_ELEMENT ('j') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') +WHITE_SPACE (' ') +NAME_ELEMENT ('z') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') +WHITE_SPACE (' ') +NAME_ELEMENT ('k') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') +WHITE_SPACE (' ') +NAME_ELEMENT ('l') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderGenerate') +WHITE_SPACE (' ') +NAME_ELEMENT ('m') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.PotionBrewer') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/ItemPotion;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.PotionBrewer') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/PotionRegistry;') +CLASS_VALUE ('Lnet/minecraft/server/Item;') +CLASS_VALUE ('Lnet/minecraft/server/PotionRegistry;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.PotionBrewer') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/ItemPotion;') +CLASS_VALUE ('Lnet/minecraft/server/Item;') +CLASS_VALUE ('Lnet/minecraft/server/ItemPotion;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.PotionBrewer') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/PotionRegistry;') +CLASS_VALUE ('Lnet/minecraft/server/RecipeItemStack;') +CLASS_VALUE ('Lnet/minecraft/server/PotionRegistry;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.CriterionTriggers') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/CriterionTrigger;') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/CriterionTrigger;') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityVillager$MerchantRecipeOptionBook') +CRLF ('\n') +KEYWORD_ELEMENT ('public-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.CreativeModeTab') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') +WHITE_SPACE (' ') +NAME_ELEMENT ('u') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') +WHITE_SPACE (' ') +NAME_ELEMENT ('v') +CRLF ('\n') +KEYWORD_ELEMENT ('public-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') +WHITE_SPACE (' ') +NAME_ELEMENT ('g') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') +WHITE_SPACE (' ') +NAME_ELEMENT ('w') +CRLF ('\n') +KEYWORD_ELEMENT ('public-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') +WHITE_SPACE (' ') +NAME_ELEMENT ('h') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') +WHITE_SPACE (' ') +NAME_ELEMENT ('x') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') +WHITE_SPACE (' ') +NAME_ELEMENT ('I') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') +WHITE_SPACE (' ') +NAME_ELEMENT ('y') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderHell') +WHITE_SPACE (' ') +NAME_ELEMENT ('J') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeSavanna') +WHITE_SPACE (' ') +ASTERISK_ELEMENT ('*()') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderTheEnd') +WHITE_SPACE (' ') +NAME_ELEMENT ('p') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderTheEnd') +WHITE_SPACE (' ') +NAME_ELEMENT ('i') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderTheEnd') +WHITE_SPACE (' ') +NAME_ELEMENT ('j') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderTheEnd') +WHITE_SPACE (' ') +NAME_ELEMENT ('k') +CRLF ('\n') +KEYWORD_ELEMENT ('private-f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ChunkProviderTheEnd') +WHITE_SPACE (' ') +NAME_ELEMENT ('o') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.BiomeForest') +WHITE_SPACE (' ') +ASTERISK_ELEMENT ('*()') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityTrackerEntry') +WHITE_SPACE (' ') +NAME_ELEMENT ('trackedPlayers') +CRLF ('\n') +KEYWORD_ELEMENT ('public+f') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.WorldGenStronghold') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.PotionBrewer$PredicatedCombination') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.WorldLoader') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.MinecraftKey') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Ljava/lang/String;') +CLOSE_PAREN (')') +CLASS_VALUE ('[Ljava/lang/String;') +CRLF ('\n') +KEYWORD_ELEMENT ('default') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.ItemStack') +WHITE_SPACE (' ') +NAME_ELEMENT ('damage') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityExperienceOrb') +WHITE_SPACE (' ') +NAME_ELEMENT ('value') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.EntityMinecartContainer') +WHITE_SPACE (' ') +NAME_ELEMENT ('b') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bib') +WHITE_SPACE (' ') +NAME_ELEMENT ('Q') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bib') +WHITE_SPACE (' ') +NAME_ELEMENT ('aE') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bib') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Lnet/minecraft/server/ItemStack;') +CLASS_VALUE ('Lnet/minecraft/server/TileEntity;') +CLOSE_PAREN (')') +CLASS_VALUE ('Lnet/minecraft/server/ItemStack;') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bib') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +PRIMITIVE ('I') +PRIMITIVE ('I') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bib') +WHITE_SPACE (' ') +NAME_ELEMENT ('ar') +OPEN_PAREN ('(') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('bib') +WHITE_SPACE (' ') +NAME_ELEMENT ('a') +OPEN_PAREN ('(') +CLASS_VALUE ('Lcdr;') +CLOSE_PAREN (')') +PRIMITIVE ('V') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.PathfinderGoalSelector') +WHITE_SPACE (' ') +NAME_ELEMENT ('b') +CRLF ('\n') +KEYWORD_ELEMENT ('public') +WHITE_SPACE (' ') +CLASS_NAME_ELEMENT ('net.minecraft.server.PlayerSelector') +WHITE_SPACE (' ') +NAME_ELEMENT ('c') +OPEN_PAREN ('(') +CLASS_VALUE ('Ljava/lang/String;') +CLOSE_PAREN (')') +CLASS_VALUE ('Ljava/lang/String;') Index: src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/asterisks_at.cfg =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/asterisks_at.cfg (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/asterisks_at.cfg (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,2 @@ +public net.minecraft.network.play.client.CPacketPlayer * +public net.minecraft.network.play.client.CPacketResourcePackStatus *() Index: src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/asterisks_at.txt =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/asterisks_at.txt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/asterisks_at.txt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,20 @@ +Access transformers(0,127) + AtEntryImpl(ENTRY)(0,56) + AtKeywordImpl(KEYWORD)(0,6) + PsiElement(KEYWORD_ELEMENT)('public')(0,6) + PsiWhiteSpace(' ')(6,7) + AtClassNameImpl(CLASS_NAME)(7,54) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.network.play.client.CPacketPlayer')(7,54) + PsiWhiteSpace(' ')(54,55) + AtAsteriskImpl(ASTERISK)(55,56) + PsiElement(ASTERISK_ELEMENT)('*')(55,56) + PsiElement(CRLF)('\n')(56,57) + AtEntryImpl(ENTRY)(57,127) + AtKeywordImpl(KEYWORD)(57,63) + PsiElement(KEYWORD_ELEMENT)('public')(57,63) + PsiWhiteSpace(' ')(63,64) + AtClassNameImpl(CLASS_NAME)(64,123) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.network.play.client.CPacketResourcePackStatus')(64,123) + PsiWhiteSpace(' ')(123,124) + AtAsteriskImpl(ASTERISK)(124,127) + PsiElement(ASTERISK_ELEMENT)('*()')(124,127) Index: src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/comments_at.cfg =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/comments_at.cfg (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/comments_at.cfg (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,6 @@ +# Comment one +# Comment two +private-f net.minecraft.network.ServerStatusResponse$PlayerCountData field_151334_b # Comment after method +public-f net.minecraft.item.ItemStack # Comment after no value +public net.minecraft.network.play.client.CPacketPlayer * # Comment after asterisk +public net.minecraft.item.ItemTool field_77864_a # Comment after field Index: src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/comments_at.txt =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/comments_at.txt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/comments_at.txt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,49 @@ +Access transformers(0,350) + PsiComment(COMMENT)('# Comment one')(0,13) + PsiElement(CRLF)('\n')(13,14) + PsiComment(COMMENT)('# Comment two')(14,27) + PsiElement(CRLF)('\n')(27,28) + AtEntryImpl(ENTRY)(28,111) + AtKeywordImpl(KEYWORD)(28,37) + PsiElement(KEYWORD_ELEMENT)('private-f')(28,37) + PsiWhiteSpace(' ')(37,38) + AtClassNameImpl(CLASS_NAME)(38,96) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.network.ServerStatusResponse$PlayerCountData')(38,96) + PsiWhiteSpace(' ')(96,97) + AtFieldNameImpl(FIELD_NAME)(97,111) + PsiElement(NAME_ELEMENT)('field_151334_b')(97,111) + PsiWhiteSpace(' ')(111,112) + PsiComment(COMMENT)('# Comment after method')(112,134) + PsiElement(CRLF)('\n')(134,135) + AtEntryImpl(ENTRY)(135,172) + AtKeywordImpl(KEYWORD)(135,143) + PsiElement(KEYWORD_ELEMENT)('public-f')(135,143) + PsiWhiteSpace(' ')(143,144) + AtClassNameImpl(CLASS_NAME)(144,172) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.item.ItemStack')(144,172) + PsiWhiteSpace(' ')(172,173) + PsiComment(COMMENT)('# Comment after no value')(173,197) + PsiElement(CRLF)('\n')(197,198) + AtEntryImpl(ENTRY)(198,254) + AtKeywordImpl(KEYWORD)(198,204) + PsiElement(KEYWORD_ELEMENT)('public')(198,204) + PsiWhiteSpace(' ')(204,205) + AtClassNameImpl(CLASS_NAME)(205,252) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.network.play.client.CPacketPlayer')(205,252) + PsiWhiteSpace(' ')(252,253) + AtAsteriskImpl(ASTERISK)(253,254) + PsiElement(ASTERISK_ELEMENT)('*')(253,254) + PsiWhiteSpace(' ')(254,255) + PsiComment(COMMENT)('# Comment after asterisk')(255,279) + PsiElement(CRLF)('\n')(279,280) + AtEntryImpl(ENTRY)(280,328) + AtKeywordImpl(KEYWORD)(280,286) + PsiElement(KEYWORD_ELEMENT)('public')(280,286) + PsiWhiteSpace(' ')(286,287) + AtClassNameImpl(CLASS_NAME)(287,314) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.item.ItemTool')(287,314) + PsiWhiteSpace(' ')(314,315) + AtFieldNameImpl(FIELD_NAME)(315,328) + PsiElement(NAME_ELEMENT)('field_77864_a')(315,328) + PsiWhiteSpace(' ')(328,329) + PsiComment(COMMENT)('# Comment after field')(329,350) Index: src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/fields_at.cfg =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/fields_at.cfg (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/fields_at.cfg (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,9 @@ +public net.minecraft.entity.player.EntityPlayer field_184827_bp # PLAYER_MODEL_FLAG +public net.minecraft.entity.player.EntityPlayer field_184828_bq # MAIN_HAND +public net.minecraft.entity.player.EntityPlayer field_184829_a # field_184829_a +public net.minecraft.entity.player.EntityPlayer field_184830_b # PLAYER_SCORE +public net.minecraft.entity.player.EntityPlayer field_71078_a # theInventoryEnderChest +public net.minecraft.entity.player.EntityPlayerMP field_71144_ck # lastExperience +public net.minecraft.entity.player.InventoryPlayer field_184440_g # main_inventory +public net.minecraft.entity.player.PlayerCapabilities field_75096_f # flySpeed +public net.minecraft.entity.player.PlayerCapabilities field_75097_g # walkSpeed Index: src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/fields_at.txt =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/fields_at.txt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/fields_at.txt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,108 @@ +Access transformers(0,728) + AtEntryImpl(ENTRY)(0,63) + AtKeywordImpl(KEYWORD)(0,6) + PsiElement(KEYWORD_ELEMENT)('public')(0,6) + PsiWhiteSpace(' ')(6,7) + AtClassNameImpl(CLASS_NAME)(7,47) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.EntityPlayer')(7,47) + PsiWhiteSpace(' ')(47,48) + AtFieldNameImpl(FIELD_NAME)(48,63) + PsiElement(NAME_ELEMENT)('field_184827_bp')(48,63) + PsiWhiteSpace(' ')(63,64) + PsiComment(COMMENT)('# PLAYER_MODEL_FLAG')(64,83) + PsiElement(CRLF)('\n')(83,84) + AtEntryImpl(ENTRY)(84,147) + AtKeywordImpl(KEYWORD)(84,90) + PsiElement(KEYWORD_ELEMENT)('public')(84,90) + PsiWhiteSpace(' ')(90,91) + AtClassNameImpl(CLASS_NAME)(91,131) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.EntityPlayer')(91,131) + PsiWhiteSpace(' ')(131,132) + AtFieldNameImpl(FIELD_NAME)(132,147) + PsiElement(NAME_ELEMENT)('field_184828_bq')(132,147) + PsiWhiteSpace(' ')(147,148) + PsiComment(COMMENT)('# MAIN_HAND')(148,159) + PsiElement(CRLF)('\n')(159,160) + AtEntryImpl(ENTRY)(160,222) + AtKeywordImpl(KEYWORD)(160,166) + PsiElement(KEYWORD_ELEMENT)('public')(160,166) + PsiWhiteSpace(' ')(166,167) + AtClassNameImpl(CLASS_NAME)(167,207) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.EntityPlayer')(167,207) + PsiWhiteSpace(' ')(207,208) + AtFieldNameImpl(FIELD_NAME)(208,222) + PsiElement(NAME_ELEMENT)('field_184829_a')(208,222) + PsiWhiteSpace(' ')(222,223) + PsiComment(COMMENT)('# field_184829_a')(223,239) + PsiElement(CRLF)('\n')(239,240) + AtEntryImpl(ENTRY)(240,302) + AtKeywordImpl(KEYWORD)(240,246) + PsiElement(KEYWORD_ELEMENT)('public')(240,246) + PsiWhiteSpace(' ')(246,247) + AtClassNameImpl(CLASS_NAME)(247,287) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.EntityPlayer')(247,287) + PsiWhiteSpace(' ')(287,288) + AtFieldNameImpl(FIELD_NAME)(288,302) + PsiElement(NAME_ELEMENT)('field_184830_b')(288,302) + PsiWhiteSpace(' ')(302,303) + PsiComment(COMMENT)('# PLAYER_SCORE')(303,317) + PsiElement(CRLF)('\n')(317,318) + AtEntryImpl(ENTRY)(318,379) + AtKeywordImpl(KEYWORD)(318,324) + PsiElement(KEYWORD_ELEMENT)('public')(318,324) + PsiWhiteSpace(' ')(324,325) + AtClassNameImpl(CLASS_NAME)(325,365) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.EntityPlayer')(325,365) + PsiWhiteSpace(' ')(365,366) + AtFieldNameImpl(FIELD_NAME)(366,379) + PsiElement(NAME_ELEMENT)('field_71078_a')(366,379) + PsiWhiteSpace(' ')(379,380) + PsiComment(COMMENT)('# theInventoryEnderChest')(380,404) + PsiElement(CRLF)('\n')(404,405) + AtEntryImpl(ENTRY)(405,469) + AtKeywordImpl(KEYWORD)(405,411) + PsiElement(KEYWORD_ELEMENT)('public')(405,411) + PsiWhiteSpace(' ')(411,412) + AtClassNameImpl(CLASS_NAME)(412,454) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.EntityPlayerMP')(412,454) + PsiWhiteSpace(' ')(454,455) + AtFieldNameImpl(FIELD_NAME)(455,469) + PsiElement(NAME_ELEMENT)('field_71144_ck')(455,469) + PsiWhiteSpace(' ')(469,470) + PsiComment(COMMENT)('# lastExperience')(470,486) + PsiElement(CRLF)('\n')(486,487) + AtEntryImpl(ENTRY)(487,552) + AtKeywordImpl(KEYWORD)(487,493) + PsiElement(KEYWORD_ELEMENT)('public')(487,493) + PsiWhiteSpace(' ')(493,494) + AtClassNameImpl(CLASS_NAME)(494,537) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.InventoryPlayer')(494,537) + PsiWhiteSpace(' ')(537,538) + AtFieldNameImpl(FIELD_NAME)(538,552) + PsiElement(NAME_ELEMENT)('field_184440_g')(538,552) + PsiWhiteSpace(' ')(552,553) + PsiComment(COMMENT)('# main_inventory')(553,569) + PsiElement(CRLF)('\n')(569,570) + AtEntryImpl(ENTRY)(570,637) + AtKeywordImpl(KEYWORD)(570,576) + PsiElement(KEYWORD_ELEMENT)('public')(570,576) + PsiWhiteSpace(' ')(576,577) + AtClassNameImpl(CLASS_NAME)(577,623) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.PlayerCapabilities')(577,623) + PsiWhiteSpace(' ')(623,624) + AtFieldNameImpl(FIELD_NAME)(624,637) + PsiElement(NAME_ELEMENT)('field_75096_f')(624,637) + PsiWhiteSpace(' ')(637,638) + PsiComment(COMMENT)('# flySpeed')(638,648) + PsiElement(CRLF)('\n')(648,649) + AtEntryImpl(ENTRY)(649,716) + AtKeywordImpl(KEYWORD)(649,655) + PsiElement(KEYWORD_ELEMENT)('public')(649,655) + PsiWhiteSpace(' ')(655,656) + AtClassNameImpl(CLASS_NAME)(656,702) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.player.PlayerCapabilities')(656,702) + PsiWhiteSpace(' ')(702,703) + AtFieldNameImpl(FIELD_NAME)(703,716) + PsiElement(NAME_ELEMENT)('field_75097_g')(703,716) + PsiWhiteSpace(' ')(716,717) + PsiComment(COMMENT)('# walkSpeed')(717,728) Index: src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/funcs_at.cfg =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/funcs_at.cfg (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/funcs_at.cfg (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,20 @@ +public net.minecraft.server.management.UserList func_152680_h()V # removeExpired +public net.minecraft.server.management.UserList func_152681_a(Lcom/mojang/authlib/GameProfile;)Ljava/lang/String; # getObjectKey +public net.minecraft.server.management.UserList func_152681_a(Ljava/lang/Object;)Ljava/lang/String; # getObjectKey +public net.minecraft.server.management.UserList func_152688_e()Ljava/util/Map; +public net.minecraft.server.management.UserListBans func_152681_a(Lcom/mojang/authlib/GameProfile;)Ljava/lang/String; # getObjectKey +public net.minecraft.server.management.UserListBans func_152681_a(Ljava/lang/Object;)Ljava/lang/String; # getObjectKey +public net.minecraft.server.management.UserListEntry func_152640_f()Ljava/lang/Object; # getValue +public net.minecraft.server.management.UserListIPBans func_152707_c(Ljava/net/SocketAddress;)Ljava/lang/String; # addressToString +public net.minecraft.server.management.UserListOps func_152681_a(Lcom/mojang/authlib/GameProfile;)Ljava/lang/String; # getObjectKey +public net.minecraft.server.management.UserListOps func_152681_a(Ljava/lang/Object;)Ljava/lang/String; # getObjectKey +public net.minecraft.server.management.UserListWhitelist func_152681_a(Lcom/mojang/authlib/GameProfile;)Ljava/lang/String; # getObjectKey +public net.minecraft.server.management.UserListWhitelist func_152681_a(Ljava/lang/Object;)Ljava/lang/String; # getObjectKey +public net.minecraft.util.DamageSource func_151518_m()Lnet/minecraft/util/DamageSource; # setDamageIsAbsolute +public net.minecraft.util.DamageSource func_76348_h()Lnet/minecraft/util/DamageSource; # setDamageBypassesArmor +public net.minecraft.util.DamageSource func_76359_i()Lnet/minecraft/util/DamageSource; # setDamageAllowedInCreativeMode +public net.minecraft.util.DamageSource func_76361_j()Lnet/minecraft/util/DamageSource; # setFireDamage +public net.minecraft.util.DamageSource (Ljava/lang/String;)V # protected DamageSource (String damageTypeIn) +public net.minecraft.world.World func_175663_a(IIIIIIZ)Z # isAreaLoaded +public net.minecraft.server.MinecraftServer func_175584_a(Ljava/lang/String;Lnet/minecraft/world/storage/ISaveHandler;)V # setResourcePackFromWorld +public net.minecraft.tileentity.MobSpawnerBaseLogic func_180613_a(Lnet/minecraft/entity/Entity;Z)Lnet/minecraft/entity/Entity; # spawnNewEntity Index: src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/funcs_at.txt =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/funcs_at.txt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/funcs_at.txt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,380 @@ +Access transformers(0,2318) + AtEntryImpl(ENTRY)(0,64) + AtKeywordImpl(KEYWORD)(0,6) + PsiElement(KEYWORD_ELEMENT)('public')(0,6) + PsiWhiteSpace(' ')(6,7) + AtClassNameImpl(CLASS_NAME)(7,47) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserList')(7,47) + PsiWhiteSpace(' ')(47,48) + AtFunctionImpl(FUNCTION)(48,64) + AtFuncNameImpl(FUNC_NAME)(48,61) + PsiElement(NAME_ELEMENT)('func_152680_h')(48,61) + PsiElement(OPEN_PAREN)('(')(61,62) + PsiElement(CLOSE_PAREN)(')')(62,63) + AtReturnValueImpl(RETURN_VALUE)(63,64) + PsiElement(PRIMITIVE)('V')(63,64) + PsiWhiteSpace(' ')(64,65) + PsiComment(COMMENT)('# removeExpired')(65,80) + PsiElement(CRLF)('\n')(80,81) + AtEntryImpl(ENTRY)(81,194) + AtKeywordImpl(KEYWORD)(81,87) + PsiElement(KEYWORD_ELEMENT)('public')(81,87) + PsiWhiteSpace(' ')(87,88) + AtClassNameImpl(CLASS_NAME)(88,128) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserList')(88,128) + PsiWhiteSpace(' ')(128,129) + AtFunctionImpl(FUNCTION)(129,194) + AtFuncNameImpl(FUNC_NAME)(129,142) + PsiElement(NAME_ELEMENT)('func_152681_a')(129,142) + PsiElement(OPEN_PAREN)('(')(142,143) + AtArgumentImpl(ARGUMENT)(143,175) + PsiElement(CLASS_VALUE)('Lcom/mojang/authlib/GameProfile;')(143,175) + PsiElement(CLOSE_PAREN)(')')(175,176) + AtReturnValueImpl(RETURN_VALUE)(176,194) + PsiElement(CLASS_VALUE)('Ljava/lang/String;')(176,194) + PsiWhiteSpace(' ')(194,195) + PsiComment(COMMENT)('# getObjectKey')(195,209) + PsiElement(CRLF)('\n')(209,210) + AtEntryImpl(ENTRY)(210,309) + AtKeywordImpl(KEYWORD)(210,216) + PsiElement(KEYWORD_ELEMENT)('public')(210,216) + PsiWhiteSpace(' ')(216,217) + AtClassNameImpl(CLASS_NAME)(217,257) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserList')(217,257) + PsiWhiteSpace(' ')(257,258) + AtFunctionImpl(FUNCTION)(258,309) + AtFuncNameImpl(FUNC_NAME)(258,271) + PsiElement(NAME_ELEMENT)('func_152681_a')(258,271) + PsiElement(OPEN_PAREN)('(')(271,272) + AtArgumentImpl(ARGUMENT)(272,290) + PsiElement(CLASS_VALUE)('Ljava/lang/Object;')(272,290) + PsiElement(CLOSE_PAREN)(')')(290,291) + AtReturnValueImpl(RETURN_VALUE)(291,309) + PsiElement(CLASS_VALUE)('Ljava/lang/String;')(291,309) + PsiWhiteSpace(' ')(309,310) + PsiComment(COMMENT)('# getObjectKey')(310,324) + PsiElement(CRLF)('\n')(324,325) + AtEntryImpl(ENTRY)(325,403) + AtKeywordImpl(KEYWORD)(325,331) + PsiElement(KEYWORD_ELEMENT)('public')(325,331) + PsiWhiteSpace(' ')(331,332) + AtClassNameImpl(CLASS_NAME)(332,372) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserList')(332,372) + PsiWhiteSpace(' ')(372,373) + AtFunctionImpl(FUNCTION)(373,403) + AtFuncNameImpl(FUNC_NAME)(373,386) + PsiElement(NAME_ELEMENT)('func_152688_e')(373,386) + PsiElement(OPEN_PAREN)('(')(386,387) + PsiElement(CLOSE_PAREN)(')')(387,388) + AtReturnValueImpl(RETURN_VALUE)(388,403) + PsiElement(CLASS_VALUE)('Ljava/util/Map;')(388,403) + PsiElement(CRLF)('\n')(403,404) + AtEntryImpl(ENTRY)(404,521) + AtKeywordImpl(KEYWORD)(404,410) + PsiElement(KEYWORD_ELEMENT)('public')(404,410) + PsiWhiteSpace(' ')(410,411) + AtClassNameImpl(CLASS_NAME)(411,455) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserListBans')(411,455) + PsiWhiteSpace(' ')(455,456) + AtFunctionImpl(FUNCTION)(456,521) + AtFuncNameImpl(FUNC_NAME)(456,469) + PsiElement(NAME_ELEMENT)('func_152681_a')(456,469) + PsiElement(OPEN_PAREN)('(')(469,470) + AtArgumentImpl(ARGUMENT)(470,502) + PsiElement(CLASS_VALUE)('Lcom/mojang/authlib/GameProfile;')(470,502) + PsiElement(CLOSE_PAREN)(')')(502,503) + AtReturnValueImpl(RETURN_VALUE)(503,521) + PsiElement(CLASS_VALUE)('Ljava/lang/String;')(503,521) + PsiWhiteSpace(' ')(521,522) + PsiComment(COMMENT)('# getObjectKey')(522,536) + PsiElement(CRLF)('\n')(536,537) + AtEntryImpl(ENTRY)(537,640) + AtKeywordImpl(KEYWORD)(537,543) + PsiElement(KEYWORD_ELEMENT)('public')(537,543) + PsiWhiteSpace(' ')(543,544) + AtClassNameImpl(CLASS_NAME)(544,588) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserListBans')(544,588) + PsiWhiteSpace(' ')(588,589) + AtFunctionImpl(FUNCTION)(589,640) + AtFuncNameImpl(FUNC_NAME)(589,602) + PsiElement(NAME_ELEMENT)('func_152681_a')(589,602) + PsiElement(OPEN_PAREN)('(')(602,603) + AtArgumentImpl(ARGUMENT)(603,621) + PsiElement(CLASS_VALUE)('Ljava/lang/Object;')(603,621) + PsiElement(CLOSE_PAREN)(')')(621,622) + AtReturnValueImpl(RETURN_VALUE)(622,640) + PsiElement(CLASS_VALUE)('Ljava/lang/String;')(622,640) + PsiWhiteSpace(' ')(640,641) + PsiComment(COMMENT)('# getObjectKey')(641,655) + PsiElement(CRLF)('\n')(655,656) + AtEntryImpl(ENTRY)(656,742) + AtKeywordImpl(KEYWORD)(656,662) + PsiElement(KEYWORD_ELEMENT)('public')(656,662) + PsiWhiteSpace(' ')(662,663) + AtClassNameImpl(CLASS_NAME)(663,708) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserListEntry')(663,708) + PsiWhiteSpace(' ')(708,709) + AtFunctionImpl(FUNCTION)(709,742) + AtFuncNameImpl(FUNC_NAME)(709,722) + PsiElement(NAME_ELEMENT)('func_152640_f')(709,722) + PsiElement(OPEN_PAREN)('(')(722,723) + PsiElement(CLOSE_PAREN)(')')(723,724) + AtReturnValueImpl(RETURN_VALUE)(724,742) + PsiElement(CLASS_VALUE)('Ljava/lang/Object;')(724,742) + PsiWhiteSpace(' ')(742,743) + PsiComment(COMMENT)('# getValue')(743,753) + PsiElement(CRLF)('\n')(753,754) + AtEntryImpl(ENTRY)(754,865) + AtKeywordImpl(KEYWORD)(754,760) + PsiElement(KEYWORD_ELEMENT)('public')(754,760) + PsiWhiteSpace(' ')(760,761) + AtClassNameImpl(CLASS_NAME)(761,807) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserListIPBans')(761,807) + PsiWhiteSpace(' ')(807,808) + AtFunctionImpl(FUNCTION)(808,865) + AtFuncNameImpl(FUNC_NAME)(808,821) + PsiElement(NAME_ELEMENT)('func_152707_c')(808,821) + PsiElement(OPEN_PAREN)('(')(821,822) + AtArgumentImpl(ARGUMENT)(822,846) + PsiElement(CLASS_VALUE)('Ljava/net/SocketAddress;')(822,846) + PsiElement(CLOSE_PAREN)(')')(846,847) + AtReturnValueImpl(RETURN_VALUE)(847,865) + PsiElement(CLASS_VALUE)('Ljava/lang/String;')(847,865) + PsiWhiteSpace(' ')(865,866) + PsiComment(COMMENT)('# addressToString')(866,883) + PsiElement(CRLF)('\n')(883,884) + AtEntryImpl(ENTRY)(884,1000) + AtKeywordImpl(KEYWORD)(884,890) + PsiElement(KEYWORD_ELEMENT)('public')(884,890) + PsiWhiteSpace(' ')(890,891) + AtClassNameImpl(CLASS_NAME)(891,934) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserListOps')(891,934) + PsiWhiteSpace(' ')(934,935) + AtFunctionImpl(FUNCTION)(935,1000) + AtFuncNameImpl(FUNC_NAME)(935,948) + PsiElement(NAME_ELEMENT)('func_152681_a')(935,948) + PsiElement(OPEN_PAREN)('(')(948,949) + AtArgumentImpl(ARGUMENT)(949,981) + PsiElement(CLASS_VALUE)('Lcom/mojang/authlib/GameProfile;')(949,981) + PsiElement(CLOSE_PAREN)(')')(981,982) + AtReturnValueImpl(RETURN_VALUE)(982,1000) + PsiElement(CLASS_VALUE)('Ljava/lang/String;')(982,1000) + PsiWhiteSpace(' ')(1000,1001) + PsiComment(COMMENT)('# getObjectKey')(1001,1015) + PsiElement(CRLF)('\n')(1015,1016) + AtEntryImpl(ENTRY)(1016,1118) + AtKeywordImpl(KEYWORD)(1016,1022) + PsiElement(KEYWORD_ELEMENT)('public')(1016,1022) + PsiWhiteSpace(' ')(1022,1023) + AtClassNameImpl(CLASS_NAME)(1023,1066) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserListOps')(1023,1066) + PsiWhiteSpace(' ')(1066,1067) + AtFunctionImpl(FUNCTION)(1067,1118) + AtFuncNameImpl(FUNC_NAME)(1067,1080) + PsiElement(NAME_ELEMENT)('func_152681_a')(1067,1080) + PsiElement(OPEN_PAREN)('(')(1080,1081) + AtArgumentImpl(ARGUMENT)(1081,1099) + PsiElement(CLASS_VALUE)('Ljava/lang/Object;')(1081,1099) + PsiElement(CLOSE_PAREN)(')')(1099,1100) + AtReturnValueImpl(RETURN_VALUE)(1100,1118) + PsiElement(CLASS_VALUE)('Ljava/lang/String;')(1100,1118) + PsiWhiteSpace(' ')(1118,1119) + PsiComment(COMMENT)('# getObjectKey')(1119,1133) + PsiElement(CRLF)('\n')(1133,1134) + AtEntryImpl(ENTRY)(1134,1256) + AtKeywordImpl(KEYWORD)(1134,1140) + PsiElement(KEYWORD_ELEMENT)('public')(1134,1140) + PsiWhiteSpace(' ')(1140,1141) + AtClassNameImpl(CLASS_NAME)(1141,1190) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserListWhitelist')(1141,1190) + PsiWhiteSpace(' ')(1190,1191) + AtFunctionImpl(FUNCTION)(1191,1256) + AtFuncNameImpl(FUNC_NAME)(1191,1204) + PsiElement(NAME_ELEMENT)('func_152681_a')(1191,1204) + PsiElement(OPEN_PAREN)('(')(1204,1205) + AtArgumentImpl(ARGUMENT)(1205,1237) + PsiElement(CLASS_VALUE)('Lcom/mojang/authlib/GameProfile;')(1205,1237) + PsiElement(CLOSE_PAREN)(')')(1237,1238) + AtReturnValueImpl(RETURN_VALUE)(1238,1256) + PsiElement(CLASS_VALUE)('Ljava/lang/String;')(1238,1256) + PsiWhiteSpace(' ')(1256,1257) + PsiComment(COMMENT)('# getObjectKey')(1257,1271) + PsiElement(CRLF)('\n')(1271,1272) + AtEntryImpl(ENTRY)(1272,1380) + AtKeywordImpl(KEYWORD)(1272,1278) + PsiElement(KEYWORD_ELEMENT)('public')(1272,1278) + PsiWhiteSpace(' ')(1278,1279) + AtClassNameImpl(CLASS_NAME)(1279,1328) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.management.UserListWhitelist')(1279,1328) + PsiWhiteSpace(' ')(1328,1329) + AtFunctionImpl(FUNCTION)(1329,1380) + AtFuncNameImpl(FUNC_NAME)(1329,1342) + PsiElement(NAME_ELEMENT)('func_152681_a')(1329,1342) + PsiElement(OPEN_PAREN)('(')(1342,1343) + AtArgumentImpl(ARGUMENT)(1343,1361) + PsiElement(CLASS_VALUE)('Ljava/lang/Object;')(1343,1361) + PsiElement(CLOSE_PAREN)(')')(1361,1362) + AtReturnValueImpl(RETURN_VALUE)(1362,1380) + PsiElement(CLASS_VALUE)('Ljava/lang/String;')(1362,1380) + PsiWhiteSpace(' ')(1380,1381) + PsiComment(COMMENT)('# getObjectKey')(1381,1395) + PsiElement(CRLF)('\n')(1395,1396) + AtEntryImpl(ENTRY)(1396,1483) + AtKeywordImpl(KEYWORD)(1396,1402) + PsiElement(KEYWORD_ELEMENT)('public')(1396,1402) + PsiWhiteSpace(' ')(1402,1403) + AtClassNameImpl(CLASS_NAME)(1403,1434) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.util.DamageSource')(1403,1434) + PsiWhiteSpace(' ')(1434,1435) + AtFunctionImpl(FUNCTION)(1435,1483) + AtFuncNameImpl(FUNC_NAME)(1435,1448) + PsiElement(NAME_ELEMENT)('func_151518_m')(1435,1448) + PsiElement(OPEN_PAREN)('(')(1448,1449) + PsiElement(CLOSE_PAREN)(')')(1449,1450) + AtReturnValueImpl(RETURN_VALUE)(1450,1483) + PsiElement(CLASS_VALUE)('Lnet/minecraft/util/DamageSource;')(1450,1483) + PsiWhiteSpace(' ')(1483,1484) + PsiComment(COMMENT)('# setDamageIsAbsolute')(1484,1505) + PsiElement(CRLF)('\n')(1505,1506) + AtEntryImpl(ENTRY)(1506,1592) + AtKeywordImpl(KEYWORD)(1506,1512) + PsiElement(KEYWORD_ELEMENT)('public')(1506,1512) + PsiWhiteSpace(' ')(1512,1513) + AtClassNameImpl(CLASS_NAME)(1513,1544) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.util.DamageSource')(1513,1544) + PsiWhiteSpace(' ')(1544,1545) + AtFunctionImpl(FUNCTION)(1545,1592) + AtFuncNameImpl(FUNC_NAME)(1545,1557) + PsiElement(NAME_ELEMENT)('func_76348_h')(1545,1557) + PsiElement(OPEN_PAREN)('(')(1557,1558) + PsiElement(CLOSE_PAREN)(')')(1558,1559) + AtReturnValueImpl(RETURN_VALUE)(1559,1592) + PsiElement(CLASS_VALUE)('Lnet/minecraft/util/DamageSource;')(1559,1592) + PsiWhiteSpace(' ')(1592,1593) + PsiComment(COMMENT)('# setDamageBypassesArmor')(1593,1617) + PsiElement(CRLF)('\n')(1617,1618) + AtEntryImpl(ENTRY)(1618,1704) + AtKeywordImpl(KEYWORD)(1618,1624) + PsiElement(KEYWORD_ELEMENT)('public')(1618,1624) + PsiWhiteSpace(' ')(1624,1625) + AtClassNameImpl(CLASS_NAME)(1625,1656) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.util.DamageSource')(1625,1656) + PsiWhiteSpace(' ')(1656,1657) + AtFunctionImpl(FUNCTION)(1657,1704) + AtFuncNameImpl(FUNC_NAME)(1657,1669) + PsiElement(NAME_ELEMENT)('func_76359_i')(1657,1669) + PsiElement(OPEN_PAREN)('(')(1669,1670) + PsiElement(CLOSE_PAREN)(')')(1670,1671) + AtReturnValueImpl(RETURN_VALUE)(1671,1704) + PsiElement(CLASS_VALUE)('Lnet/minecraft/util/DamageSource;')(1671,1704) + PsiWhiteSpace(' ')(1704,1705) + PsiComment(COMMENT)('# setDamageAllowedInCreativeMode')(1705,1737) + PsiElement(CRLF)('\n')(1737,1738) + AtEntryImpl(ENTRY)(1738,1824) + AtKeywordImpl(KEYWORD)(1738,1744) + PsiElement(KEYWORD_ELEMENT)('public')(1738,1744) + PsiWhiteSpace(' ')(1744,1745) + AtClassNameImpl(CLASS_NAME)(1745,1776) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.util.DamageSource')(1745,1776) + PsiWhiteSpace(' ')(1776,1777) + AtFunctionImpl(FUNCTION)(1777,1824) + AtFuncNameImpl(FUNC_NAME)(1777,1789) + PsiElement(NAME_ELEMENT)('func_76361_j')(1777,1789) + PsiElement(OPEN_PAREN)('(')(1789,1790) + PsiElement(CLOSE_PAREN)(')')(1790,1791) + AtReturnValueImpl(RETURN_VALUE)(1791,1824) + PsiElement(CLASS_VALUE)('Lnet/minecraft/util/DamageSource;')(1791,1824) + PsiWhiteSpace(' ')(1824,1825) + PsiComment(COMMENT)('# setFireDamage')(1825,1840) + PsiElement(CRLF)('\n')(1840,1841) + AtEntryImpl(ENTRY)(1841,1907) + AtKeywordImpl(KEYWORD)(1841,1847) + PsiElement(KEYWORD_ELEMENT)('public')(1841,1847) + PsiWhiteSpace(' ')(1847,1848) + AtClassNameImpl(CLASS_NAME)(1848,1879) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.util.DamageSource')(1848,1879) + PsiWhiteSpace(' ')(1879,1880) + AtFunctionImpl(FUNCTION)(1880,1907) + AtFuncNameImpl(FUNC_NAME)(1880,1886) + PsiElement(NAME_ELEMENT)('')(1880,1886) + PsiElement(OPEN_PAREN)('(')(1886,1887) + AtArgumentImpl(ARGUMENT)(1887,1905) + PsiElement(CLASS_VALUE)('Ljava/lang/String;')(1887,1905) + PsiElement(CLOSE_PAREN)(')')(1905,1906) + AtReturnValueImpl(RETURN_VALUE)(1906,1907) + PsiElement(PRIMITIVE)('V')(1906,1907) + PsiWhiteSpace(' ')(1907,1908) + PsiComment(COMMENT)('# protected DamageSource (String damageTypeIn)')(1908,1954) + PsiElement(CRLF)('\n')(1954,1955) + AtEntryImpl(ENTRY)(1955,2011) + AtKeywordImpl(KEYWORD)(1955,1961) + PsiElement(KEYWORD_ELEMENT)('public')(1955,1961) + PsiWhiteSpace(' ')(1961,1962) + AtClassNameImpl(CLASS_NAME)(1962,1987) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.world.World')(1962,1987) + PsiWhiteSpace(' ')(1987,1988) + AtFunctionImpl(FUNCTION)(1988,2011) + AtFuncNameImpl(FUNC_NAME)(1988,2001) + PsiElement(NAME_ELEMENT)('func_175663_a')(1988,2001) + PsiElement(OPEN_PAREN)('(')(2001,2002) + AtArgumentImpl(ARGUMENT)(2002,2003) + PsiElement(PRIMITIVE)('I')(2002,2003) + AtArgumentImpl(ARGUMENT)(2003,2004) + PsiElement(PRIMITIVE)('I')(2003,2004) + AtArgumentImpl(ARGUMENT)(2004,2005) + PsiElement(PRIMITIVE)('I')(2004,2005) + AtArgumentImpl(ARGUMENT)(2005,2006) + PsiElement(PRIMITIVE)('I')(2005,2006) + AtArgumentImpl(ARGUMENT)(2006,2007) + PsiElement(PRIMITIVE)('I')(2006,2007) + AtArgumentImpl(ARGUMENT)(2007,2008) + PsiElement(PRIMITIVE)('I')(2007,2008) + AtArgumentImpl(ARGUMENT)(2008,2009) + PsiElement(PRIMITIVE)('Z')(2008,2009) + PsiElement(CLOSE_PAREN)(')')(2009,2010) + AtReturnValueImpl(RETURN_VALUE)(2010,2011) + PsiElement(PRIMITIVE)('Z')(2010,2011) + PsiWhiteSpace(' ')(2011,2012) + PsiComment(COMMENT)('# isAreaLoaded')(2012,2026) + PsiElement(CRLF)('\n')(2026,2027) + AtEntryImpl(ENTRY)(2027,2147) + AtKeywordImpl(KEYWORD)(2027,2033) + PsiElement(KEYWORD_ELEMENT)('public')(2027,2033) + PsiWhiteSpace(' ')(2033,2034) + AtClassNameImpl(CLASS_NAME)(2034,2070) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.server.MinecraftServer')(2034,2070) + PsiWhiteSpace(' ')(2070,2071) + AtFunctionImpl(FUNCTION)(2071,2147) + AtFuncNameImpl(FUNC_NAME)(2071,2084) + PsiElement(NAME_ELEMENT)('func_175584_a')(2071,2084) + PsiElement(OPEN_PAREN)('(')(2084,2085) + AtArgumentImpl(ARGUMENT)(2085,2103) + PsiElement(CLASS_VALUE)('Ljava/lang/String;')(2085,2103) + AtArgumentImpl(ARGUMENT)(2103,2145) + PsiElement(CLASS_VALUE)('Lnet/minecraft/world/storage/ISaveHandler;')(2103,2145) + PsiElement(CLOSE_PAREN)(')')(2145,2146) + AtReturnValueImpl(RETURN_VALUE)(2146,2147) + PsiElement(PRIMITIVE)('V')(2146,2147) + PsiWhiteSpace(' ')(2147,2148) + PsiComment(COMMENT)('# setResourcePackFromWorld')(2148,2174) + PsiElement(CRLF)('\n')(2174,2175) + AtEntryImpl(ENTRY)(2175,2301) + AtKeywordImpl(KEYWORD)(2175,2181) + PsiElement(KEYWORD_ELEMENT)('public')(2175,2181) + PsiWhiteSpace(' ')(2181,2182) + AtClassNameImpl(CLASS_NAME)(2182,2226) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.tileentity.MobSpawnerBaseLogic')(2182,2226) + PsiWhiteSpace(' ')(2226,2227) + AtFunctionImpl(FUNCTION)(2227,2301) + AtFuncNameImpl(FUNC_NAME)(2227,2240) + PsiElement(NAME_ELEMENT)('func_180613_a')(2227,2240) + PsiElement(OPEN_PAREN)('(')(2240,2241) + AtArgumentImpl(ARGUMENT)(2241,2270) + PsiElement(CLASS_VALUE)('Lnet/minecraft/entity/Entity;')(2241,2270) + AtArgumentImpl(ARGUMENT)(2270,2271) + PsiElement(PRIMITIVE)('Z')(2270,2271) + PsiElement(CLOSE_PAREN)(')')(2271,2272) + AtReturnValueImpl(RETURN_VALUE)(2272,2301) + PsiElement(CLASS_VALUE)('Lnet/minecraft/entity/Entity;')(2272,2301) + PsiWhiteSpace(' ')(2301,2302) + PsiComment(COMMENT)('# spawnNewEntity')(2302,2318) Index: src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/keywords_at.cfg =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/keywords_at.cfg (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/keywords_at.cfg (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,12 @@ +public package.class field +public-f package.class field +public+f package.class field +private package.class field +private-f package.class field +private+f package.class field +protected package.class field +protected-f package.class field +protected+f package.class field +default package.class field +default-f package.class field +default+f package.class field Index: src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/keywords_at.txt =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/keywords_at.txt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/keywords_at.txt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,120 @@ +Access transformers(0,354) + AtEntryImpl(ENTRY)(0,26) + AtKeywordImpl(KEYWORD)(0,6) + PsiElement(KEYWORD_ELEMENT)('public')(0,6) + PsiWhiteSpace(' ')(6,7) + AtClassNameImpl(CLASS_NAME)(7,20) + PsiElement(CLASS_NAME_ELEMENT)('package.class')(7,20) + PsiWhiteSpace(' ')(20,21) + AtFieldNameImpl(FIELD_NAME)(21,26) + PsiElement(NAME_ELEMENT)('field')(21,26) + PsiElement(CRLF)('\n')(26,27) + AtEntryImpl(ENTRY)(27,55) + AtKeywordImpl(KEYWORD)(27,35) + PsiElement(KEYWORD_ELEMENT)('public-f')(27,35) + PsiWhiteSpace(' ')(35,36) + AtClassNameImpl(CLASS_NAME)(36,49) + PsiElement(CLASS_NAME_ELEMENT)('package.class')(36,49) + PsiWhiteSpace(' ')(49,50) + AtFieldNameImpl(FIELD_NAME)(50,55) + PsiElement(NAME_ELEMENT)('field')(50,55) + PsiElement(CRLF)('\n')(55,56) + AtEntryImpl(ENTRY)(56,84) + AtKeywordImpl(KEYWORD)(56,64) + PsiElement(KEYWORD_ELEMENT)('public+f')(56,64) + PsiWhiteSpace(' ')(64,65) + AtClassNameImpl(CLASS_NAME)(65,78) + PsiElement(CLASS_NAME_ELEMENT)('package.class')(65,78) + PsiWhiteSpace(' ')(78,79) + AtFieldNameImpl(FIELD_NAME)(79,84) + PsiElement(NAME_ELEMENT)('field')(79,84) + PsiElement(CRLF)('\n')(84,85) + AtEntryImpl(ENTRY)(85,112) + AtKeywordImpl(KEYWORD)(85,92) + PsiElement(KEYWORD_ELEMENT)('private')(85,92) + PsiWhiteSpace(' ')(92,93) + AtClassNameImpl(CLASS_NAME)(93,106) + PsiElement(CLASS_NAME_ELEMENT)('package.class')(93,106) + PsiWhiteSpace(' ')(106,107) + AtFieldNameImpl(FIELD_NAME)(107,112) + PsiElement(NAME_ELEMENT)('field')(107,112) + PsiElement(CRLF)('\n')(112,113) + AtEntryImpl(ENTRY)(113,142) + AtKeywordImpl(KEYWORD)(113,122) + PsiElement(KEYWORD_ELEMENT)('private-f')(113,122) + PsiWhiteSpace(' ')(122,123) + AtClassNameImpl(CLASS_NAME)(123,136) + PsiElement(CLASS_NAME_ELEMENT)('package.class')(123,136) + PsiWhiteSpace(' ')(136,137) + AtFieldNameImpl(FIELD_NAME)(137,142) + PsiElement(NAME_ELEMENT)('field')(137,142) + PsiElement(CRLF)('\n')(142,143) + AtEntryImpl(ENTRY)(143,172) + AtKeywordImpl(KEYWORD)(143,152) + PsiElement(KEYWORD_ELEMENT)('private+f')(143,152) + PsiWhiteSpace(' ')(152,153) + AtClassNameImpl(CLASS_NAME)(153,166) + PsiElement(CLASS_NAME_ELEMENT)('package.class')(153,166) + PsiWhiteSpace(' ')(166,167) + AtFieldNameImpl(FIELD_NAME)(167,172) + PsiElement(NAME_ELEMENT)('field')(167,172) + PsiElement(CRLF)('\n')(172,173) + AtEntryImpl(ENTRY)(173,202) + AtKeywordImpl(KEYWORD)(173,182) + PsiElement(KEYWORD_ELEMENT)('protected')(173,182) + PsiWhiteSpace(' ')(182,183) + AtClassNameImpl(CLASS_NAME)(183,196) + PsiElement(CLASS_NAME_ELEMENT)('package.class')(183,196) + PsiWhiteSpace(' ')(196,197) + AtFieldNameImpl(FIELD_NAME)(197,202) + PsiElement(NAME_ELEMENT)('field')(197,202) + PsiElement(CRLF)('\n')(202,203) + AtEntryImpl(ENTRY)(203,234) + AtKeywordImpl(KEYWORD)(203,214) + PsiElement(KEYWORD_ELEMENT)('protected-f')(203,214) + PsiWhiteSpace(' ')(214,215) + AtClassNameImpl(CLASS_NAME)(215,228) + PsiElement(CLASS_NAME_ELEMENT)('package.class')(215,228) + PsiWhiteSpace(' ')(228,229) + AtFieldNameImpl(FIELD_NAME)(229,234) + PsiElement(NAME_ELEMENT)('field')(229,234) + PsiElement(CRLF)('\n')(234,235) + AtEntryImpl(ENTRY)(235,266) + AtKeywordImpl(KEYWORD)(235,246) + PsiElement(KEYWORD_ELEMENT)('protected+f')(235,246) + PsiWhiteSpace(' ')(246,247) + AtClassNameImpl(CLASS_NAME)(247,260) + PsiElement(CLASS_NAME_ELEMENT)('package.class')(247,260) + PsiWhiteSpace(' ')(260,261) + AtFieldNameImpl(FIELD_NAME)(261,266) + PsiElement(NAME_ELEMENT)('field')(261,266) + PsiElement(CRLF)('\n')(266,267) + AtEntryImpl(ENTRY)(267,294) + AtKeywordImpl(KEYWORD)(267,274) + PsiElement(KEYWORD_ELEMENT)('default')(267,274) + PsiWhiteSpace(' ')(274,275) + AtClassNameImpl(CLASS_NAME)(275,288) + PsiElement(CLASS_NAME_ELEMENT)('package.class')(275,288) + PsiWhiteSpace(' ')(288,289) + AtFieldNameImpl(FIELD_NAME)(289,294) + PsiElement(NAME_ELEMENT)('field')(289,294) + PsiElement(CRLF)('\n')(294,295) + AtEntryImpl(ENTRY)(295,324) + AtKeywordImpl(KEYWORD)(295,304) + PsiElement(KEYWORD_ELEMENT)('default-f')(295,304) + PsiWhiteSpace(' ')(304,305) + AtClassNameImpl(CLASS_NAME)(305,318) + PsiElement(CLASS_NAME_ELEMENT)('package.class')(305,318) + PsiWhiteSpace(' ')(318,319) + AtFieldNameImpl(FIELD_NAME)(319,324) + PsiElement(NAME_ELEMENT)('field')(319,324) + PsiElement(CRLF)('\n')(324,325) + AtEntryImpl(ENTRY)(325,354) + AtKeywordImpl(KEYWORD)(325,334) + PsiElement(KEYWORD_ELEMENT)('default+f')(325,334) + PsiWhiteSpace(' ')(334,335) + AtClassNameImpl(CLASS_NAME)(335,348) + PsiElement(CLASS_NAME_ELEMENT)('package.class')(335,348) + PsiWhiteSpace(' ')(348,349) + AtFieldNameImpl(FIELD_NAME)(349,354) + PsiElement(NAME_ELEMENT)('field')(349,354) Index: src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/no_value_at.cfg =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/no_value_at.cfg (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/no_value_at.cfg (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,3 @@ +public-f net.minecraft.item.ItemStack +public net.minecraft.block.state.BlockStateContainer$StateImplementation +public net.minecraft.entity.ai.EntityAITasks$EntityAITaskEntry Index: src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/no_value_at.txt =================================================================== --- src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/no_value_at.txt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) +++ src/test/resources/com/demonwav/mcdev/platform/minecraft/at/parser/fixtures/no_value_at.txt (revision ac29973c3640d6f6b0ea57bdcc44e60e8f11d2dc) @@ -0,0 +1,21 @@ +Access transformers(0,173) + AtEntryImpl(ENTRY)(0,37) + AtKeywordImpl(KEYWORD)(0,8) + PsiElement(KEYWORD_ELEMENT)('public-f')(0,8) + PsiWhiteSpace(' ')(8,9) + AtClassNameImpl(CLASS_NAME)(9,37) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.item.ItemStack')(9,37) + PsiElement(CRLF)('\n')(37,38) + AtEntryImpl(ENTRY)(38,110) + AtKeywordImpl(KEYWORD)(38,44) + PsiElement(KEYWORD_ELEMENT)('public')(38,44) + PsiWhiteSpace(' ')(44,45) + AtClassNameImpl(CLASS_NAME)(45,110) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.block.state.BlockStateContainer$StateImplementation')(45,110) + PsiElement(CRLF)('\n')(110,111) + AtEntryImpl(ENTRY)(111,173) + AtKeywordImpl(KEYWORD)(111,117) + PsiElement(KEYWORD_ELEMENT)('public')(111,117) + PsiWhiteSpace(' ')(117,118) + AtClassNameImpl(CLASS_NAME)(118,173) + PsiElement(CLASS_NAME_ELEMENT)('net.minecraft.entity.ai.EntityAITasks$EntityAITaskEntry')(118,173)