/* * This file is a part of the SteamWar software. * * Copyright (C) 2026 SteamWar.de-Serverteam * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package de.steamwar; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; /** * Parses Fabric-compatible .accesswidener files. *

* Supported format: *

 *   accessWidener v2 named
 *
 *   # comments are supported
 *   accessible class  net/minecraft/Foo
 *   accessible method net/minecraft/Foo someMethod ()V
 *   accessible field  net/minecraft/Foo someField I
 *   mutable    field  net/minecraft/Foo someField I
 *   extendable class  net/minecraft/Foo
 *   extendable method net/minecraft/Foo someMethod ()V
 *
 *   # transitive variants (expose widening to dependents)
 *   transitive-accessible class net/minecraft/Foo
 * 
*/ public final class AccessWidenerParser { private AccessWidenerParser() { } public static List parse(InputStream in) throws IOException { List entries = new ArrayList<>(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) { String line; boolean headerSeen = false; while ((line = reader.readLine()) != null) { // Strip inline comments int commentIdx = line.indexOf('#'); if (commentIdx >= 0) line = line.substring(0, commentIdx); line = line.strip(); if (line.isEmpty()) continue; if (!headerSeen) { // First non-blank, non-comment line must be the header if (!line.startsWith("accessWidener")) { throw new IOException("Missing accessWidener header, got: " + line); } headerSeen = true; continue; } AccessWidenerEntry entry = parseLine(line); if (entry != null) entries.add(entry); } } return entries; } private static AccessWidenerEntry parseLine(String line) { String[] parts = line.split("\\s+"); if (parts.length < 3) return null; String directive = parts[0]; // accessible / mutable / extendable / transitive-* String memberType = parts[1]; // class / method / field String target = parts[2]; // internal class name return switch (memberType) { case "class" -> new AccessWidenerEntry(directive, "class", target, null, null); case "method", "field" -> { if (parts.length < 5) yield null; yield new AccessWidenerEntry(directive, memberType, target, parts[3], parts[4]); } default -> null; }; } }