Skip to content

Commit f24f5d0

Browse files
add generation param args to PrintStatsCommand, close #284
use translations in PrintStatsCommand logging
1 parent d375d15 commit f24f5d0

File tree

3 files changed

+112
-19
lines changed

3 files changed

+112
-19
lines changed

enigma-cli/src/main/java/org/quiltmc/enigma/command/Argument.java

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@
88
import java.nio.file.Path;
99
import java.nio.file.Paths;
1010
import java.util.Arrays;
11+
import java.util.Collection;
1112
import java.util.Map;
1213
import java.util.Optional;
1314
import java.util.function.Consumer;
1415
import java.util.function.Function;
1516
import java.util.function.Predicate;
1617
import java.util.regex.Pattern;
1718
import java.util.regex.PatternSyntaxException;
19+
import java.util.stream.Collector;
1820
import java.util.stream.Collectors;
1921

2022
/**
@@ -88,7 +90,7 @@ static Argument<String> ofLenientEnum(String name, Class<? extends Enum<?>> type
8890
* Assumes enum values have conventional {@code SCREAMING_SNAKE_CASE} names.
8991
*/
9092
static <E extends Enum<E>> Argument<E> ofEnum(String name, Class<E> type, String explanation) {
91-
return new Argument<>(name, alternativesOf(type), string -> Enum.valueOf(type, string.toUpperCase()), explanation);
93+
return new Argument<>(name, alternativesOf(type), string -> parseCaseInsensitiveEnum(type, string), explanation);
9294
}
9395

9496
static <E extends Enum<E>> Argument<E> ofStrictEnum(String name, Class<E> type, String explanation) {
@@ -111,10 +113,15 @@ static Argument<Pattern> ofPattern(String name, String explanation) {
111113
return new Argument<>(name, PATTERN_TYPE, Argument::parsePattern, explanation);
112114
}
113115

114-
private static String alternativesOf(Class<? extends Enum<?>> type) {
115-
return Arrays.stream(type.getEnumConstants())
116-
.map(Object::toString)
117-
.collect(Collectors.joining(ALTERNATIVES_DELIM));
116+
static <T, C extends Collection<T>> Argument<C> ofCollection(
117+
String name, String typeDescription, String explanation,
118+
Function<String, T> elementParser, Collector<T, ?, C> collector
119+
) {
120+
return new Argument<>(
121+
name, typeDescription,
122+
string -> parseCollection(string, ",", elementParser, collector),
123+
explanation
124+
);
118125
}
119126

120127
private final String name;
@@ -143,6 +150,21 @@ static Path parseFile(String path) {
143150
return verifyFile(parsePath(path)).orElse(null);
144151
}
145152

153+
static <T, C extends Collection<T>> C parseCollection(
154+
String input, String delimRegex, Function<String, T> elementParser, Collector<T, ?, C> collector
155+
) {
156+
return Arrays.stream(input.split(delimRegex))
157+
.map(string -> {
158+
final T element = elementParser.apply(string);
159+
if (element == null) {
160+
throw new IllegalArgumentException("Invalid element: " + string);
161+
} else {
162+
return element;
163+
}
164+
})
165+
.collect(collector);
166+
}
167+
146168
static Path parseFolder(String path) {
147169
return verifyFolder(parsePath(path)).orElse(null);
148170
}
@@ -205,6 +227,10 @@ static String parseString(String string) {
205227
return string.isEmpty() ? null : string;
206228
}
207229

230+
static <E extends Enum<E>> E parseCaseInsensitiveEnum(Class<E> type, String string) {
231+
return Enum.valueOf(type, string.toUpperCase());
232+
}
233+
208234
static Pattern parsePattern(String regex) {
209235
if (regex.isEmpty()) {
210236
return null;
@@ -256,6 +282,16 @@ static <T> Optional<T> peek(Optional<T> optional, Consumer<T> action) {
256282
return optional;
257283
}
258284

285+
static String alternativesOf(Class<? extends Enum<?>> type) {
286+
return alternativesOf(type, ALTERNATIVES_DELIM);
287+
}
288+
289+
static String alternativesOf(Class<? extends Enum<?>> type, String delim) {
290+
return Arrays.stream(type.getEnumConstants())
291+
.map(Object::toString)
292+
.collect(Collectors.joining(delim));
293+
}
294+
259295
public String getName() {
260296
return this.name;
261297
}

enigma-cli/src/main/java/org/quiltmc/enigma/command/PrintStatsCommand.java

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,61 @@
88
import org.quiltmc.enigma.api.stats.StatType;
99
import org.quiltmc.enigma.api.stats.StatsGenerator;
1010
import org.quiltmc.enigma.command.PrintStatsCommand.Required;
11+
import org.quiltmc.enigma.command.PrintStatsCommand.Optional;
12+
import org.quiltmc.enigma.util.I18n;
1113
import org.tinylog.Logger;
1214

1315
import javax.annotation.Nullable;
1416
import java.nio.file.Path;
17+
import java.util.EnumSet;
1518
import java.util.Set;
19+
import java.util.stream.Collectors;
1620

1721
import static org.quiltmc.enigma.command.CommonArguments.ENIGMA_PROFILE;
1822
import static org.quiltmc.enigma.command.CommonArguments.INPUT_JAR;
1923
import static org.quiltmc.enigma.command.CommonArguments.INPUT_MAPPINGS;
2024

21-
public final class PrintStatsCommand extends Command<Required, Path> {
25+
public final class PrintStatsCommand extends Command<Required, Optional> {
26+
private static final Argument<Set<StatType>> INCLUDED_TYPES = Argument.ofCollection(
27+
"included-types", Argument.alternativesOf(StatType.class, "&|"),
28+
"""
29+
The stat types to include.""",
30+
string -> Argument.parseCaseInsensitiveEnum(StatType.class, string),
31+
Collectors.toUnmodifiableSet()
32+
);
33+
34+
private static final Argument<Boolean> INCLUDE_SYNTHETIC = Argument.ofBool("include-synthetic",
35+
"""
36+
Whether to include synthetic entries."""
37+
);
38+
39+
private static final Argument<Boolean> COUNT_FALLBACK = Argument.ofBool("count-fallback",
40+
"""
41+
Whether to count fallback-proposed entries as mapped."""
42+
);
43+
2244
public static final PrintStatsCommand INSTANCE = new PrintStatsCommand();
2345

2446
private PrintStatsCommand() {
2547
super(
2648
ArgsParser.of(INPUT_JAR, INPUT_MAPPINGS, Required::new),
27-
ArgsParser.of(ENIGMA_PROFILE)
49+
ArgsParser.of(ENIGMA_PROFILE, INCLUDED_TYPES, INCLUDE_SYNTHETIC, COUNT_FALLBACK, Optional::new)
2850
);
2951
}
3052

3153
@Override
32-
void runImpl(Required required, Path enigmaProfile) throws Exception {
33-
run(required.inputJar, required.inputMappings, enigmaProfile, null);
54+
void runImpl(Required required, Optional optional) throws Exception {
55+
final Set<StatType> includedTypes = optional.includedTypes == null || optional.includedTypes.isEmpty()
56+
? EnumSet.allOf(StatType.class)
57+
: optional.includedTypes;
58+
59+
final GenerationParameters params = new GenerationParameters(
60+
includedTypes,
61+
Boolean.TRUE.equals(optional.includeSynthetic),
62+
Boolean.TRUE.equals(optional.countFallback)
63+
);
64+
65+
run(required.inputJar, required.inputMappings, optional.enigmaProfile, params, null);
3466
}
3567

3668
@Override
@@ -43,24 +75,44 @@ public String getDescription() {
4375
return "Generates and prints out the statistics of how well the provided mappings cover the provided JAR file.";
4476
}
4577

46-
public static void run(Path inJar, Path mappings, @Nullable Path profilePath, @Nullable Iterable<EnigmaPlugin> plugins) throws Exception {
78+
public static void run(
79+
Path inJar, Path mappings, @Nullable Path profilePath,
80+
@Nullable GenerationParameters params, @Nullable Iterable<EnigmaPlugin> plugins
81+
) throws Exception {
4782
EnigmaProfile profile = EnigmaProfile.read(profilePath);
4883
Enigma enigma = createEnigma(profile, plugins);
4984

50-
run(inJar, mappings, enigma);
85+
run(inJar, mappings, enigma, params);
5186
}
5287

53-
public static void run(Path inJar, Path mappings, Enigma enigma) throws Exception {
88+
public static void run(Path inJar, Path mappings, Enigma enigma, @Nullable GenerationParameters params) throws Exception {
5489
StatsGenerator generator = new StatsGenerator(openProject(inJar, mappings, enigma));
55-
ProjectStatsResult result = generator.generate(new ConsoleProgressListener(), new GenerationParameters(Set.of(StatType.values())));
5690

57-
Logger.info(String.format("Overall mapped: %.2f%% (%s / %s)", result.getPercentage(), result.getMapped(), result.getMappable()));
58-
Logger.info(String.format("Classes: %.2f%% (%s / %s)", result.getPercentage(StatType.CLASSES), result.getMapped(StatType.CLASSES), result.getMappable(StatType.CLASSES)));
59-
Logger.info(String.format("Fields: %.2f%% (%s / %s)", result.getPercentage(StatType.FIELDS), result.getMapped(StatType.FIELDS), result.getMappable(StatType.FIELDS)));
60-
Logger.info(String.format("Methods: %.2f%% (%s / %s)", result.getPercentage(StatType.METHODS), result.getMapped(StatType.METHODS), result.getMappable(StatType.METHODS)));
61-
Logger.info(String.format("Parameters: %.2f%% (%s / %s)", result.getPercentage(StatType.PARAMETERS), result.getMapped(StatType.PARAMETERS), result.getMappable(StatType.PARAMETERS)));
91+
if (params == null) {
92+
params = new GenerationParameters();
93+
}
94+
95+
ProjectStatsResult result = generator.generate(new ConsoleProgressListener(), params);
96+
97+
final Set<StatType> includedTypes = params.includedTypes();
98+
99+
if (includedTypes.size() > 1) {
100+
final String overall = I18n.translate("menu.file.stats.overall");
101+
logResult(overall, result.getPercentage(), result.getMapped(), result.getMappable());
102+
}
103+
104+
for (final StatType type : StatType.values()) {
105+
if (includedTypes.contains(type)) {
106+
logResult(type.getName(), result.getPercentage(type), result.getMapped(type), result.getMappable(type));
107+
}
108+
}
109+
}
110+
111+
private static void logResult(String label, double percentage, int mapped, int mappable) {
112+
Logger.info("%s: %.2f%% (%s / %s)".formatted(label, percentage, mapped, mappable));
62113
}
63114

64115
record Required(Path inputJar, Path inputMappings) { }
116+
record Optional(Path enigmaProfile, Set<StatType> includedTypes, Boolean includeSynthetic, Boolean countFallback) { }
65117
}
66118

enigma-cli/src/test/java/org/quiltmc/enigma/command/PrintStatsCommandTest.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
import org.junit.jupiter.api.Test;
44
import org.quiltmc.enigma.TestUtil;
5+
import org.quiltmc.enigma.api.stats.GenerationParameters;
6+
import org.quiltmc.enigma.api.stats.StatType;
57

68
import java.nio.file.Path;
9+
import java.util.Set;
710

811
import static org.quiltmc.enigma.TestUtil.getResource;
912

@@ -14,6 +17,8 @@ public class PrintStatsCommandTest {
1417
@Test
1518
public void test() throws Exception {
1619
// just here to manually verify output
17-
PrintStatsCommand.run(JAR, MAPPINGS, null, null);
20+
PrintStatsCommand.run(JAR, MAPPINGS, null, null, null);
21+
final var customParams = new GenerationParameters(Set.of(StatType.CLASSES), true, true);
22+
PrintStatsCommand.run(JAR, MAPPINGS, null, customParams, null);
1823
}
1924
}

0 commit comments

Comments
 (0)