diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 86aa22b4..fc9d4486 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -43,5 +43,6 @@ dependencies { implementation "org.gradlex:extra-java-module-info:${props.getProperty('extra_java_module_info_version')}" implementation "com.gradleup.shadow:shadow-gradle-plugin:${props.getProperty('shadow_version')}" implementation "me.modmuss50:mod-publish-plugin:${props.getProperty('mod_publish_plugin_version')}" + implementation "org.openrewrite:plugin:${props.getProperty('openrewrite_plugin_version')}" } diff --git a/buildSrc/src/main/groovy/matcher.openrewrite.base.gradle b/buildSrc/src/main/groovy/matcher.openrewrite.base.gradle new file mode 100644 index 00000000..01f47dd9 --- /dev/null +++ b/buildSrc/src/main/groovy/matcher.openrewrite.base.gradle @@ -0,0 +1,161 @@ +plugins { + id 'org.openrewrite.rewrite' +} + +rewrite { + failOnDryRunResults = true + + activeRecipe( + "org.openrewrite.java.RemoveObjectsIsNull", + "org.openrewrite.java.RemoveUnusedImports", + // "org.openrewrite.java.logging.PrintStackTraceToLogError", // Breaks Util#getStackTrace, see https://github.com/openrewrite/rewrite-logging-frameworks/issues/281 + "org.openrewrite.java.logging.SystemErrToLogging", + "org.openrewrite.java.logging.SystemOutToLogging", + "org.openrewrite.java.logging.slf4j.Slf4jBestPractices", + "org.openrewrite.staticanalysis.CompareEnumsWithEqualityOperator", + "org.openrewrite.staticanalysis.JavaApiBestPractices", + "org.openrewrite.staticanalysis.MissingOverrideAnnotation", + "org.openrewrite.staticanalysis.SimplifyConstantIfBranchExecution", + "org.openrewrite.staticanalysis.UseStandardCharset", + "org.openrewrite.java.recipes.BlankLinesAroundFieldsWithAnnotations", + "org.openrewrite.java.migrate.RemoveIllegalSemicolons", + "org.openrewrite.java.migrate.lang.IfElseIfConstructToSwitch", + "org.openrewrite.java.migrate.lang.StringRulesRecipes", + "org.openrewrite.java.migrate.lang.UseStringIsEmptyRecipe", + "org.openrewrite.java.migrate.util.JavaUtilAPIs", + "org.openrewrite.java.migrate.util.UseEnumSetOf", + "org.openrewrite.java.migrate.util.UseListOf", + "org.openrewrite.java.migrate.util.UseSetOf", + "org.openrewrite.java.format.NormalizeFormat", + "org.openrewrite.java.format.RemoveTrailingWhitespace", + "org.openrewrite.java.format.SingleLineComments", + // "org.openrewrite.java.format.Spaces", // Conflicts with Checkstyle config regarding { } vs {} + + // TODO: https://docs.openrewrite.org/recipes/java/recipes/recipenullabilitybestpractices + + /* + * org.openrewrite.staticanalysis.CommonStaticAnalysis (modified), based on commit 69d43a5: + * https://github.com/openrewrite/rewrite-static-analysis/blob/63586c0ffa2f8dd7150a6a1767b808532b2560a8/src/main/resources/META-INF/rewrite/common-static-analysis.yml + */ + "org.openrewrite.staticanalysis.AbstractClassPublicConstructor", + "org.openrewrite.staticanalysis.AtomicPrimitiveEqualsUsesGet", + "org.openrewrite.staticanalysis.BigDecimalDoubleConstructorRecipe", + "org.openrewrite.staticanalysis.BigDecimalRoundingConstantsToEnums", + "org.openrewrite.staticanalysis.BooleanChecksNotInverted", + "org.openrewrite.staticanalysis.CaseInsensitiveComparisonsDoNotChangeCase", + "org.openrewrite.staticanalysis.CatchClauseOnlyRethrows", + "org.openrewrite.staticanalysis.ChainStringBuilderAppendCalls", + "org.openrewrite.staticanalysis.CollectionToArrayShouldHaveProperType", + "org.openrewrite.staticanalysis.CovariantEquals", + "org.openrewrite.staticanalysis.DefaultComesLast", + "org.openrewrite.staticanalysis.EmptyBlock", + // "org.openrewrite.staticanalysis.EqualsAvoidsNull", + "org.openrewrite.staticanalysis.ExplicitInitialization", + "org.openrewrite.staticanalysis.ExternalizableHasNoArgsConstructor", + "org.openrewrite.staticanalysis.FinalizePrivateFields", + "org.openrewrite.staticanalysis.FinalClass", + "org.openrewrite.staticanalysis.FixStringFormatExpressions", + "org.openrewrite.staticanalysis.ForLoopIncrementInUpdate", + "org.openrewrite.staticanalysis.HideUtilityClassConstructor", + "org.openrewrite.staticanalysis.IndexOfChecksShouldUseAStartPosition", + "org.openrewrite.staticanalysis.IndexOfReplaceableByContains", + "org.openrewrite.staticanalysis.IndexOfShouldNotCompareGreaterThanZero", + "org.openrewrite.staticanalysis.InlineVariable", + "org.openrewrite.staticanalysis.IsEmptyCallOnCollections", + "org.openrewrite.staticanalysis.LambdaBlockToExpression", + "org.openrewrite.staticanalysis.LowercasePackage", + "org.openrewrite.staticanalysis.MethodNameCasing", + "org.openrewrite.staticanalysis.ModifierOrder", + // "org.openrewrite.staticanalysis.MultipleVariableDeclarations", + // "org.openrewrite.staticanalysis.NeedBraces", + "org.openrewrite.staticanalysis.NestedEnumsAreNotStatic", + "org.openrewrite.staticanalysis.NewStringBuilderBufferWithCharArgument", + "org.openrewrite.staticanalysis.NoDoubleBraceInitialization", + "org.openrewrite.staticanalysis.NoEmptyCollectionWithRawType", + "org.openrewrite.staticanalysis.NoEqualityInForCondition", + "org.openrewrite.staticanalysis.NoFinalizer", + "org.openrewrite.staticanalysis.NoPrimitiveWrappersForToStringOrCompareTo", + "org.openrewrite.staticanalysis.NoRedundantJumpStatements", + "org.openrewrite.staticanalysis.NoToStringOnStringType", + "org.openrewrite.staticanalysis.NoValueOfOnStringType", + "org.openrewrite.staticanalysis.ObjectFinalizeCallsSuper", + "org.openrewrite.staticanalysis.PreferSystemGetPropertyOverGetenv", + "org.openrewrite.staticanalysis.PrimitiveWrapperClassConstructorToValueOf", + "org.openrewrite.staticanalysis.RedundantFileCreation", + "org.openrewrite.staticanalysis.RemoveExtraSemicolons", + "org.openrewrite.staticanalysis.RemoveRedundantNullCheckBeforeInstanceof", + "org.openrewrite.staticanalysis.RemoveRedundantNullCheckBeforeLiteralEquals", + "org.openrewrite.staticanalysis.RemoveRedundantTypeCast", + // "org.openrewrite.staticanalysis.RemoveUnusedLocalVariables", + // "org.openrewrite.staticanalysis.RemoveUnusedPrivateMethods", + // "org.openrewrite.staticanalysis.RenameLocalVariablesToCamelCase", + "org.openrewrite.staticanalysis.RenameMethodsNamedHashcodeEqualOrToString", + // "org.openrewrite.staticanalysis.RenamePrivateFieldsToCamelCase", // Always generates empty diff for UidSetupPane.java + "org.openrewrite.staticanalysis.ReplaceClassIsInstanceWithInstanceof", + "org.openrewrite.staticanalysis.ReplaceLambdaWithMethodReference", + "org.openrewrite.staticanalysis.ReplaceStringBuilderWithString", + "org.openrewrite.staticanalysis.ReplaceStringConcatenationWithStringValueOf", + "org.openrewrite.staticanalysis.SimplifyArraysAsList", + "org.openrewrite.staticanalysis.SimplifyBooleanExpression", + // "org.openrewrite.staticanalysis.SimplifyBooleanReturn", + "org.openrewrite.staticanalysis.SimplifyTernaryRecipes", + "org.openrewrite.staticanalysis.StaticMethodNotFinal", + "org.openrewrite.staticanalysis.StringLiteralEquality", + "org.openrewrite.staticanalysis.UnnecessaryCloseInTryWithResources", + "org.openrewrite.staticanalysis.UnnecessaryExplicitTypeArguments", + "org.openrewrite.staticanalysis.UnnecessaryParentheses", + "org.openrewrite.staticanalysis.UnnecessaryPrimitiveAnnotations", + "org.openrewrite.staticanalysis.UnnecessaryReturnAsLastStatement", + // "org.openrewrite.staticanalysis.UnwrapElseAfterReturn", + "org.openrewrite.staticanalysis.UpperCaseLiteralSuffixes", + "org.openrewrite.staticanalysis.UnnecessaryThrows", + "org.openrewrite.staticanalysis.UseCollectionInterfaces", + "org.openrewrite.staticanalysis.UseDiamondOperator", + "org.openrewrite.staticanalysis.UseJavaStyleArrayDeclarations", + "org.openrewrite.staticanalysis.UsePortableNewlines", + "org.openrewrite.staticanalysis.UseLambdaForFunctionalInterface", + "org.openrewrite.staticanalysis.UseStringReplace", + "org.openrewrite.staticanalysis.WhileInsteadOfFor", + "org.openrewrite.staticanalysis.WriteOctalValuesAsDecimal", + + /* + * org.openrewrite.staticanalysis.CodeCleanup (modified), based on commit a32c4e3: + * https://github.com/openrewrite/rewrite-static-analysis/blob/63586c0ffa2f8dd7150a6a1767b808532b2560a8/src/main/resources/META-INF/rewrite/static-analysis.yml + */ + "org.openrewrite.staticanalysis.DefaultComesLast", + "org.openrewrite.staticanalysis.EmptyBlock", + "org.openrewrite.java.format.EmptyNewlineAtEndOfFile", + "org.openrewrite.staticanalysis.ForLoopControlVariablePostfixOperators", + "org.openrewrite.staticanalysis.FinalizePrivateFields", + "org.openrewrite.java.format.MethodParamPad", + "org.openrewrite.java.format.NoWhitespaceAfter", + "org.openrewrite.java.format.NoWhitespaceBefore", + "org.openrewrite.java.format.PadEmptyForLoopComponents", + "org.openrewrite.staticanalysis.TypecastParenPad", + // "org.openrewrite.staticanalysis.EqualsAvoidsNull", + "org.openrewrite.staticanalysis.ExplicitInitialization", + // "org.openrewrite.staticanalysis.FallThrough", + "org.openrewrite.staticanalysis.HideUtilityClassConstructor", + // "org.openrewrite.staticanalysis.NeedBraces", + "org.openrewrite.staticanalysis.OperatorWrap", + "org.openrewrite.staticanalysis.UnnecessaryParentheses", + "org.openrewrite.staticanalysis.ReplaceThreadRunWithThreadStart", + "org.openrewrite.staticanalysis.ChainStringBuilderAppendCalls", + "org.openrewrite.staticanalysis.ReplaceStringBuilderWithString", + "org.openrewrite.java.ShortenFullyQualifiedTypeReferences", + "org.openrewrite.java.SimplifySingleElementAnnotation", + // "org.openrewrite.java.OrderImports", + ) +} + +dependencies { + rewrite(platform("org.openrewrite.recipe:rewrite-recipe-bom:3.25.0")) + rewrite("org.openrewrite.recipe:rewrite-migrate-java") + rewrite("org.openrewrite.recipe:rewrite-static-analysis") + rewrite("org.openrewrite.recipe:rewrite-logging-frameworks") + rewrite("org.openrewrite.recipe:rewrite-rewrite") +} + +tasks.named("check").configure { + dependsOn(tasks.named("rewriteDryRun")) +} diff --git a/buildSrc/src/main/groovy/matcher.openrewrite.java11.gradle b/buildSrc/src/main/groovy/matcher.openrewrite.java11.gradle new file mode 100644 index 00000000..c04c22f5 --- /dev/null +++ b/buildSrc/src/main/groovy/matcher.openrewrite.java11.gradle @@ -0,0 +1,8 @@ +plugins { + id 'org.openrewrite.rewrite' + id 'matcher.openrewrite.base' +} + +rewrite { + activeRecipe("org.openrewrite.java.migrate.Java8toJava11") +} diff --git a/buildSrc/src/main/groovy/matcher.openrewrite.java17.gradle b/buildSrc/src/main/groovy/matcher.openrewrite.java17.gradle new file mode 100644 index 00000000..e1c2d493 --- /dev/null +++ b/buildSrc/src/main/groovy/matcher.openrewrite.java17.gradle @@ -0,0 +1,8 @@ +plugins { + id 'org.openrewrite.rewrite' + id 'matcher.openrewrite.base' +} + +rewrite { + activeRecipe("org.openrewrite.java.migrate.UpgradeToJava17") +} diff --git a/gradle.properties b/gradle.properties index 5d6315ad..56a94a6d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,6 +8,7 @@ javafx_plugin_version = 0.1.0 extra_java_module_info_version = 1.9 shadow_version = 8.3.5 mod_publish_plugin_version = 0.8.4 +openrewrite_plugin_version = 7.27.0 # Project Properties version = 0.1.0 diff --git a/matcher-cli/build.gradle b/matcher-cli/build.gradle index 1910a1dd..45cd7501 100644 --- a/matcher-cli/build.gradle +++ b/matcher-cli/build.gradle @@ -2,6 +2,7 @@ plugins { id 'matcher.common' id 'matcher.publishing.maven' id 'matcher.publishing.github.no-natives' + id 'matcher.openrewrite.java17' id 'org.gradlex.extra-java-module-info' id 'application' } diff --git a/matcher-cli/src/main/java/matcher/cli/MatcherCli.java b/matcher-cli/src/main/java/matcher/cli/MatcherCli.java index 7fc4331b..a0591f8d 100644 --- a/matcher-cli/src/main/java/matcher/cli/MatcherCli.java +++ b/matcher-cli/src/main/java/matcher/cli/MatcherCli.java @@ -4,8 +4,6 @@ import java.util.List; import com.beust.jcommander.JCommander; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import matcher.cli.provider.CliCommandProvider; import matcher.cli.provider.CliParameterProvider; @@ -60,7 +58,6 @@ public void processArgs(String[] args) { } } - public static final Logger LOGGER = LoggerFactory.getLogger("Matcher CLI"); private final List paramProviders = new ArrayList<>(5); private final List commandProviders = new ArrayList<>(5); private final boolean acceptUnknownParams; diff --git a/matcher-cli/src/main/java/matcher/cli/provider/builtin/AutomatchCliCommandProvider.java b/matcher-cli/src/main/java/matcher/cli/provider/builtin/AutomatchCliCommandProvider.java index 9fabf966..abf6c826 100644 --- a/matcher-cli/src/main/java/matcher/cli/provider/builtin/AutomatchCliCommandProvider.java +++ b/matcher-cli/src/main/java/matcher/cli/provider/builtin/AutomatchCliCommandProvider.java @@ -1,6 +1,7 @@ package matcher.cli.provider.builtin; import java.io.IOException; +import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -9,10 +10,11 @@ import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import net.fabricmc.mappingio.MappingReader; -import matcher.cli.MatcherCli; import matcher.cli.provider.CliCommandProvider; import matcher.core.Matcher; import matcher.core.serdes.MatchesIo; @@ -26,8 +28,8 @@ * Provides the default {@code automatch} command. */ public class AutomatchCliCommandProvider implements CliCommandProvider { - @Parameters(commandNames = {commandName}) - class AutomatchCommand { + @Parameters(commandNames = {COMMAND_NAME}) + static class AutomatchCommand { @Parameter(names = {BuiltinCliParameters.INPUTS_A}, required = true) List inputsA = Collections.emptyList(); @@ -76,7 +78,7 @@ class AutomatchCommand { @Override public String getCommandName() { - return commandName; + return COMMAND_NAME; } @Override @@ -104,7 +106,7 @@ public void processArgs() { .build(); Config.setProjectConfig(config); - matcher.init(config, (progress) -> { }); + matcher.init(config, progress -> { }); if (config.getMappingsPathA() != null) { Path mappingsPath = config.getMappingsPathA(); @@ -116,7 +118,7 @@ public void processArgs() { MappingField.PLAIN, MappingField.MAPPED, env.getEnvA(), true); } catch (IOException e) { - e.printStackTrace(); + throw new UncheckedIOException("Failed to load mappings for side A", e); } } @@ -130,24 +132,25 @@ public void processArgs() { MappingField.PLAIN, MappingField.MAPPED, env.getEnvB(), true); } catch (IOException e) { - e.printStackTrace(); + throw new UncheckedIOException("Failed to load mappings for side B", e); } } for (int i = 0; i < command.passes; i++) { - matcher.autoMatchAll((progress) -> { }); + matcher.autoMatchAll(progress -> { }); } try { Files.deleteIfExists(command.outputFile); MatchesIo.write(matcher, command.outputFile); - } catch (Throwable e) { + } catch (Exception e) { throw new RuntimeException(e); } - MatcherCli.LOGGER.info("Auto-matching done!"); + LOGGER.info("Auto-matching done!"); } - private static final String commandName = "automatch"; + private static final Logger LOGGER = LoggerFactory.getLogger(AutomatchCliCommandProvider.class); + private static final String COMMAND_NAME = "automatch"; private final AutomatchCommand command = new AutomatchCommand(); } diff --git a/matcher-cli/src/main/java/matcher/cli/provider/builtin/BuiltinCliParameters.java b/matcher-cli/src/main/java/matcher/cli/provider/builtin/BuiltinCliParameters.java index fa2087e1..37a6e8c6 100644 --- a/matcher-cli/src/main/java/matcher/cli/provider/builtin/BuiltinCliParameters.java +++ b/matcher-cli/src/main/java/matcher/cli/provider/builtin/BuiltinCliParameters.java @@ -3,7 +3,10 @@ /** * All CLI parameters the CLI module handles by default. */ -public class BuiltinCliParameters { +public final class BuiltinCliParameters { + private BuiltinCliParameters() { + } + public static final String ADDITIONAL_PLUGINS = "--additional-plugins"; public static final String INPUTS_A = "--inputs-a"; public static final String INPUTS_B = "--inputs-b"; diff --git a/matcher-cli/src/main/java/module-info.java b/matcher-cli/src/main/java/module-info.java index a3d7431c..12f79a7a 100644 --- a/matcher-cli/src/main/java/module-info.java +++ b/matcher-cli/src/main/java/module-info.java @@ -1,3 +1,4 @@ +@SuppressWarnings("requires-transitive-automatic") module matcher.cli { requires transitive jcommander; requires transitive matcher.core; diff --git a/matcher-core/build.gradle b/matcher-core/build.gradle index 678f43e1..a6e9b924 100644 --- a/matcher-core/build.gradle +++ b/matcher-core/build.gradle @@ -1,6 +1,7 @@ plugins { id 'matcher.common' id 'matcher.publishing.maven' + id 'matcher.openrewrite.java11' } base { diff --git a/matcher-core/src/main/java/matcher/core/Matcher.java b/matcher-core/src/main/java/matcher/core/Matcher.java index f6457904..c66d878a 100644 --- a/matcher-core/src/main/java/matcher/core/Matcher.java +++ b/matcher-core/src/main/java/matcher/core/Matcher.java @@ -127,7 +127,11 @@ public void match(ClassInstance a, ClassInstance b) { if (a.getArrayDimensions() != b.getArrayDimensions()) throw new IllegalArgumentException("the classes don't have the same amount of array dimensions"); if (a.getMatch() == b) return; - LOGGER.debug("Matching class {} -> {}{}", a, b, (a.hasMappedName() ? " ("+a.getName(NameType.MAPPED_PLAIN)+")" : "")); + LOGGER.atDebug() + .addArgument(a) + .addArgument(b) + .addArgument(() -> (a.hasMappedName() ? " (" + a.getName(NameType.MAPPED_PLAIN) + ")" : "")) + .log("Matching class {} -> {}{}"); if (a.getMatch() != null) { a.getMatch().setMatch(null); @@ -254,7 +258,11 @@ public void match(MethodInstance a, MethodInstance b) { if (a.getCls().getMatch() != b.getCls()) throw new IllegalArgumentException("the methods don't belong to the same class"); if (a.getMatch() == b) return; - LOGGER.debug("Matching method {} -> {}{}", a, b, (a.hasMappedName() ? " ("+a.getName(NameType.MAPPED_PLAIN)+")" : "")); + LOGGER.atDebug() + .addArgument(a) + .addArgument(b) + .addArgument(() -> (a.hasMappedName() ? " (" + a.getName(NameType.MAPPED_PLAIN) + ")" : "")) + .log("Matching method {} -> {}{}"); Set membersA = a.getAllHierarchyMembers(); Set membersB = b.getAllHierarchyMembers(); @@ -323,7 +331,11 @@ public void match(FieldInstance a, FieldInstance b) { if (a.getCls().getMatch() != b.getCls()) throw new IllegalArgumentException("the methods don't belong to the same class"); if (a.getMatch() == b) return; - LOGGER.debug("Matching field {} -> {}{}", a, b, (a.hasMappedName() ? " ("+a.getName(NameType.MAPPED_PLAIN)+")" : "")); + LOGGER.atDebug() + .addArgument(a) + .addArgument(b) + .addArgument(() -> (a.hasMappedName() ? " (" + a.getName(NameType.MAPPED_PLAIN) + ")" : "")) + .log("Matching field {} -> {}{}"); if (a.getMatch() != null) a.getMatch().setMatch(null); if (b.getMatch() != null) b.getMatch().setMatch(null); @@ -341,7 +353,11 @@ public void match(MethodVarInstance a, MethodVarInstance b) { if (a.isArg() != b.isArg()) throw new IllegalArgumentException("the method vars are not of the same kind"); if (a.getMatch() == b) return; - LOGGER.debug("Matching method arg {} -> {}{}", a, b, (a.hasMappedName() ? " ("+a.getName(NameType.MAPPED_PLAIN)+")" : "")); + LOGGER.atDebug() + .addArgument(a) + .addArgument(b) + .addArgument(() -> (a.hasMappedName() ? " (" + a.getName(NameType.MAPPED_PLAIN) + ")" : "")) + .log("Matching method arg {} -> {}{}"); if (a.getMatch() != null) a.getMatch().setMatch(null); if (b.getMatch() != null) b.getMatch().setMatch(null); @@ -356,7 +372,11 @@ public void unmatch(ClassInstance cls) { if (cls == null) throw new NullPointerException("null class"); if (cls.getMatch() == null) return; - LOGGER.debug("Unmatching class {} (was {}){}", cls, cls.getMatch(), (cls.hasMappedName() ? " ("+cls.getName(NameType.MAPPED_PLAIN)+")" : "")); + LOGGER.atDebug() + .addArgument(cls) + .addArgument(cls.getMatch()) + .addArgument(() -> (cls.hasMappedName() ? " (" + cls.getName(NameType.MAPPED_PLAIN) + ")" : "")) + .log("Unmatching class {} (was {}){}"); cls.getMatch().setMatch(null); cls.setMatch(null); @@ -378,7 +398,11 @@ public void unmatch(MemberInstance m) { if (m == null) throw new NullPointerException("null member"); if (m.getMatch() == null) return; - LOGGER.debug("Unmatching member {} (was {}){}", m, m.getMatch(), (m.hasMappedName() ? " ("+m.getName(NameType.MAPPED_PLAIN)+")" : "")); + LOGGER.atDebug() + .addArgument(m) + .addArgument(m.getMatch()) + .addArgument(() -> (m.hasMappedName() ? " (" + m.getName(NameType.MAPPED_PLAIN) + ")" : "")) + .log("Unmatching member {} (was {}){}"); if (m instanceof MethodInstance) { for (MethodVarInstance arg : ((MethodInstance) m).getArgs()) { @@ -406,7 +430,11 @@ public void unmatch(MethodVarInstance a) { if (a == null) throw new NullPointerException("null method var"); if (a.getMatch() == null) return; - LOGGER.debug("Unmatching method var {} (was {}){}", a, a.getMatch(), (a.hasMappedName() ? " ("+a.getName(NameType.MAPPED_PLAIN)+")" : "")); + LOGGER.atDebug() + .addArgument(a) + .addArgument(a.getMatch()) + .addArgument(() -> (a.hasMappedName() ? " (" + a.getName(NameType.MAPPED_PLAIN) + ")" : "")) + .log("Unmatching method var {} (was {}){}"); a.getMatch().setMatch(null); a.setMatch(null); @@ -463,7 +491,7 @@ public boolean autoMatchClasses(ClassifierLevel level, double absThreshold, doub ClassInstance[] cmpClasses = env.getClassesB().stream() .filter(filter) - .collect(Collectors.toList()).toArray(new ClassInstance[0]); + .toArray(ClassInstance[]::new); double maxScore = ClassClassifier.getMaxScore(level); double maxMismatch = maxScore - ClassifierUtil.getRawScore(absThreshold * (1 - relThreshold), maxScore); @@ -485,7 +513,11 @@ public boolean autoMatchClasses(ClassifierLevel level, double absThreshold, doub match(entry.getKey(), entry.getValue()); } - LOGGER.info("Auto matched {} classes ({} unmatched, {} total)", matches.size(), (classes.size() - matches.size()), env.getClassesA().size()); + LOGGER.atInfo() + .addArgument(matches::size) + .addArgument(() -> (classes.size() - matches.size())) + .addArgument(() -> env.getClassesA().size()) + .log("Auto matched {} classes ({} unmatched, {} total)"); return !matches.isEmpty(); } @@ -497,7 +529,7 @@ public static void runInParallel(List workSet, Consumer worker, Dou int updateRate = Math.max(1, workSet.size() / 200); try { - List> futures = threadPool.invokeAll(workSet.stream().>map(workItem -> () -> { + List> futures = THREAD_POOL.invokeAll(workSet.stream().>map(workItem -> () -> { worker.accept(workItem); int cItemsDone = itemsDone.incrementAndGet(); @@ -524,14 +556,17 @@ public boolean autoMatchMethods(DoubleConsumer progressReceiver) { public boolean autoMatchMethods(ClassifierLevel level, double absThreshold, double relThreshold, DoubleConsumer progressReceiver) { AtomicInteger totalUnmatched = new AtomicInteger(); Map matches = match(level, absThreshold, relThreshold, - cls -> cls.getMethods(), MethodClassifier::rank, MethodClassifier.getMaxScore(level), + ClassInstance::getMethods, MethodClassifier::rank, MethodClassifier.getMaxScore(level), progressReceiver, totalUnmatched); for (Map.Entry entry : matches.entrySet()) { match(entry.getKey(), entry.getValue()); } - LOGGER.info("Auto matched {} methods ({} unmatched)", matches.size(), totalUnmatched.get()); + LOGGER.atInfo() + .addArgument(matches::size) + .addArgument(totalUnmatched::get) + .log("Auto matched {} methods ({} unmatched)"); return !matches.isEmpty(); } @@ -545,14 +580,17 @@ public boolean autoMatchFields(ClassifierLevel level, double absThreshold, doubl double maxScore = FieldClassifier.getMaxScore(level); Map matches = match(level, absThreshold, relThreshold, - cls -> cls.getFields(), FieldClassifier::rank, maxScore, + ClassInstance::getFields, FieldClassifier::rank, maxScore, progressReceiver, totalUnmatched); for (Map.Entry entry : matches.entrySet()) { match(entry.getKey(), entry.getValue()); } - LOGGER.info("Auto matched {} fields ({} unmatched)", matches.size(), totalUnmatched.get()); + LOGGER.atInfo() + .addArgument(matches::size) + .addArgument(totalUnmatched::get) + .log("Auto matched {} fields ({} unmatched)"); return !matches.isEmpty(); } @@ -620,7 +658,7 @@ private boolean autoMatchMethodVars(boolean isArg, Function methods = env.getClassesA().stream() .filter(cls -> cls.isReal() && cls.hasMatch() && cls.getMethods().length > 0) - .flatMap(cls -> Stream.of(cls.getMethods())) + .flatMap(cls -> Stream.of(cls.getMethods())) .filter(m -> m.hasMatch() && supplier.apply(m).length > 0) .filter(m -> { for (MethodVarInstance a : supplier.apply(m)) { @@ -667,7 +705,11 @@ private boolean autoMatchMethodVars(boolean isArg, Function (isArg ? "arg" : "var")) + .addArgument(totalUnmatched::get) + .log("Auto matched {} method {}s ({} unmatched)"); return !matches.isEmpty(); } @@ -771,8 +813,8 @@ public static class MatchingStatus { public final int matchedFieldCount; } - public static final ExecutorService threadPool = Executors.newWorkStealingPool(); - public static final Logger LOGGER = LoggerFactory.getLogger("Matcher"); + public static final ExecutorService THREAD_POOL = Executors.newWorkStealingPool(); + private static final Logger LOGGER = LoggerFactory.getLogger(Matcher.class); private final ClassEnvironment env; private final ClassifierLevel autoMatchLevel = ClassifierLevel.Extra; diff --git a/matcher-core/src/main/java/matcher/core/PluginLoader.java b/matcher-core/src/main/java/matcher/core/PluginLoader.java index 86b2edd8..5f6b00f9 100644 --- a/matcher-core/src/main/java/matcher/core/PluginLoader.java +++ b/matcher-core/src/main/java/matcher/core/PluginLoader.java @@ -7,7 +7,6 @@ import java.net.URLClassLoader; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -15,14 +14,14 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -public class PluginLoader { +public final class PluginLoader { public static void run(List extraPluginPaths) { List pluginPaths = new ArrayList<>(); - pluginPaths.add(Paths.get("plugins")); + pluginPaths.add(Path.of("plugins")); if (extraPluginPaths != null) { for (String path : extraPluginPaths) { - pluginPaths.add(Paths.get(path)); + pluginPaths.add(Path.of(path)); } } @@ -58,9 +57,12 @@ public static void run(List extraPluginPaths) { ServiceLoader pluginLoader = ServiceLoader.load(Plugin.class, cl); for (Plugin p : pluginLoader) { - p.init(apiVersion); + p.init(API_VERSION); } } - private static final int apiVersion = 0; + private PluginLoader() { + } + + private static final int API_VERSION = 0; } diff --git a/matcher-core/src/main/java/matcher/core/serdes/MatchesIo.java b/matcher-core/src/main/java/matcher/core/serdes/MatchesIo.java index 29f43bb1..4535a70c 100644 --- a/matcher-core/src/main/java/matcher/core/serdes/MatchesIo.java +++ b/matcher-core/src/main/java/matcher/core/serdes/MatchesIo.java @@ -11,10 +11,12 @@ import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Base64; -import java.util.Comparator; import java.util.List; import java.util.function.DoubleConsumer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import matcher.core.Matcher; import matcher.model.config.Config; import matcher.model.type.ClassEnvironment; @@ -27,7 +29,7 @@ import matcher.model.type.MethodInstance; import matcher.model.type.MethodVarInstance; -public class MatchesIo { +public final class MatchesIo { public static void read(Path path, List inputDirs, boolean verifyInputs, Matcher matcher, DoubleConsumer progressReceiver) { ClassEnvironment env = matcher.getEnv(); @@ -83,7 +85,7 @@ public static void read(Path path, List inputDirs, boolean verifyInputs, M final int indent = 2; int sizeEnd = line.indexOf('\t', indent); - long size = InputFile.unknownSize; + long size = InputFile.UNKNOWN_SIZE; byte[] hash = null; HashType hashType = null; String url = null; // TODO: save url? @@ -143,7 +145,7 @@ public static void read(Path path, List inputDirs, boolean verifyInputs, M } else if (line.startsWith("\tnon-obf mem b\t")) { nonObfuscatedMemberPatternB = line.substring("\tnon-obf mem b\t".length()); } else { - throw new IOException("invalid header: "+line); + throw new IOException("invalid header: " + line); } } } @@ -169,12 +171,12 @@ public static void read(Path path, List inputDirs, boolean verifyInputs, M ClassInstance target; if (currentClass == null) { - Matcher.LOGGER.warn("Unknown a class {}", idA); + LOGGER.warn("Unknown a class {}", idA); } else if ((target = env.getLocalClsByIdB(idB)) == null) { - Matcher.LOGGER.warn("Unknown b class {}", idA); + LOGGER.warn("Unknown b class {}", idA); currentClass = null; } else if (!currentClass.isMatchable() || !target.isMatchable()) { - Matcher.LOGGER.warn("Unmatchable a/b class {}/{}", idA, idB); + LOGGER.warn("Unmatchable a/b class {}/{}", idA, idB); currentClass = null; } else { currentClass.setMatchable(true); @@ -191,7 +193,7 @@ public static void read(Path path, List inputDirs, boolean verifyInputs, M currentMethod = null; if (cls == null) { - Matcher.LOGGER.warn("Unknown {} class {}", side, id); + LOGGER.warn("Unknown {} class {}", side, id); } else { if (cls.hasMatch()) matcher.unmatch(cls); cls.setMatchable(false); @@ -210,11 +212,11 @@ public static void read(Path path, List inputDirs, boolean verifyInputs, M MethodInstance b; if (a == null) { - Matcher.LOGGER.warn("Unknown a method {} in class {}", idA, currentClass); + LOGGER.warn("Unknown a method {} in class {}", idA, currentClass); } else if ((b = currentClass.getMatch().getMethod(idB)) == null) { - Matcher.LOGGER.warn("Unknown b method {} in class {}", idB, currentClass.getMatch()); + LOGGER.warn("Unknown b method {} in class {}", idB, currentClass.getMatch()); } else if (!a.isMatchable() || !b.isMatchable()) { - Matcher.LOGGER.warn("Unmatchable a/b method {}/{}", idA, idB); + LOGGER.warn("Unmatchable a/b method {}/{}", idA, idB); currentMethod = null; } else { a.setMatchable(true); @@ -226,11 +228,11 @@ public static void read(Path path, List inputDirs, boolean verifyInputs, M FieldInstance b; if (a == null) { - Matcher.LOGGER.warn("Unknown a field {} in class {}", idA, currentClass); + LOGGER.warn("Unknown a field {} in class {}", idA, currentClass); } else if ((b = currentClass.getMatch().getField(idB)) == null) { - Matcher.LOGGER.warn("Unknown b field {} in class {}", idB, currentClass.getMatch()); + LOGGER.warn("Unknown b field {} in class {}", idB, currentClass.getMatch()); } else if (!a.isMatchable() || !b.isMatchable()) { - Matcher.LOGGER.warn("Unmatchable a/b field {}/{}", idA, idB); + LOGGER.warn("Unmatchable a/b field {}/{}", idA, idB); } else { a.setMatchable(true); b.setMatchable(true); @@ -250,12 +252,12 @@ public static void read(Path path, List inputDirs, boolean verifyInputs, M MemberInstance member = line.charAt(1) == 'm' ? cls.getMethod(id) : cls.getField(id); if (member == null) { - Matcher.LOGGER.warn("Unknown member {} in class {}", id, cls); + LOGGER.warn("Unknown member {} in class {}", id, cls); } else { if (member.hasMatch()) matcher.unmatch(member); if (!member.setMatchable(false)) { - Matcher.LOGGER.warn("Can't mark {} as unmatchable, already matched?", member); + LOGGER.warn("Can't mark {} as unmatchable, already matched?", member); } } } else if (line.startsWith("\t\tma\t") || line.startsWith("\t\tmv\t")) { // method arg or method var @@ -282,11 +284,11 @@ public static void read(Path path, List inputDirs, boolean verifyInputs, M } if (idxA < 0 || idxA >= varsA.length) { - Matcher.LOGGER.warn("Unknown a method {} {} in method {}", type, idxA, currentMethod); + LOGGER.warn("Unknown a method {} {} in method {}", type, idxA, currentMethod); } else if (idxB < 0 || idxB >= varsB.length) { - Matcher.LOGGER.warn("Unknown b method {} {} in method {}", type, idxB, matchedMethod); + LOGGER.warn("Unknown b method {} {} in method {}", type, idxB, matchedMethod); } else if (!varsA[idxA].isMatchable() || !varsB[idxB].isMatchable()) { - Matcher.LOGGER.warn("Unmatchable a/b method {} {}/{} in method {}/{}", + LOGGER.warn("Unmatchable a/b method {} {}/{} in method {}/{}", type, idxA, idxB, currentMethod, matchedMethod); currentMethod = null; } else { @@ -317,8 +319,7 @@ public static void read(Path path, List inputDirs, boolean verifyInputs, M } if (idx < 0 || idx >= vars.length) { - Matcher.LOGGER.warn("Unknown a method {} {} in method {}", type, idx, method); - continue; + LOGGER.warn("Unknown a method {} {} in method {}", type, idx, method); } else { MethodVarInstance var = vars[idx]; @@ -356,15 +357,12 @@ public static boolean write(Matcher matcher, Path path) throws IOException { if (classes.isEmpty()) return false; - classes.sort(new Comparator() { - @Override - public int compare(ClassInstance a, ClassInstance b) { - if (a.getEnv() != b.getEnv()) { - return a.getEnv() == env.getEnvA() ? -1 : 1; - } - - return a.getId().compareTo(b.getId()); + classes.sort((a, b) -> { + if (a.getEnv() != b.getEnv()) { + return a.getEnv() == env.getEnvA() ? -1 : 1; } + + return a.getId().compareTo(b.getId()); }); try (Writer writer = Files.newBufferedWriter(path, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)) { @@ -555,7 +553,12 @@ private static void writeVar(MethodVarInstance var, char side, Writer out) throw out.write('\n'); } + private MatchesIo() { + } + private enum ParserState { - START, HEADER, FILES_A, FILES_B, CP_FILES, CP_FILES_A, CP_FILES_B, CONTENT; + START, HEADER, FILES_A, FILES_B, CP_FILES, CP_FILES_A, CP_FILES_B, CONTENT } + + private static final Logger LOGGER = LoggerFactory.getLogger(MatchesIo.class); } diff --git a/matcher-gui/build.gradle b/matcher-gui/build.gradle index 8358e5c2..73ed13d6 100644 --- a/matcher-gui/build.gradle +++ b/matcher-gui/build.gradle @@ -4,6 +4,7 @@ plugins { id 'matcher.common' id 'matcher.publishing.maven' id 'matcher.publishing.github.base' + id 'matcher.openrewrite.java17' id 'org.openjfx.javafxplugin' id 'org.gradlex.extra-java-module-info' id 'application' diff --git a/matcher-gui/src/main/java/matcher/gui/Main.java b/matcher-gui/src/main/java/matcher/gui/Main.java index 13079ba1..1b0fad5f 100644 --- a/matcher-gui/src/main/java/matcher/gui/Main.java +++ b/matcher-gui/src/main/java/matcher/gui/Main.java @@ -18,7 +18,7 @@ public static void main(String[] args) { case "--additional-plugins": extraPluginPaths = new ArrayList<>(); - while (i+1 < args.length && !args[i+1].startsWith("--")) { + while (i + 1 < args.length && !args[i + 1].startsWith("--")) { extraPluginPaths.add(args[++i]); } diff --git a/matcher-gui/src/main/java/matcher/gui/MatcherGui.java b/matcher-gui/src/main/java/matcher/gui/MatcherGui.java index 2439e3b2..8261ebff 100644 --- a/matcher-gui/src/main/java/matcher/gui/MatcherGui.java +++ b/matcher-gui/src/main/java/matcher/gui/MatcherGui.java @@ -2,6 +2,7 @@ import java.io.File; import java.io.IOException; +import java.io.UncheckedIOException; import java.net.URL; import java.nio.file.Path; import java.util.ArrayList; @@ -20,6 +21,7 @@ import javafx.application.Application; import javafx.application.Platform; import javafx.concurrent.Task; +import javafx.event.Event; import javafx.geometry.Insets; import javafx.scene.Node; import javafx.scene.Scene; @@ -41,6 +43,8 @@ import javafx.stage.Stage; import javafx.stage.StageStyle; import javafx.stage.Window; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import net.fabricmc.mappingio.MappingReader; @@ -102,7 +106,7 @@ public void start(Stage stage) { scene = new Scene(border, 1400, 800); Shortcuts.init(this); - for (Consumer l : loadListeners) { + for (Consumer l : LOAD_LISTENERS) { l.accept(this); } @@ -117,8 +121,8 @@ public void start(Stage stage) { } @Override - public void stop() throws Exception { - threadPool.shutdown(); + public void stop() { + THREAD_POOL.shutdown(); } private void handleStartupArgs(List args) { @@ -142,35 +146,35 @@ private void handleStartupArgs(List args) { // ProjectConfig args case "--inputs-a": - while (i+1 < args.size() && !args.get(i+1).startsWith("--")) { + while (i + 1 < args.size() && !args.get(i + 1).startsWith("--")) { inputsA.add(Path.of(args.get(++i))); validProjectConfigArgPresent = true; } break; case "--inputs-b": - while (i+1 < args.size() && !args.get(i+1).startsWith("--")) { + while (i + 1 < args.size() && !args.get(i + 1).startsWith("--")) { inputsB.add(Path.of(args.get(++i))); validProjectConfigArgPresent = true; } break; case "--classpath-a": - while (i+1 < args.size() && !args.get(i+1).startsWith("--")) { + while (i + 1 < args.size() && !args.get(i + 1).startsWith("--")) { classPathA.add(Path.of(args.get(++i))); validProjectConfigArgPresent = true; } break; case "--classpath-b": - while (i+1 < args.size() && !args.get(i+1).startsWith("--")) { + while (i + 1 < args.size() && !args.get(i + 1).startsWith("--")) { classPathB.add(Path.of(args.get(++i))); validProjectConfigArgPresent = true; } break; case "--shared-classpath": - while (i+1 < args.size() && !args.get(i+1).startsWith("--")) { + while (i + 1 < args.size() && !args.get(i + 1).startsWith("--")) { sharedClassPath.add(Path.of(args.get(++i))); validProjectConfigArgPresent = true; } @@ -241,7 +245,7 @@ public CompletableFuture newProject(ProjectConfig config, boolean showC if (showConfigDialog) { Dialog dialog = new Dialog<>(); - //dialog.initModality(Modality.APPLICATION_MODAL); + // dialog.initModality(Modality.APPLICATION_MODAL); dialog.setResizable(true); dialog.setTitle("Project configuration"); dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL); @@ -282,7 +286,7 @@ public CompletableFuture newProject(ProjectConfig config, boolean showC MappingField.PLAIN, MappingField.MAPPED, env.getEnvA(), true); } catch (IOException e) { - e.printStackTrace(); + throw new UncheckedIOException("Failed to load mappings for side A", e); } } @@ -296,14 +300,15 @@ public CompletableFuture newProject(ProjectConfig config, boolean showC MappingField.PLAIN, MappingField.MAPPED, env.getEnvB(), true); } catch (IOException e) { - e.printStackTrace(); + throw new UncheckedIOException("Failed to load mappings for side B", e); } } onProjectChange(); }, exc -> { - exc.printStackTrace(); + LOGGER.error("Failed to initialize project", exc); + showAlert(AlertType.ERROR, "Project initialization error", "An error occurred while initializing the project", exc.getMessage()); ret.completeExceptionally(exc); }); @@ -487,20 +492,20 @@ public void onMatchChange(Set types) { } public static CompletableFuture runAsyncTask(Callable task) { - Task jfxTask = new Task() { + Task jfxTask = new Task<>() { @Override protected T call() throws Exception { return task.call(); } }; - CompletableFuture ret = new CompletableFuture(); + CompletableFuture ret = new CompletableFuture<>(); jfxTask.setOnSucceeded(event -> ret.complete(jfxTask.getValue())); jfxTask.setOnFailed(event -> ret.completeExceptionally(jfxTask.getException())); jfxTask.setOnCancelled(event -> ret.cancel(false)); - threadPool.execute(jfxTask); + THREAD_POOL.execute(jfxTask); return ret; } @@ -512,15 +517,15 @@ public void runProgressTask(String labelText, Consumer task) { public void runProgressTask(String labelText, Consumer task, Runnable onSuccess, Consumer onError) { Stage stage = new Stage(StageStyle.UTILITY); stage.initOwner(this.scene.getWindow()); - VBox pane = new VBox(GuiConstants.padding); + VBox pane = new VBox(GuiConstants.PADDING); stage.setScene(new Scene(pane)); stage.initModality(Modality.APPLICATION_MODAL); - stage.setOnCloseRequest(event -> event.consume()); + stage.setOnCloseRequest(Event::consume); stage.setResizable(false); stage.setTitle("Operation progress"); - pane.setPadding(new Insets(GuiConstants.padding)); + pane.setPadding(new Insets(GuiConstants.PADDING)); pane.getChildren().add(new Label(labelText)); @@ -530,9 +535,9 @@ public void runProgressTask(String labelText, Consumer task, Run stage.show(); - Task jfxTask = new Task() { + Task jfxTask = new Task<>() { @Override - protected Void call() throws Exception { + protected Void call() { task.accept(cProgress -> Platform.runLater(() -> progress.setProgress(cProgress))); return null; @@ -549,7 +554,7 @@ protected Void call() throws Exception { if (onError != null) onError.accept(jfxTask.getException()); }); - threadPool.execute(jfxTask); + THREAD_POOL.execute(jfxTask); } public void showAlert(AlertType type, String title, String headerText, String text) { @@ -645,18 +650,19 @@ public static Path requestDir(String title, Window parent) { public static URL getThemeCss(Theme theme) { String path = "/ui/styles/" + theme.getId() + ".css"; URL ret = MatcherGui.class.getResource(path); - if (ret == null) throw new RuntimeException("can't find resource "+path); + if (ret == null) throw new RuntimeException("can't find resource " + path); return ret; } public enum SortKey { - Name, MappedName, MatchStatus, Similarity; + Name, MappedName, MatchStatus, Similarity } - public static final List> loadListeners = new ArrayList<>(); + public static final List> LOAD_LISTENERS = new ArrayList<>(); - private static final ExecutorService threadPool = Executors.newCachedThreadPool(); + private static final Logger LOGGER = LoggerFactory.getLogger(MatcherGui.class); + private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool(); private ClassEnvironment env; private Matcher matcher; diff --git a/matcher-gui/src/main/java/matcher/gui/srcprocess/Cfr.java b/matcher-gui/src/main/java/matcher/gui/srcprocess/Cfr.java index c23ee672..db625143 100644 --- a/matcher-gui/src/main/java/matcher/gui/srcprocess/Cfr.java +++ b/matcher-gui/src/main/java/matcher/gui/srcprocess/Cfr.java @@ -3,7 +3,6 @@ import java.io.IOException; import java.nio.file.NoSuchFileException; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -12,8 +11,9 @@ import org.benf.cfr.reader.api.ClassFileSource; import org.benf.cfr.reader.api.OutputSinkFactory; import org.benf.cfr.reader.bytecode.analysis.parse.utils.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import matcher.core.Matcher; import matcher.model.NameType; import matcher.model.type.ClassFeatureExtractor; import matcher.model.type.ClassInstance; @@ -32,25 +32,20 @@ public synchronized String decompile(ClassInstance cls, ClassFeatureExtractor en .withOutputSink(sink) .build(); - driver.analyse(Collections.singletonList(cls.getName(nameType).concat(fileSuffix))); + driver.analyse(List.of(cls.getName(nameType).concat(FILE_SUFFIX))); return sink.toString(); } - private static class Source implements ClassFileSource { - Source(ClassFeatureExtractor env, NameType nameType) { - this.env = env; - this.nameType = nameType; - } - + private record Source(ClassFeatureExtractor env, NameType nameType) implements ClassFileSource { @Override public void informAnalysisRelativePathDetail(String usePath, String classFilePath) { - //Matcher.LOGGER.debug("informAnalysisRelativePathDetail {} {}", usePath, classFilePath); + // LOGGER.debug("informAnalysisRelativePathDetail {} {}", usePath, classFilePath); } @Override public Collection addJar(String jarPath) { - Matcher.LOGGER.debug("addJar {}", jarPath); + LOGGER.debug("addJar {}", jarPath); throw new UnsupportedOperationException(); } @@ -62,21 +57,21 @@ public String getPossiblyRenamedPath(String path) { @Override public Pair getClassFileContent(String path) throws IOException { - if (!path.endsWith(fileSuffix)) { - Matcher.LOGGER.debug("getClassFileContent invalid path: {}", path); + if (!path.endsWith(FILE_SUFFIX)) { + LOGGER.debug("getClassFileContent invalid path: {}", path); throw new NoSuchFileException(path); } - String clsName = path.substring(0, path.length() - fileSuffix.length()); + String clsName = path.substring(0, path.length() - FILE_SUFFIX.length()); ClassInstance cls = env.getClsByName(clsName, nameType); if (cls == null) { - Matcher.LOGGER.debug("getClassFileContent missing cls: {}", clsName); + LOGGER.debug("getClassFileContent missing cls: {}", clsName); throw new NoSuchFileException(path); } if (cls.getAsmNodes() == null) { - Matcher.LOGGER.debug("getClassFileContent unknown cls: {}", clsName); + LOGGER.debug("getClassFileContent unknown cls: {}", clsName); throw new NoSuchFileException(path); } @@ -84,31 +79,28 @@ public Pair getClassFileContent(String path) throws IOException return Pair.make(data, path); } - - private final ClassFeatureExtractor env; - private final NameType nameType; } private static class Sink implements OutputSinkFactory { @Override public List getSupportedSinks(SinkType sinkType, Collection available) { - return Collections.singletonList(SinkClass.STRING); + return List.of(SinkClass.STRING); } @Override public OutputSinkFactory.Sink getSink(SinkType sinkType, SinkClass sinkClass) { switch (sinkType) { case EXCEPTION: - return str -> Matcher.LOGGER.error("CFR exception: {}", str); + return str -> LOGGER.error("CFR exception: {}", str); case JAVA: return sb::append; case PROGRESS: - return str -> Matcher.LOGGER.debug("CFR progress: {}", str); + return str -> LOGGER.debug("CFR progress: {}", str); case SUMMARY: - return str -> Matcher.LOGGER.debug("CFR summary: {}", str); + return str -> LOGGER.debug("CFR summary: {}", str); default: - Matcher.LOGGER.debug("Unknown CFR sink type: {}", sinkType); - return str -> Matcher.LOGGER.debug("{}", str); + LOGGER.debug("Unknown CFR sink type: {}", sinkType); + return str -> LOGGER.debug("{}", str); } } @@ -120,5 +112,6 @@ public String toString() { private final StringBuilder sb = new StringBuilder(); } - private static final String fileSuffix = ".class"; + private static final Logger LOGGER = LoggerFactory.getLogger(Cfr.class); + private static final String FILE_SUFFIX = ".class"; } diff --git a/matcher-gui/src/main/java/matcher/gui/srcprocess/HtmlPrinter.java b/matcher-gui/src/main/java/matcher/gui/srcprocess/HtmlPrinter.java index 1940350d..dd25c2c2 100644 --- a/matcher-gui/src/main/java/matcher/gui/srcprocess/HtmlPrinter.java +++ b/matcher-gui/src/main/java/matcher/gui/srcprocess/HtmlPrinter.java @@ -135,8 +135,8 @@ import matcher.model.type.FieldInstance; import matcher.model.type.MethodInstance; -public class HtmlPrinter extends DefaultPrettyPrinterVisitor { - public HtmlPrinter(TypeResolver typeResolver) { +class HtmlPrinter extends DefaultPrettyPrinterVisitor { + HtmlPrinter(TypeResolver typeResolver) { super(new DefaultPrinterConfiguration() .addOption(new DefaultConfigurationOption(ConfigOption.INDENTATION, new Indentation(IndentType.TABS, 1))) .addOption(new DefaultConfigurationOption(ConfigOption.END_OF_LINE_CHARACTER, "\n")) @@ -205,7 +205,7 @@ private static int getTypeIdx(BodyDeclaration decl) { return 4; } } else { - throw new RuntimeException("unknown body decl type: "+decl.getClass().getName()); + throw new RuntimeException("unknown body decl type: " + decl.getClass().getName()); } } @@ -551,7 +551,7 @@ public void visit(final FieldDeclaration n, final Void arg) { Optional maximumCommonType = n.getMaximumCommonType(); maximumCommonType.ifPresent(t -> t.accept(this, arg)); - if (!maximumCommonType.isPresent()) { + if (maximumCommonType.isEmpty()) { printer.print("???"); } } @@ -592,6 +592,7 @@ private boolean fieldStart(VariableDeclarator var) { } @Override + @SuppressWarnings("unchecked") public void visit(final VariableDeclarator n, final Void arg) { printOrphanCommentsBeforeThisChildNode(n); printComment(n.getComment(), arg); @@ -805,6 +806,7 @@ public void visit(final SuperExpr n, final Void arg) { } @Override + @SuppressWarnings("unchecked") public void visit(final MethodCallExpr n, final Void arg) { printOrphanCommentsBeforeThisChildNode(n); printComment(n.getComment(), arg); @@ -835,7 +837,7 @@ public void visit(final MethodCallExpr n, final Void arg) { } // check if the parent is a method call and thus we are in an argument list - columnAlignFirstMethodChain.set(!p.filter(MethodCallExpr.class::isInstance).isPresent()); + columnAlignFirstMethodChain.set(p.filter(MethodCallExpr.class::isInstance).isEmpty()); } } @@ -897,7 +899,7 @@ public void visit(final MethodCallExpr n, final Void arg) { scope = firstScopePart; lastScopePart = (NameExpr) scope.clone(); - lastScopePart.setName(oldName.substring(dotIndex, oldName.length())); + lastScopePart.setName(oldName.substring(dotIndex)); } } @@ -1142,7 +1144,7 @@ public void visit(final MethodDeclaration n, final Void arg) { } } - if (!n.getBody().isPresent()) { + if (n.getBody().isEmpty()) { printer.print(";"); } else { printer.print(" "); @@ -1167,7 +1169,7 @@ public void visit(final Parameter n, final Void arg) { printer.print("..."); } - if (!(n.getType().isUnknownType())) { + if (!n.getType().isUnknownType()) { printer.print(" "); } @@ -1253,7 +1255,7 @@ public void visit(final SwitchEntry n, final Void arg) { printOrphanCommentsBeforeThisChildNode(n); printComment(n.getComment(), arg); - final String separator = (n.getType() == SwitchEntry.Type.STATEMENT_GROUP) ? ":" : " ->"; // old/new switch + final String separator = n.getType() == SwitchEntry.Type.STATEMENT_GROUP ? ":" : " ->"; // old/new switch if (isNullOrEmpty(n.getLabels())) { printer.print("default" + separator); @@ -1442,7 +1444,7 @@ public void visit(final IfStmt n, final Void arg) { boolean thenBlock = n.getThenStmt() instanceof BlockStmt; while (thenBlock - && !n.getElseStmt().isPresent() + && n.getElseStmt().isEmpty() && ((BlockStmt) n.getThenStmt()).getStatements().size() == 1 && !(n.getParentNode().orElse(null) instanceof IfStmt)) { Statement stmt = ((BlockStmt) n.getThenStmt()).getStatements().get(0); @@ -1455,7 +1457,7 @@ public void visit(final IfStmt n, final Void arg) { Node prev = getPrev(n); if (thenBlock - && (canAddNewLine(n) || prev instanceof IfStmt && !((IfStmt) prev).hasThenBlock()) + && (canAddNewLine(n) || prev instanceof IfStmt prevIfStmt && !prevIfStmt.hasThenBlock()) && !(n.getParentNode().orElse(null) instanceof IfStmt)) { printer.println(); } @@ -1766,7 +1768,7 @@ public void visit(final MemberValuePair n, final Void arg) { printOrphanCommentsBeforeThisChildNode(n); printComment(n.getComment(), arg); - boolean annotation = (n.getParentNode().get() instanceof NormalAnnotationExpr); + boolean annotation = n.getParentNode().get() instanceof NormalAnnotationExpr; if (annotation) printer.print(""); n.getName().accept(this, arg); @@ -1778,7 +1780,7 @@ public void visit(final MemberValuePair n, final Void arg) { @Override public void visit(final LineComment n, final Void arg) { - if (!getOption(ConfigOption.PRINT_COMMENTS).isPresent()) { + if (getOption(ConfigOption.PRINT_COMMENTS).isEmpty()) { return; } @@ -1791,7 +1793,7 @@ public void visit(final LineComment n, final Void arg) { @Override public void visit(final BlockComment n, final Void arg) { - if (!getOption(ConfigOption.PRINT_COMMENTS).isPresent()) { + if (getOption(ConfigOption.PRINT_COMMENTS).isEmpty()) { return; } @@ -1889,7 +1891,7 @@ public void visit(ModuleOpensDirective n, Void arg) { } private void printOrphanCommentsBeforeThisChildNode(final Node node) { - if (!getOption(ConfigOption.PRINT_COMMENTS).isPresent()) return; + if (getOption(ConfigOption.PRINT_COMMENTS).isEmpty()) return; if (node instanceof Comment) return; Node parent = node.getParentNode().orElse(null); @@ -1898,7 +1900,7 @@ private void printOrphanCommentsBeforeThisChildNode(final Node node) { sortByBeginPosition(everything); int positionOfTheChild = -1; - for (int i = 0; i < everything.size(); ++i) { // indexOf is by equality, so this is used to index by identity + for (int i = 0; i < everything.size(); i++) { // indexOf is by equality, so this is used to index by identity if (everything.get(i) == node) { positionOfTheChild = i; break; @@ -1929,7 +1931,7 @@ private void printOrphanCommentsBeforeThisChildNode(final Node node) { } private void printOrphanCommentsEnding(final Node node) { - if (!getOption(ConfigOption.PRINT_COMMENTS).isPresent()) return; + if (getOption(ConfigOption.PRINT_COMMENTS).isEmpty()) return; List everything = new ArrayList<>(node.getChildNodes()); sortByBeginPosition(everything); @@ -1943,7 +1945,7 @@ private void printOrphanCommentsEnding(final Node node) { while (findingComments && commentsAtEnd < everything.size()) { Node last = everything.get(everything.size() - 1 - commentsAtEnd); - findingComments = (last instanceof Comment); + findingComments = last instanceof Comment; if (findingComments) { commentsAtEnd++; @@ -2006,7 +2008,7 @@ private static Node getNext(Node n) { return parent.getChildNodes().get(idx + 1); } - private static Pattern RTRIM = Pattern.compile("\\s+$"); + private static final Pattern RTRIM = Pattern.compile("\\s+$"); protected final TypeResolver typeResolver; protected boolean instantiationAhead; protected int recursionCounter; diff --git a/matcher-gui/src/main/java/matcher/gui/srcprocess/HtmlUtil.java b/matcher-gui/src/main/java/matcher/gui/srcprocess/HtmlUtil.java index 1832d340..e1f92fd1 100644 --- a/matcher-gui/src/main/java/matcher/gui/srcprocess/HtmlUtil.java +++ b/matcher-gui/src/main/java/matcher/gui/srcprocess/HtmlUtil.java @@ -5,7 +5,7 @@ import matcher.model.type.FieldInstance; import matcher.model.type.MethodInstance; -public class HtmlUtil { +public final class HtmlUtil { public static String getId(MethodInstance method) { return "method-".concat(escapeId(method.getId())); } @@ -58,7 +58,7 @@ public static String escape(String str, String... allowedTags) { if (ret == null) ret = new StringBuilder(max * 2); if (c == '<' && allowedTags != null) { - int pos = str.substring(i, str.length()).indexOf('>'); + int pos = str.substring(i).indexOf('>'); if (tagPattern.matcher(str.substring(i, i + pos + 1)).find()) { // Skip ahead to after the tag @@ -106,4 +106,7 @@ private static Pattern compileTagPattern(String... tags) { return Pattern.compile(builder.toString()); } + + private HtmlUtil() { + } } diff --git a/matcher-gui/src/main/java/matcher/gui/srcprocess/Procyon.java b/matcher-gui/src/main/java/matcher/gui/srcprocess/Procyon.java index 08ac0d82..db29c00a 100644 --- a/matcher-gui/src/main/java/matcher/gui/srcprocess/Procyon.java +++ b/matcher-gui/src/main/java/matcher/gui/srcprocess/Procyon.java @@ -9,8 +9,9 @@ import com.strobel.assembler.metadata.ITypeLoader; import com.strobel.decompiler.DecompilerSettings; import com.strobel.decompiler.PlainTextOutput; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import matcher.core.Matcher; import matcher.model.NameType; import matcher.model.type.ClassFeatureExtractor; import matcher.model.type.ClassInstance; @@ -44,7 +45,7 @@ public boolean tryLoadType(String internalName, Buffer buffer) { if (cls == null) { if (checkWarn(internalName)) { - Matcher.LOGGER.debug("Missing cls: {}", internalName); + LOGGER.debug("Missing cls: {}", internalName); } return false; @@ -52,7 +53,7 @@ public boolean tryLoadType(String internalName, Buffer buffer) { if (cls.getAsmNodes() == null) { if (checkWarn(internalName)) { - Matcher.LOGGER.debug("Unknown cls: {}", internalName); + LOGGER.debug("Unknown cls: {}", internalName); } return false; @@ -75,7 +76,8 @@ private boolean checkWarn(String name) { private final ClassFeatureExtractor env; private final NameType nameType; - private final Set warnedClasses = new HashSet<>(); } + + private static final Logger LOGGER = LoggerFactory.getLogger(Procyon.class); } diff --git a/matcher-gui/src/main/java/matcher/gui/srcprocess/SrcDecorator.java b/matcher-gui/src/main/java/matcher/gui/srcprocess/SrcDecorator.java index 83a3d261..a54fd389 100644 --- a/matcher-gui/src/main/java/matcher/gui/srcprocess/SrcDecorator.java +++ b/matcher-gui/src/main/java/matcher/gui/srcprocess/SrcDecorator.java @@ -1,6 +1,7 @@ package matcher.gui.srcprocess; import java.io.BufferedReader; +import java.io.Serial; import java.io.StringReader; import java.util.ArrayList; import java.util.List; @@ -28,15 +29,16 @@ import com.github.javaparser.ast.comments.Comment; import com.github.javaparser.ast.comments.JavadocComment; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import matcher.core.Matcher; import matcher.model.NameType; import matcher.model.type.ClassInstance; import matcher.model.type.FieldInstance; import matcher.model.type.MethodInstance; import matcher.model.type.MethodVarInstance; -public class SrcDecorator { +public final class SrcDecorator { public static String decorate(String src, ClassInstance cls, NameType nameType) { String name = cls.getName(nameType); @@ -47,7 +49,7 @@ public static String decorate(String src, ClassInstance cls, NameType nameType) List classNames = new ArrayList<>(); boolean firstDollar = true; - name = name.substring(nameStartPos, name.length()); + name = name.substring(nameStartPos); for (int i = 0; i < name.length(); i++) { char ch = name.charAt(i); @@ -62,7 +64,7 @@ public static String decorate(String src, ClassInstance cls, NameType nameType) } } - classNames.add(name.substring(0, name.length())); + classNames.add(name); for (int i = classNames.size() - 1; i >= 0; i--) { src = src.replace(classNames.get(i).replace('$', '.'), classNames.get(i)); @@ -96,7 +98,7 @@ public static String decorate(String src, ClassInstance cls, NameType nameType) TypeResolver resolver = new TypeResolver(); resolver.setup(cls, nameType, cu); - cu.accept(remapVisitor, resolver); + cu.accept(REMAP_VISITOR, resolver); HtmlPrinter printer = new HtmlPrinter(resolver); cu.accept(printer, null); @@ -106,12 +108,13 @@ public static String decorate(String src, ClassInstance cls, NameType nameType) public static class SrcParseException extends RuntimeException { SrcParseException(List problems, String source) { - super("Parsing failed: "+problems); + super("Parsing failed: " + problems); this.problems = problems.stream().map(Problem::toString).collect(Collectors.joining(System.lineSeparator())); this.source = source; } + @Serial private static final long serialVersionUID = 6164216517595646716L; public final String problems; @@ -123,7 +126,7 @@ private static String tryFixCodeFormat(String src, List problems) { // CFR will insert super statements in inner classes after any captured locals, which crashes JavaParser // We can move the super statements around so there's no crash, so long as we can find what to move where if (!problem.getMessage().startsWith("Parse error. Found \"super\"") - || !problem.getLocation().isPresent()) { + || problem.getLocation().isEmpty()) { return null; } @@ -132,7 +135,7 @@ private static String tryFixCodeFormat(String src, List problems) { while (start.getKind() != Kind.SUPER.getKind()) { // If we can't find the super token for whatever reason no fixing can be done - if (!start.getNextToken().isPresent()) { + if (start.getNextToken().isEmpty()) { return null; } @@ -143,7 +146,7 @@ private static String tryFixCodeFormat(String src, List problems) { do { // If we can't find the end of the super statement - if (!end.getNextToken().isPresent()) { + if (end.getNextToken().isEmpty()) { return null; } @@ -154,7 +157,7 @@ private static String tryFixCodeFormat(String src, List problems) { while (to.getKind() != Kind.LBRACE.getKind()) { // If we can't find the method header the statement is in - if (!to.getPreviousToken().isPresent()) { + if (to.getPreviousToken().isEmpty()) { return null; } @@ -162,9 +165,9 @@ private static String tryFixCodeFormat(String src, List problems) { } // Unpack the limits of each statement so it's clear what needs to move in the source - if (!to.getRange().isPresent() - || !start.getRange().isPresent() - || !end.getRange().isPresent()) { + if (to.getRange().isEmpty() + || start.getRange().isEmpty() + || end.getRange().isEmpty()) { return null; } @@ -175,10 +178,10 @@ private static String tryFixCodeFormat(String src, List problems) { } private static String moveStatement(String source, Range slice, Position to) { - Matcher.LOGGER.debug("Shifting " + slice + " to " + to); + LOGGER.debug("Shifting {} to {}", slice, to); - //Remember that lines are counted from 1 not 0, so the indexes have to be offset backwards - List lines = new BufferedReader(new StringReader(source)).lines().collect(Collectors.toList()); + // Remember that lines are counted from 1 not 0, so the indexes have to be offset backwards + List lines = new BufferedReader(new StringReader(source)).lines().toList(); String sliceLine; if (slice.begin.line != slice.end.line) { @@ -190,7 +193,7 @@ private static String moveStatement(String source, Range slice, Position to) { } String sliceEnd = lines.get(slice.end.line - 1); - sliceLine = insert.append(sliceEnd.substring(0, slice.end.column)).toString(); + sliceLine = insert.append(sliceEnd, 0, slice.end.column).toString(); } else { sliceLine = lines.get(slice.begin.line - 1).substring(slice.begin.column - 1, slice.end.column); } @@ -228,9 +231,9 @@ private static void handleComment(String comment, Node n) { n.setComment(c); } - c.setContent("\n * "+comment.replace("\n", "\n * ")+'\n'+c.getContent()); + c.setContent("\n * " + comment.replace("\n", "\n * ") + '\n' + c.getContent()); } else { - n.setComment(new JavadocComment("\n * "+comment.replace("\n", "\n * ")+"\n ")); + n.setComment(new JavadocComment("\n * " + comment.replace("\n", "\n * ") + "\n ")); } } @@ -267,7 +270,10 @@ private static void handleMethodComment(MethodInstance method, Node n, TypeResol handleComment(comment, n); } - private static final VoidVisitorAdapter remapVisitor = new VoidVisitorAdapter() { + private SrcDecorator() { + } + + private static final VoidVisitorAdapter REMAP_VISITOR = new VoidVisitorAdapter<>() { @Override public void visit(CompilationUnit n, TypeResolver resolver) { n.getTypes().forEach(p -> p.accept(this, resolver)); @@ -285,7 +291,7 @@ public void visit(EnumDeclaration n, TypeResolver resolver) { private void visitCls(TypeDeclaration n, TypeResolver resolver) { ClassInstance cls = resolver.getCls(n); - // Matcher.LOGGER.debug("cls {} = {} at {}", n.getName().getIdentifier(), cls, n.getRange()); + // LOGGER.debug("cls {} = {} at {}", n.getName().getIdentifier(), cls, n.getRange()); if (cls != null) { handleComment(cls.getMappedComment(), n); @@ -297,7 +303,7 @@ private void visitCls(TypeDeclaration n, TypeResolver resolver) { @Override public void visit(ConstructorDeclaration n, TypeResolver resolver) { MethodInstance m = resolver.getMethod(n); - // Matcher.LOGGER.debug("ctor {} = {} at {}", n.getName().getIdentifier(), m, n.getRange()); + // LOGGER.debug("ctor {} = {} at {}", n.getName().getIdentifier(), m, n.getRange()); if (m != null) { handleMethodComment(m, n, resolver); @@ -317,7 +323,7 @@ public void visit(ConstructorDeclaration n, TypeResolver resolver) { @Override public void visit(MethodDeclaration n, TypeResolver resolver) { MethodInstance m = resolver.getMethod(n); - // Matcher.LOGGER.debug("mth {}, = {} at {}", n.getName().getIdentifier(), m, n.getRange()); + // LOGGER.debug("mth {}, = {} at {}", n.getName().getIdentifier(), m, n.getRange()); if (m != null) { handleMethodComment(m, n, resolver); @@ -337,7 +343,7 @@ public void visit(FieldDeclaration n, TypeResolver resolver) { for (VariableDeclarator var : n.getVariables()) { FieldInstance f = resolver.getField(var); - // Matcher.LOGGER.debug("fld {} = {} at {}", v.getName().getIdentifier(), f, v.getRange()); + // LOGGER.debug("fld {} = {} at {}", v.getName().getIdentifier(), f, v.getRange()); if (f != null) { if (f.getMappedComment() != null) { @@ -357,4 +363,6 @@ public void visit(FieldDeclaration n, TypeResolver resolver) { n.getAnnotations().forEach(p -> p.accept(this, arg));*/ } }; + + private static final Logger LOGGER = LoggerFactory.getLogger(SrcDecorator.class); } diff --git a/matcher-gui/src/main/java/matcher/gui/srcprocess/TypeResolver.java b/matcher-gui/src/main/java/matcher/gui/srcprocess/TypeResolver.java index 095c0d74..f7ca3cec 100644 --- a/matcher-gui/src/main/java/matcher/gui/srcprocess/TypeResolver.java +++ b/matcher-gui/src/main/java/matcher/gui/srcprocess/TypeResolver.java @@ -86,9 +86,7 @@ public ClassInstance getCls(Node node) { } } while ((node = node.getParentNode().orElse(null)) != null); - ClassInstance cls = getClsByName(sb.toString()); - - return cls; + return getClsByName(sb.toString()); } public & NodeWithParameters> MethodInstance getMethod(T methodDecl) { @@ -108,8 +106,8 @@ public & NodeWithParameters> MethodInstance sb.append(')'); - if (methodDecl instanceof NodeWithType) { - sb.append(toDesc(((NodeWithType) methodDecl).getType(), rootCls)); + if (methodDecl instanceof NodeWithType methodDeclWithType) { + sb.append(toDesc(methodDeclWithType.getType(), rootCls)); } else { sb.append('V'); } @@ -141,34 +139,29 @@ public FieldInstance getField(EnumConstantDeclaration var) { if (cls == null) return null; String name = var.getName().getIdentifier(); - String desc = !cls.isPrimitive() ? "L"+cls.getName(nameType)+";" : cls.getId(); + String desc = cls.isPrimitive() ? cls.getId() : "L"+cls.getName(nameType)+";"; return cls.getField(name, desc, nameType); } private String toDesc(Type type, ClassInstance context) { - if (type instanceof PrimitiveType) { - PrimitiveType t = (PrimitiveType) type; - - switch (t.getType()) { - case BOOLEAN: return "Z"; - case BYTE: return "B"; - case CHAR: return "C"; - case DOUBLE: return "D"; - case FLOAT: return "F"; - case INT: return "I"; - case LONG: return "J"; - case SHORT: return "S"; - default: - throw new IllegalArgumentException("invalid primitive type class: "+t.getType().getClass().getName()); - } + if (type instanceof PrimitiveType t) { + return switch (t.getType()) { + case BOOLEAN -> "Z"; + case BYTE -> "B"; + case CHAR -> "C"; + case DOUBLE -> "D"; + case FLOAT -> "F"; + case INT -> "I"; + case LONG -> "J"; + case SHORT -> "S"; + }; } else if (type instanceof VoidType) { return "V"; - } else if (type instanceof ClassOrInterfaceType) { - ClassOrInterfaceType t = (ClassOrInterfaceType) type; + } else if (type instanceof ClassOrInterfaceType t) { String name; - if (!t.getScope().isPresent()) { + if (t.getScope().isEmpty()) { name = t.getNameAsString(); } else { List parts = new ArrayList<>(); @@ -201,9 +194,9 @@ private String toDesc(Type type, ClassInstance context) { int pkgEnd = name.lastIndexOf('/'); int nameEnd = name.length(); - for (;;) { + while (true) { if (pkgEnd == -1) { // non-fqn (fqn without package was already checked) - String cName = name.substring(pkgEnd + 1, nameEnd); + String cName = name.substring(0, nameEnd); String suffix = name.substring(nameEnd).replace('/', '$'); // plain import lookup @@ -233,8 +226,7 @@ private String toDesc(Type type, ClassInstance context) { } return ClassInstance.getId(name); - } else if (type instanceof ArrayType) { - ArrayType t = (ArrayType) type; + } else if (type instanceof ArrayType t) { Type componentType = t.getComponentType(); int dims = 1; @@ -243,13 +235,10 @@ private String toDesc(Type type, ClassInstance context) { dims++; } - StringBuilder ret = new StringBuilder(); - for (int i = 0; i < dims; i++) ret.append('['); - ret.append(toDesc(componentType, context)); - - return ret.toString(); + return "[".repeat(Math.max(0, dims)) + + toDesc(componentType, context); } else { - throw new IllegalArgumentException("invalid type class: "+type.getClass().getName()); + throw new IllegalArgumentException("invalid type class: " + type.getClass().getName()); } } diff --git a/matcher-gui/src/main/java/matcher/gui/srcprocess/Vineflower.java b/matcher-gui/src/main/java/matcher/gui/srcprocess/Vineflower.java index 6db2480c..994e622e 100644 --- a/matcher-gui/src/main/java/matcher/gui/srcprocess/Vineflower.java +++ b/matcher-gui/src/main/java/matcher/gui/srcprocess/Vineflower.java @@ -17,8 +17,9 @@ import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.jetbrains.java.decompiler.main.extern.IResultSaver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import matcher.core.Matcher; import matcher.model.NameType; import matcher.model.type.ClassFeatureExtractor; import matcher.model.type.ClassInstance; @@ -102,7 +103,7 @@ public InputStream getInputStream(String resource) throws IOException { byte[] bytecode; if ((bytecode = bytecodeByClsName.get(resource)) == null) { - throw new IOException("Requested class not in decompilation scope: "+resource); + throw new IOException("Requested class not in decompilation scope: " + resource); } return new ByteArrayInputStream(bytecode); @@ -126,7 +127,7 @@ public void begin() { } @Override public void acceptClass(String qualifiedName, String fileName, String content, int[] mapping) { - if (DEBUG) Matcher.LOGGER.debug("acceptClass({}, {}, {}, {})", qualifiedName, fileName, content, Arrays.toString(mapping)); + if (DEBUG) LOGGER.debug("acceptClass({}, {}, {}, {})", qualifiedName, fileName, content, Arrays.toString(mapping)); results.put(qualifiedName, content); } @@ -138,10 +139,11 @@ public void acceptDirectory(String directory) { } public void acceptOther(String path) { } @Override - public void close() throws IOException { } + public void close() { } - private Map results = new HashMap<>(); + private final Map results = new HashMap<>(); } + private static final Logger LOGGER = LoggerFactory.getLogger(Vineflower.class); private static final boolean DEBUG = false; } diff --git a/matcher-gui/src/main/java/matcher/gui/ui/BottomPane.java b/matcher-gui/src/main/java/matcher/gui/ui/BottomPane.java index 5d54472c..467cb15b 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/BottomPane.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/BottomPane.java @@ -20,6 +20,7 @@ import matcher.model.type.ClassInstance; import matcher.model.type.FieldInstance; import matcher.model.type.MatchType; +import matcher.model.type.MatchableKind; import matcher.model.type.MemberInstance; import matcher.model.type.MethodInstance; import matcher.model.type.MethodVarInstance; @@ -37,9 +38,9 @@ public BottomPane(MatcherGui gui, MatchPaneSrc srcPane, MatchPaneDst dstPane) { private void init() { setId("bottom-pane"); - setPadding(new Insets(GuiConstants.padding)); + setPadding(new Insets(GuiConstants.PADDING)); - HBox center = new HBox(GuiConstants.padding); + HBox center = new HBox(GuiConstants.PADDING); getChildren().add(center); StackPane.setAlignment(center, Pos.CENTER); center.setAlignment(Pos.CENTER); @@ -62,7 +63,7 @@ private void init() { center.getChildren().add(matchPerfectMembersButton); - HBox right = new HBox(GuiConstants.padding); + HBox right = new HBox(GuiConstants.PADDING); getChildren().add(right); StackPane.setAlignment(right, Pos.CENTER_RIGHT); right.setAlignment(Pos.CENTER_RIGHT); @@ -167,7 +168,7 @@ private void match() { if (memberB == null) memberB = dstPane.getSelectedField(); if (canMatchMembers(memberA, memberB)) { - if (memberA instanceof MethodInstance) { + if (memberA.getKind() == MatchableKind.METHOD) { gui.getMatcher().match((MethodInstance) memberA, (MethodInstance) memberB); gui.onMatchChange(EnumSet.of(MatchType.Method)); } else { @@ -345,7 +346,6 @@ private void toggleMatchable() { var.setMatchable(!var.isMatchable()); gui.onMatchChange(EnumSet.of(MatchType.MethodVar)); - return; } } diff --git a/matcher-gui/src/main/java/matcher/gui/ui/ContentPane.java b/matcher-gui/src/main/java/matcher/gui/ui/ContentPane.java index 9d291e9c..274e4935 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/ContentPane.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/ContentPane.java @@ -66,7 +66,7 @@ private void init(ISelectionProvider selectionProvider) { // hierarchy tab - if (showHierarchy) { + if (SHOW_HIERARCHY) { HierarchyTab hTab = new HierarchyTab(); components.add(hTab); getTabs().add(hTab); @@ -91,12 +91,12 @@ private void init(ISelectionProvider selectionProvider) { // add tab selection change listeners getSelectionModel().selectedItemProperty().addListener((ov, oldTab, newTab) -> { - if (oldTab instanceof IGuiComponent.Selectable) { - ((IGuiComponent.Selectable) oldTab).onSelectStateChange(false); + if (oldTab instanceof IGuiComponent.Selectable selectableOldTab) { + selectableOldTab.onSelectStateChange(false); } - if (newTab instanceof IGuiComponent.Selectable) { - ((IGuiComponent.Selectable) newTab).onSelectStateChange(true); + if (newTab instanceof IGuiComponent.Selectable selectableNewTab) { + selectableNewTab.onSelectStateChange(true); } }); } @@ -106,7 +106,7 @@ public Collection getComponents() { return components; } - private static final boolean showHierarchy = false; + private static final boolean SHOW_HIERARCHY = false; private final MatcherGui gui; private final boolean isSource; diff --git a/matcher-gui/src/main/java/matcher/gui/ui/GuiConstants.java b/matcher-gui/src/main/java/matcher/gui/ui/GuiConstants.java index bc4e9c07..6c86fa60 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/GuiConstants.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/GuiConstants.java @@ -1,5 +1,8 @@ package matcher.gui.ui; -public class GuiConstants { - public static final double padding = 5; +public final class GuiConstants { + private GuiConstants() { + } + + public static final double PADDING = 5; } diff --git a/matcher-gui/src/main/java/matcher/gui/ui/GuiUtil.java b/matcher-gui/src/main/java/matcher/gui/ui/GuiUtil.java index ee0f49af..9b1369f1 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/GuiUtil.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/GuiUtil.java @@ -57,4 +57,7 @@ public static void moveSelectionDown(ListView list) { } } } + + private GuiUtil() { + } } diff --git a/matcher-gui/src/main/java/matcher/gui/ui/IFwdGuiComponent.java b/matcher-gui/src/main/java/matcher/gui/ui/IFwdGuiComponent.java index fc7ff907..64462278 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/IFwdGuiComponent.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/IFwdGuiComponent.java @@ -72,6 +72,7 @@ default void onMethodVarSelect(MethodVarInstance arg) { } } + @Override default void onMatchListRefresh() { for (IGuiComponent c : getComponents()) { c.onMatchListRefresh(); diff --git a/matcher-gui/src/main/java/matcher/gui/ui/MatchPaneDst.java b/matcher-gui/src/main/java/matcher/gui/ui/MatchPaneDst.java index 5fffeef3..3c7891d9 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/MatchPaneDst.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/MatchPaneDst.java @@ -9,6 +9,7 @@ import java.util.Set; import java.util.concurrent.Callable; +import javafx.scene.control.Alert.AlertType; import javafx.scene.control.ListView; import javafx.scene.control.SplitPane; import javafx.scene.control.TextField; @@ -17,8 +18,9 @@ import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import matcher.core.Matcher; import matcher.gui.MatcherGui; import matcher.model.NameType; import matcher.model.classifier.ClassClassifier; @@ -108,7 +110,7 @@ private class DstListCell extends StyledListCell> item) { boolean full = item.getSubject() instanceof ClassInstance; - return String.format("%.3f %s", item.getScore(), item.getSubject().getDisplayName(gui.getNameType(), full)); + return "%.3f %s".formatted(item.getScore(), item.getSubject().getDisplayName(gui.getNameType(), full)); } } @@ -162,12 +164,12 @@ public ClassInstance getSelectedClass() { } private static ClassInstance getClass(Matchable m) { - if (m instanceof ClassInstance) { - return (ClassInstance) m; - } else if (m instanceof MemberInstance) { - return ((MemberInstance) m).getCls(); - } else if (m instanceof MethodVarInstance) { - return ((MethodVarInstance) m).getMethod().getCls(); + if (m instanceof ClassInstance cls) { + return cls; + } else if (m instanceof MemberInstance member) { + return member.getCls(); + } else if (m instanceof MethodVarInstance var) { + return var.getMethod().getCls(); } else { throw new IllegalStateException(); } @@ -184,10 +186,10 @@ public MemberInstance getSelectedMember() { private static MemberInstance getMember(Matchable m) { if (m instanceof ClassInstance) { return null; - } else if (m instanceof MemberInstance) { - return (MemberInstance) m; - } else if (m instanceof MethodVarInstance) { - return ((MethodVarInstance) m).getMethod(); + } else if (m instanceof MemberInstance member) { + return member; + } else if (m instanceof MethodVarInstance var) { + return var.getMethod(); } else { throw new IllegalStateException(); } @@ -204,10 +206,10 @@ public MethodInstance getSelectedMethod() { private static MethodInstance getMethod(Matchable m) { if (m instanceof ClassInstance || m instanceof FieldInstance) { return null; - } else if (m instanceof MethodInstance) { - return (MethodInstance) m; - } else if (m instanceof MethodVarInstance) { - return ((MethodVarInstance) m).getMethod(); + } else if (m instanceof MethodInstance mth) { + return mth; + } else if (m instanceof MethodVarInstance var) { + return var.getMethod(); } else { throw new IllegalStateException(); } @@ -224,8 +226,8 @@ public FieldInstance getSelectedField() { private static FieldInstance getField(Matchable m) { if (m instanceof ClassInstance || m instanceof MethodInstance || m instanceof MethodVarInstance) { return null; - } else if (m instanceof FieldInstance) { - return (FieldInstance) m; + } else if (m instanceof FieldInstance fld) { + return fld; } else { throw new IllegalStateException(); } @@ -242,8 +244,8 @@ public MethodVarInstance getSelectedMethodVar() { private static MethodVarInstance getMethodVar(Matchable m) { if (m instanceof ClassInstance || m instanceof MethodInstance || m instanceof FieldInstance) { return null; - } else if (m instanceof MethodVarInstance) { - return (MethodVarInstance) m; + } else if (m instanceof MethodVarInstance var) { + return var; } else { throw new IllegalStateException(); } @@ -254,18 +256,12 @@ public RankResult getSelectedRankResult(MatchType type) { RankResult> result = matchList.getSelectionModel().getSelectedItem(); if (result == null) return null; - switch (type) { - case Class: - return result.getSubject() instanceof ClassInstance ? result : null; - case Method: - return result.getSubject() instanceof MethodInstance ? result : null; - case Field: - return result.getSubject() instanceof FieldInstance ? result : null; - case MethodVar: - return result.getSubject() instanceof MethodVarInstance ? result : null; - } - - throw new IllegalArgumentException("invalid type: "+type); + return switch (type) { + case Class -> result.getSubject() instanceof ClassInstance ? result : null; + case Method -> result.getSubject() instanceof MethodInstance ? result : null; + case Field -> result.getSubject() instanceof FieldInstance ? result : null; + case MethodVar -> result.getSubject() instanceof MethodVarInstance ? result : null; + }; } @Override @@ -322,7 +318,7 @@ private static Comparator>> getNameComparator( } private static Comparator>> getScoreComparator() { - return Comparator.>>comparingDouble(r -> r.getScore()).reversed(); + return Comparator.>>comparingDouble(RankResult::getScore).reversed(); } private void updateResults(Matchable oldSelection, boolean simpleMode) { @@ -337,7 +333,7 @@ private void updateResults(Matchable oldSelection, boolean simpleMode) { for (RankResult> item : rankResults) { if (simpleMode) { Matchable matchable = item.getSubject(); - String matchableText = String.format("%.3f %s", item.getScore(), + String matchableText = "%.3f %s".formatted(item.getScore(), matchable.getDisplayName(gui.getNameType(), matchable instanceof ClassInstance).toLowerCase(Locale.ROOT)); if (matchableText.contains(filterStr.trim())) { @@ -424,7 +420,7 @@ private Boolean evalFilter(List stack, RankResult for (String part : parts) { String op = part.toLowerCase(Locale.ENGLISH); - //Matcher.LOGGER.debug("stack: {}, op: {}", stack, op); + // LOGGER.debug("stack: {}, op: {}", stack, op); byte opTypeA = OP_TYPE_NONE; byte opTypeB = OP_TYPE_NONE; @@ -491,7 +487,7 @@ private Boolean evalFilter(List stack, RankResult if (type == OP_TYPE_NONE) continue; if (stack.isEmpty()) { - Matcher.LOGGER.error("Stack underflow"); + LOGGER.error("Stack underflow"); return null; } @@ -506,7 +502,7 @@ private Boolean evalFilter(List stack, RankResult || type == OP_TYPE_COMPARABLE && operand instanceof Comparable; if (!valid) { - Matcher.LOGGER.debug("Invalid operand type"); + LOGGER.debug("Invalid operand type"); return null; } @@ -514,11 +510,11 @@ private Boolean evalFilter(List stack, RankResult operand = ((RankResult>) operand).getSubject(); } else if (type == OP_TYPE_CLASS && operand instanceof RankResult) { operand = getClass(((RankResult>) operand).getSubject()); - } else if (type == OP_TYPE_CLASS && operand instanceof String) { - ClassInstance cls = env.getClsByName((String) operand); + } else if (type == OP_TYPE_CLASS && operand instanceof String clsName) { + ClassInstance cls = env.getClsByName(clsName); if (cls == null) { - Matcher.LOGGER.debug("Unknown class {}", operand); + LOGGER.debug("Unknown class {}", clsName); return null; } else { operand = cls; @@ -532,7 +528,7 @@ private Boolean evalFilter(List stack, RankResult } } - //Matcher.LOGGER.debug("opA: {}, opB: {}", opA, opB); + // LOGGER.debug("opA: {}, opB: {}", opA, opB); switch (op) { case "a": @@ -581,7 +577,7 @@ private Boolean evalFilter(List stack, RankResult stack.add(Boolean.logicalOr((Boolean) opA, (Boolean) opB)); break; case "not": - stack.add(!((Boolean) opA)); + stack.add(!(Boolean) opA); break; case "startswith": stack.add(((String) opA).startsWith((String) opB)); @@ -611,16 +607,16 @@ private Boolean evalFilter(List stack, RankResult } } - //Matcher.LOGGER.debug("Res stack: {}", stack); + // LOGGER.debug("Res stack: {}", stack); if (stack.isEmpty() || stack.size() > 2) { - Matcher.LOGGER.info("No result found"); + LOGGER.info("No result found"); return null; } else if (stack.size() == 1) { if (stack.get(0) instanceof Boolean) { return (Boolean) stack.get(0); } else { - Matcher.LOGGER.error("Invalid result"); + LOGGER.error("Invalid result"); return null; } } else { // 2 elements on the stack, use equals @@ -633,24 +629,24 @@ private static boolean checkEquality(Object a, Object b, ClassEnv env) { if (a == null || b == null) return false; if (a.getClass() != b.getClass()) { - if (a instanceof RankResult) a = ((RankResult) a).getSubject(); - if (b instanceof RankResult) b = ((RankResult) b).getSubject(); + if (a instanceof RankResult rankResult) a = rankResult.getSubject(); + if (b instanceof RankResult rankResult) b = rankResult.getSubject(); } if (a.getClass() != b.getClass()) { if (a instanceof ClassInstance) { - if (b instanceof Matchable) { - b = getClass((Matchable) b); - } else if (b instanceof String) { - b = env.getClsByName((String) b); + if (b instanceof Matchable matchable) { + b = getClass(matchable); + } else if (b instanceof String clsName) { + b = env.getClsByName(clsName); } } if (b instanceof ClassInstance) { - if (a instanceof Matchable) { - a = getClass((Matchable) a); - } else if (a instanceof String) { - a = env.getClsByName((String) a); + if (a instanceof Matchable matchable) { + a = getClass(matchable); + } else if (a instanceof String clsName) { + a = env.getClsByName(clsName); } } } @@ -710,17 +706,13 @@ void onSelect(Set matchChangeTypes) { if (newSrcSelection == null) { // no class selected return; - } else if (newSrcSelection instanceof ClassInstance) { // unmatched class or no member/method var selected - ClassInstance cls = (ClassInstance) newSrcSelection; + } else if (newSrcSelection instanceof ClassInstance cls) { // unmatched class or no member/method var selected ranker = () -> ClassClassifier.rankParallel(cls, cmpClasses.toArray(new ClassInstance[0]), matchLevel, env, maxMismatch); - } else if (newSrcSelection instanceof MethodInstance) { // unmatched method or no method var selected - MethodInstance method = (MethodInstance) newSrcSelection; - ranker = () -> MethodClassifier.rank(method, method.getCls().getMatch().getMethods(), matchLevel, env, maxMismatch); - } else if (newSrcSelection instanceof FieldInstance) { // field - FieldInstance field = (FieldInstance) newSrcSelection; - ranker = () -> FieldClassifier.rank(field, field.getCls().getMatch().getFields(), matchLevel, env, maxMismatch); - } else if (newSrcSelection instanceof MethodVarInstance) { // method arg/var - MethodVarInstance var = (MethodVarInstance) newSrcSelection; + } else if (newSrcSelection instanceof MethodInstance mth) { // unmatched method or no method var selected + ranker = () -> MethodClassifier.rank(mth, mth.getCls().getMatch().getMethods(), matchLevel, env, maxMismatch); + } else if (newSrcSelection instanceof FieldInstance fld) { // field + ranker = () -> FieldClassifier.rank(fld, fld.getCls().getMatch().getFields(), matchLevel, env, maxMismatch); + } else if (newSrcSelection instanceof MethodVarInstance var) { // method arg/var MethodInstance cmpMethod = var.getMethod().getMatch(); MethodVarInstance[] cmp = var.isArg() ? cmpMethod.getArgs() : cmpMethod.getVars(); ranker = () -> MethodVarClassifier.rank(var, cmp, matchLevel, env, maxMismatch); @@ -733,7 +725,8 @@ void onSelect(Set matchChangeTypes) { // update matches list MatcherGui.runAsyncTask(ranker).whenComplete((res, exc) -> { if (exc != null) { - exc.printStackTrace(); + LOGGER.error("Error while ranking", exc); + gui.showAlert(AlertType.ERROR, "Ranking Error", "An error occurred while ranking matches", exc.getMessage()); } else if (taskId == cTaskId) { assert rankResults.isEmpty(); rankResults.addAll(res); @@ -773,6 +766,7 @@ private Matchable getMatchableSrcSelection() { private Matchable oldDstSelection; } + private static final Logger LOGGER = LoggerFactory.getLogger(MatchPaneDst.class); private final MatcherGui gui; private final MatchPaneSrc srcPane; private final Collection components = new ArrayList<>(); diff --git a/matcher-gui/src/main/java/matcher/gui/ui/MatchPaneSrc.java b/matcher-gui/src/main/java/matcher/gui/ui/MatchPaneSrc.java index f53d587d..86a5a75d 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/MatchPaneSrc.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/MatchPaneSrc.java @@ -21,14 +21,16 @@ import javafx.css.converter.ColorConverter; import javafx.geometry.Orientation; import javafx.scene.Node; +import javafx.scene.control.Alert.AlertType; import javafx.scene.control.Cell; import javafx.scene.control.ListView; import javafx.scene.control.SplitPane; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeView; import javafx.scene.paint.Color; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import matcher.core.Matcher; import matcher.gui.MatcherGui; import matcher.gui.MatcherGui.SortKey; import matcher.model.NameType; @@ -64,7 +66,7 @@ private void init() { // member list - memberList.setCellFactory(ignore -> new SrcListCell>()); + memberList.setCellFactory(ignore -> new SrcListCell<>()); memberList.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { if (suppressChangeEvents || oldValue == newValue) return; @@ -93,7 +95,7 @@ private void init() { // method var list - varList.setCellFactory(ignore -> new SrcListCell()); + varList.setCellFactory(ignore -> new SrcListCell<>()); varList.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { if (suppressChangeEvents || oldValue == newValue) return; @@ -124,7 +126,8 @@ private void retrieveCellTextColors() { try { css = parser.parse(MatcherGui.getThemeCss(Config.getTheme())); } catch (IOException e) { - Matcher.LOGGER.error("CSS parsing failed", e); + LOGGER.error("CSS parsing failed", e); + gui.showAlert(AlertType.ERROR, "Theme error", "Failed to load theme CSS", e.getMessage()); return; } @@ -151,11 +154,12 @@ private void retrieveCellTextColors() { .reduce((first, second) -> second); if (textColorDecl.isEmpty()) continue; + @SuppressWarnings("unchecked") Color color = ColorConverter.getInstance().convert(textColorDecl.get().getParsedValue(), null); if (lowSimilarityStylePresent) lowSimilarityCellTextColor = color; if (highSimilarityStylePresent) highSimilarityCellTextColor = color; - }; + } } private Node createClassList() { @@ -206,7 +210,7 @@ protected enum CellStyleClass { HIGH_MATCH_SIMILARITY("high-match-similarity-cell"); static { - cssNames = Arrays.stream(values()) + CSS_NAMES = Arrays.stream(values()) .map(e -> e.cssName) .collect(Collectors.toList()); } @@ -215,17 +219,17 @@ protected enum CellStyleClass { this.cssName = cssName; } + public static final List CSS_NAMES; public final String cssName; - public static final List cssNames; } private class SrcTreeCell extends StyledTreeCell { @Override protected String getText(Object item) { - if (item instanceof String) { - return (String) item; - } else if (item instanceof Matchable) { - return getCellText((Matchable) item, false); + if (item instanceof String string) { + return string; + } else if (item instanceof Matchable matchable) { + return getCellText(matchable, false); } else { return ""; } @@ -236,7 +240,7 @@ protected void setCustomStyle(StyledTreeCell cell) { if (cell.getItem() instanceof Matchable) { setCellStyle(cell, (Matchable) cell.getItem()); } else { - cell.getStyleClass().removeAll(CellStyleClass.cssNames); + cell.getStyleClass().removeAll(CellStyleClass.CSS_NAMES); } } } @@ -266,7 +270,7 @@ private void setCellStyle(Cell cell, Matchable item) { styleClass = CellStyleClass.HIGH_MATCH_SIMILARITY; } } else { - final float epsilon = 1e-5f; // float rounding error + final float epsilon = 1e-5F; // float rounding error float similarity = item.getSimilarity(); if (similarity < epsilon) { @@ -277,26 +281,26 @@ private void setCellStyle(Cell cell, Matchable item) { cell.setTextFill(null); if (lowSimilarityCellTextColor == null || highSimilarityCellTextColor == null) return; - similarity = Math.round((similarity / diffColorStepAlignment)) * diffColorStepAlignment; + similarity = Math.round(similarity / DIFF_COLOR_STEP_ALIGNMENT) * DIFF_COLOR_STEP_ALIGNMENT; int similarityAsInt = (int) (similarity * 100); Color textColor; switch (Config.getTheme().getDiffColorInterpolationMode()) { case RGB: - textColor = similarityToColorRgb.get(similarityAsInt); + textColor = SIMILARITY_TO_COLOR_RGB.get(similarityAsInt); if (textColor == null) { textColor = interpolateRgb(lowSimilarityCellTextColor, highSimilarityCellTextColor, similarity); - similarityToColorRgb.put(similarityAsInt, textColor); + SIMILARITY_TO_COLOR_RGB.put(similarityAsInt, textColor); } break; case HSB: - textColor = similarityToColorHsb.get(similarityAsInt); + textColor = SIMILARITY_TO_COLOR_HSB.get(similarityAsInt); if (textColor == null) { textColor = interpolateHsb(lowSimilarityCellTextColor, highSimilarityCellTextColor, similarity); - similarityToColorHsb.put(similarityAsInt, textColor); + SIMILARITY_TO_COLOR_HSB.put(similarityAsInt, textColor); } break; @@ -309,7 +313,7 @@ private void setCellStyle(Cell cell, Matchable item) { } } - cell.getStyleClass().removeAll(CellStyleClass.cssNames); + cell.getStyleClass().removeAll(CellStyleClass.CSS_NAMES); if (styleClass != null) cell.getStyleClass().add(styleClass.cssName); } @@ -439,14 +443,14 @@ public MemberInstance getSelectedMember() { public MethodInstance getSelectedMethod() { MemberInstance member = memberList.getSelectionModel().getSelectedItem(); - return member instanceof MethodInstance ? (MethodInstance) member : null; + return member instanceof MethodInstance method ? method : null; } @Override public FieldInstance getSelectedField() { MemberInstance member = memberList.getSelectionModel().getSelectedItem(); - return member instanceof FieldInstance ? (FieldInstance) member : null; + return member instanceof FieldInstance field ? field : null; } @Override @@ -491,8 +495,8 @@ public void onViewChange(ViewChangeCause cause) { case THEME_CHANGED: retrieveCellTextColors(); - similarityToColorRgb.clear(); - similarityToColorHsb.clear(); + SIMILARITY_TO_COLOR_RGB.clear(); + SIMILARITY_TO_COLOR_HSB.clear(); case DIFF_COLORS_TOGGLED: updateLists(true, true); break; @@ -629,50 +633,32 @@ private void refreshClassList() { @SuppressWarnings("unchecked") private Comparator getClassComparator() { - switch (gui.getSortKey()) { - case Name: - return Comparator.comparing(this::getName, clsNameComparator); - case MappedName: - return Comparator.comparing(this::getMappedName, clsNameComparator); - case MatchStatus: - return ((Comparator) matchStatusComparator).thenComparing(this::getName, clsNameComparator); - case Similarity: - return ((Comparator) similarityComparator).thenComparing(this::getName, clsNameComparator); - } - - throw new IllegalStateException("unhandled sort key: "+gui.getSortKey()); + return switch (gui.getSortKey()) { + case Name -> Comparator.comparing(this::getName, CLASS_NAME_COMPARATOR); + case MappedName -> Comparator.comparing(this::getMappedName, CLASS_NAME_COMPARATOR); + case MatchStatus -> ((Comparator) MATCH_STATUS_COMPARATOR).thenComparing(this::getName, CLASS_NAME_COMPARATOR); + case Similarity -> ((Comparator) SIMILARITY_COMPARATOR).thenComparing(this::getName, CLASS_NAME_COMPARATOR); + }; } @SuppressWarnings("unchecked") private Comparator> getMemberComparator() { - switch (gui.getSortKey()) { - case Name: - return memberTypeComparator.thenComparing(this::getName, clsNameComparator); - case MappedName: - return memberTypeComparator.thenComparing(this::getMappedName, clsNameComparator); - case MatchStatus: - return ((Comparator>) matchStatusComparator).thenComparing(memberTypeComparator).thenComparing(this::getName, clsNameComparator); - case Similarity: - return ((Comparator>) similarityComparator).thenComparing(memberTypeComparator).thenComparing(this::getName, clsNameComparator); - } - - throw new IllegalStateException("unhandled sort key: "+gui.getSortKey()); + return switch (gui.getSortKey()) { + case Name -> MEMBER_TYPE_COMPARATOR.thenComparing(this::getName, CLASS_NAME_COMPARATOR); + case MappedName -> MEMBER_TYPE_COMPARATOR.thenComparing(this::getMappedName, CLASS_NAME_COMPARATOR); + case MatchStatus -> ((Comparator>) MATCH_STATUS_COMPARATOR).thenComparing(MEMBER_TYPE_COMPARATOR).thenComparing(this::getName, CLASS_NAME_COMPARATOR); + case Similarity -> ((Comparator>) SIMILARITY_COMPARATOR).thenComparing(MEMBER_TYPE_COMPARATOR).thenComparing(this::getName, CLASS_NAME_COMPARATOR); + }; } @SuppressWarnings("unchecked") private Comparator getVarComparator() { - switch (gui.getSortKey()) { - case Name: - return varTypeComparator.thenComparing(this::getName, clsNameComparator); - case MappedName: - return varTypeComparator.thenComparing(this::getMappedName, clsNameComparator); - case MatchStatus: - return ((Comparator) matchStatusComparator).thenComparing(varTypeComparator).thenComparing(this::getName, clsNameComparator); - case Similarity: - return ((Comparator) similarityComparator).thenComparing(varTypeComparator).thenComparing(this::getName, clsNameComparator); - } - - throw new IllegalStateException("unhandled sort key: "+gui.getSortKey()); + return switch (gui.getSortKey()) { + case Name -> VAR_TYPE_COMPARATOR.thenComparing(this::getName, CLASS_NAME_COMPARATOR); + case MappedName -> VAR_TYPE_COMPARATOR.thenComparing(this::getMappedName, CLASS_NAME_COMPARATOR); + case MatchStatus -> ((Comparator) MATCH_STATUS_COMPARATOR).thenComparing(VAR_TYPE_COMPARATOR).thenComparing(this::getName, CLASS_NAME_COMPARATOR); + case Similarity -> ((Comparator) SIMILARITY_COMPARATOR).thenComparing(VAR_TYPE_COMPARATOR).thenComparing(this::getName, CLASS_NAME_COMPARATOR); + }; } private String getName(Matchable m) { @@ -727,7 +713,7 @@ public Collection getComponents() { return components; } - private static final Comparator> memberTypeComparator = (a, b) -> { + private static final Comparator> MEMBER_TYPE_COMPARATOR = (a, b) -> { boolean aIsMethod = a instanceof MethodInstance; boolean bIsMethod = b instanceof MethodInstance; @@ -738,7 +724,7 @@ public Collection getComponents() { } }; - private static final Comparator varTypeComparator = (a, b) -> { + private static final Comparator VAR_TYPE_COMPARATOR = (a, b) -> { if (a.isArg() == b.isArg()) { return 0; } else { @@ -746,7 +732,7 @@ public Collection getComponents() { } }; - private static final Comparator> matchStatusComparator = (a, b) -> { + private static final Comparator> MATCH_STATUS_COMPARATOR = (a, b) -> { // sort order: unmatched partially-matched fully-matched-shallow fully-matched-recursive unmatchable boolean aMatchable = a.hasPotentialMatch(); @@ -781,15 +767,13 @@ public Collection getComponents() { return 0; }; - private static final Comparator> similarityComparator = (a, b) -> { - return Float.compare(a.getSimilarity(), b.getSimilarity()); - }; - - private static final Comparator clsNameComparator = Util::compareNatural; - private static final int diffColorSteps = 20; - private static final float diffColorStepAlignment = 1f / diffColorSteps; - private static final Map similarityToColorRgb = new HashMap<>(diffColorSteps / 2 + 1); - private static final Map similarityToColorHsb = new HashMap<>(diffColorSteps / 2 + 1); + private static final Logger LOGGER = LoggerFactory.getLogger(MatchPaneSrc.class); + private static final Comparator> SIMILARITY_COMPARATOR = (a, b) -> Float.compare(a.getSimilarity(), b.getSimilarity()); + private static final Comparator CLASS_NAME_COMPARATOR = Util::compareNatural; + private static final int DIFF_COLOR_STEPS = 20; + private static final float DIFF_COLOR_STEP_ALIGNMENT = 1f / DIFF_COLOR_STEPS; + private static final Map SIMILARITY_TO_COLOR_RGB = new HashMap<>(DIFF_COLOR_STEPS / 2 + 1); + private static final Map SIMILARITY_TO_COLOR_HSB = new HashMap<>(DIFF_COLOR_STEPS / 2 + 1); private final MatcherGui gui; private final Collection components = new ArrayList<>(); diff --git a/matcher-gui/src/main/java/matcher/gui/ui/Shortcuts.java b/matcher-gui/src/main/java/matcher/gui/ui/Shortcuts.java index 3606ebe0..894f06cf 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/Shortcuts.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/Shortcuts.java @@ -9,7 +9,7 @@ import matcher.gui.MatcherGui; -public class Shortcuts { +public final class Shortcuts { public static void init(MatcherGui gui) { Map accelerators = gui.getScene().getAccelerators(); @@ -28,4 +28,7 @@ public static void init(MatcherGui gui) { // I - ignore (toggle matchable) accelerators.put(new KeyCodeCombination(KeyCode.I), () -> gui.getBottomPane().getMatchableButton().fireEvent(new ActionEvent())); } + + private Shortcuts() { + } } diff --git a/matcher-gui/src/main/java/matcher/gui/ui/StyledListCell.java b/matcher-gui/src/main/java/matcher/gui/ui/StyledListCell.java index 7fff536c..02d15b27 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/StyledListCell.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/StyledListCell.java @@ -19,5 +19,5 @@ protected void updateItem(T item, boolean empty) { protected abstract String getText(T item); protected void setCustomStyle(StyledListCell cell, T item) { - }; + } } diff --git a/matcher-gui/src/main/java/matcher/gui/ui/menu/FileMenu.java b/matcher-gui/src/main/java/matcher/gui/ui/menu/FileMenu.java index 2eacbee1..39ba5a1c 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/menu/FileMenu.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/menu/FileMenu.java @@ -5,7 +5,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Arrays; import java.util.EnumSet; import java.util.List; import java.util.Locale; @@ -23,6 +22,8 @@ import javafx.stage.FileChooser; import javafx.stage.FileChooser.ExtensionFilter; import javafx.stage.Window; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import net.fabricmc.mappingio.MappingReader; import net.fabricmc.mappingio.format.MappingFormat; @@ -114,14 +115,14 @@ private void loadProject() { gui.onProjectChange(); gui.runProgressTask("Initializing files...", - progressReceiver -> MatchesIo.read(res.path, newConfig.paths, newConfig.verifyFiles, gui.getMatcher(), progressReceiver), - () -> gui.onProjectChange(), + progressReceiver -> MatchesIo.read(res.path, newConfig.paths(), newConfig.verifyFiles(), gui.getMatcher(), progressReceiver), + gui::onProjectChange, Throwable::printStackTrace); } public ProjectLoadSettings requestProjectLoadSettings() { Dialog dialog = new Dialog<>(); - //dialog.initModality(Modality.APPLICATION_MODAL); + // dialog.initModality(Modality.APPLICATION_MODAL); dialog.setResizable(true); dialog.setTitle("Project paths"); dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL); @@ -134,9 +135,9 @@ public ProjectLoadSettings requestProjectLoadSettings() { ProjectLoadSettings settings = dialog.showAndWait().orElse(null); - if (settings != null && !settings.paths.isEmpty()) { - Config.setInputDirs(settings.paths); - Config.setVerifyInputFiles(settings.verifyFiles); + if (settings != null && !settings.paths().isEmpty()) { + Config.setInputDirs(settings.paths()); + Config.setVerifyInputFiles(settings.verifyFiles()); Config.saveAsLast(); } @@ -163,7 +164,7 @@ private void loadMappings(MappingFormat format) { List namespaces = MappingReader.getNamespaces(file, format); Dialog dialog = new Dialog<>(); - //dialog.initModality(Modality.APPLICATION_MODAL); + // dialog.initModality(Modality.APPLICATION_MODAL); dialog.setResizable(true); dialog.setTitle("Import Settings"); dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL); @@ -171,21 +172,20 @@ private void loadMappings(MappingFormat format) { LoadMappingsPane content = new LoadMappingsPane(namespaces); dialog.getDialogPane().setContent(content); dialog.setResultConverter(button -> button == ButtonType.OK ? content.getSettings() : null); - final MappingFormat loadFormat = format; Optional result = dialog.showAndWait(); - if (!result.isPresent()) return; + if (result.isEmpty()) return; MappingsLoadSettings settings = result.get(); ClassEnvironment env = gui.getMatcher().getEnv(); - Mappings.load(file, loadFormat, + Mappings.load(file, format, settings.nsSource, settings.nsTarget, settings.fieldSource, settings.fieldTarget, - (settings.a ? env.getEnvA() : env.getEnvB()), + settings.a ? env.getEnvA() : env.getEnvB(), settings.replace); } catch (IOException e) { - e.printStackTrace(); + LOGGER.error("Error while loading mappings", e); gui.showAlert(AlertType.ERROR, "Load error", "Error while loading mappings", e.toString()); return; } @@ -202,11 +202,11 @@ private static List getMappingLoadExtensionFilters() { if (format.hasSingleFile()) supportedExtensions.add(format.getGlobPattern()); } - ret.add(new FileChooser.ExtensionFilter("All supported", supportedExtensions)); - ret.add(new FileChooser.ExtensionFilter("Any", "*.*")); + ret.add(new ExtensionFilter("All supported", supportedExtensions)); + ret.add(new ExtensionFilter("Any", "*.*")); for (MappingFormat format : formats) { - if (format.hasSingleFile()) ret.add(new FileChooser.ExtensionFilter(format.name, format.getGlobPattern())); + if (format.hasSingleFile()) ret.add(new ExtensionFilter(format.name, format.getGlobPattern())); } return ret; @@ -222,7 +222,7 @@ private void saveMappings(MappingFormat format) { for (MappingFormat f : MappingFormat.values()) { if (f.hasSingleFile()) { - FileChooser.ExtensionFilter filter = new FileChooser.ExtensionFilter(f.name, "*."+f.fileExt); + FileChooser.ExtensionFilter filter = new ExtensionFilter(f.name, "*." + f.fileExt); fileChooser.getExtensionFilters().add(filter); if (f == format) fileChooser.setSelectedExtensionFilter(filter); @@ -243,11 +243,12 @@ private void saveMappings(MappingFormat format) { try { if (!Util.clearDir(path, file -> !Files.isDirectory(file) && !file.getFileName().toString().endsWith(".mapping"))) { + LOGGER.error("Save location contains non-mapping files: {}", path); gui.showAlert(AlertType.ERROR, "Save error", "Error while preparing save location", "The target directory contains non-mapping files."); return; } } catch (IOException e) { - e.printStackTrace(); + LOGGER.error("Error while preparing save location", e); gui.showAlert(AlertType.ERROR, "Save error", "Error while preparing save location", e.getMessage()); return; } @@ -259,24 +260,27 @@ private void saveMappings(MappingFormat format) { if (format == null) throw new IllegalStateException("mapping format detection failed"); if (format.hasSingleFile()) { - path = path.resolveSibling(path.getFileName().toString()+"."+format.fileExt); + path = path.resolveSibling(path.getFileName().toString() + "." + format.fileExt); } } if (Files.exists(path)) { - if (Files.isDirectory(path) != !format.hasSingleFile()) { + if (Files.isDirectory(path) == format.hasSingleFile()) { + LOGGER.error("Selected file is of the wrong type: expected {}, got {}", + format.hasSingleFile() ? "file" : "directory", + Files.isDirectory(path) ? "directory" : "file"); gui.showAlert(AlertType.ERROR, "Save error", "Invalid file selection", "The selected file is of the wrong type."); return; } } Dialog dialog = new Dialog<>(); - //dialog.initModality(Modality.APPLICATION_MODAL); + // dialog.initModality(Modality.APPLICATION_MODAL); dialog.setResizable(true); dialog.setTitle("Mappings export settings"); dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL); - SaveMappingsPane content = new SaveMappingsPane(format.hasNamespaces); + SaveMappingsPane content = new SaveMappingsPane(format.features().hasNamespaces()); dialog.getDialogPane().setContent(content); dialog.setResultConverter(button -> button == ButtonType.OK ? content.getSettings() : null); final Path savePath = path; @@ -290,22 +294,22 @@ private void saveMappings(MappingFormat format) { Files.deleteIfExists(savePath); } - if (!Mappings.save(savePath, saveFormat, (settings.a ? env.getEnvA() : env.getEnvB()), + if (!Mappings.save(savePath, saveFormat, settings.a ? env.getEnvA() : env.getEnvB(), settings.nsTypes, settings.nsNames, settings.verbosity, settings.forAnyInput, settings.fieldsFirst)) { gui.showAlert(AlertType.WARNING, "Mapping save warning", "No mappings to save", "There are currently no names mapped to matched classes, so saving was aborted."); } } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + LOGGER.error("Error while saving mappings", e); + gui.showAlert(AlertType.ERROR, "Save error", "Error while saving mappings", e.toString()); } }); } private static boolean isDirEmpty(Path dir) { try (Stream stream = Files.list(dir)) { - return !stream.anyMatch(ignore -> true); + return stream.noneMatch(ignore -> true); } catch (IOException e) { - e.printStackTrace(); + LOGGER.error("Error while checking directory contents for {}", dir, e); return false; } } @@ -344,17 +348,17 @@ private void loadMatches() { } private static List getMatchesLoadExtensionFilters() { - return Arrays.asList(new FileChooser.ExtensionFilter("Matches", "*.match")); + return List.of(new ExtensionFilter("Matches", "*.match")); } private void saveMatches() { - SelectedFile res = MatcherGui.requestFile("Save matches file", gui.getScene().getWindow(), Arrays.asList(new FileChooser.ExtensionFilter("Matches", "*.match")), false); + SelectedFile res = MatcherGui.requestFile("Save matches file", gui.getScene().getWindow(), List.of(new ExtensionFilter("Matches", "*.match")), false); if (res == null) return; Path path = res.path; if (!path.getFileName().toString().toLowerCase(Locale.ENGLISH).endsWith(".match")) { - path = path.resolveSibling(path.getFileName().toString()+".match"); + path = path.resolveSibling(path.getFileName() + ".match"); } try { @@ -368,11 +372,11 @@ private void saveMatches() { gui.showAlert(AlertType.WARNING, "Matches save warning", "No matches to save", "There are currently no matched classes, so saving was aborted."); } } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return; + LOGGER.error("Error while saving matches", e); + gui.showAlert(AlertType.ERROR, "Save error", "Error while saving matches", e.toString()); } } + private static final Logger LOGGER = LoggerFactory.getLogger(FileMenu.class); private final MatcherGui gui; } diff --git a/matcher-gui/src/main/java/matcher/gui/ui/menu/FixRecordNamesPane.java b/matcher-gui/src/main/java/matcher/gui/ui/menu/FixRecordNamesPane.java index 509a25e7..25d73269 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/menu/FixRecordNamesPane.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/menu/FixRecordNamesPane.java @@ -18,8 +18,8 @@ class FixRecordNamesPane extends GridPane { } private void init() { - setHgap(GuiConstants.padding); - setVgap(GuiConstants.padding); + setHgap(GuiConstants.PADDING); + setVgap(GuiConstants.PADDING); List namespaces = new ArrayList<>(); diff --git a/matcher-gui/src/main/java/matcher/gui/ui/menu/LoadMappingsPane.java b/matcher-gui/src/main/java/matcher/gui/ui/menu/LoadMappingsPane.java index 9c52195d..824960f8 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/menu/LoadMappingsPane.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/menu/LoadMappingsPane.java @@ -23,8 +23,8 @@ class LoadMappingsPane extends GridPane { } private void init(List namespaces) { - setHgap(GuiConstants.padding); - setVgap(GuiConstants.padding); + setHgap(GuiConstants.PADDING); + setVgap(GuiConstants.PADDING); add(new Label("Namespace"), 1, 0); add(new Label("Field"), 2, 0); diff --git a/matcher-gui/src/main/java/matcher/gui/ui/menu/LoadProjectPane.java b/matcher-gui/src/main/java/matcher/gui/ui/menu/LoadProjectPane.java index 5e4c8dcd..cb61fce9 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/menu/LoadProjectPane.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/menu/LoadProjectPane.java @@ -27,7 +27,7 @@ public class LoadProjectPane extends VBox { LoadProjectPane(List paths, boolean verifyFiles, Window window, Node okButton) { - super(GuiConstants.padding); + super(GuiConstants.PADDING); this.paths = FXCollections.observableArrayList(paths); this.verifyFiles = verifyFiles; @@ -48,7 +48,7 @@ private void init() { list.setPrefHeight(200); VBox.setVgrow(list, Priority.ALWAYS); - HBox footer = new HBox(GuiConstants.padding); + HBox footer = new HBox(GuiConstants.PADDING); getChildren().add(footer); footer.setAlignment(Pos.CENTER_RIGHT); @@ -75,9 +75,8 @@ private void init() { footer.getChildren().add(downButton); downButton.setOnAction(event -> GuiUtil.moveSelectionDown(list)); - ListChangeListener itemChangeListener = change -> { - okButton.setDisable(paths.isEmpty()); - }; + ListChangeListener itemChangeListener = change -> + okButton.setDisable(paths.isEmpty()); list.getItems().addListener(itemChangeListener); @@ -104,15 +103,7 @@ public ProjectLoadSettings createConfig() { return new ProjectLoadSettings(new ArrayList<>(paths), verifyFilesBox.isSelected()); } - public static class ProjectLoadSettings { - public ProjectLoadSettings(List paths, boolean verifyFiles) { - this.paths = paths; - this.verifyFiles = verifyFiles; - } - - public final List paths; - public final boolean verifyFiles; - } + public record ProjectLoadSettings(List paths, boolean verifyFiles) { } private final ObservableList paths; private final boolean verifyFiles; diff --git a/matcher-gui/src/main/java/matcher/gui/ui/menu/MainMenuBar.java b/matcher-gui/src/main/java/matcher/gui/ui/menu/MainMenuBar.java index 451c73b1..6d7581bc 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/menu/MainMenuBar.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/menu/MainMenuBar.java @@ -24,8 +24,8 @@ private void init() { private T addMenu(T menu) { getMenus().add(menu); - if (menu instanceof IGuiComponent) { - gui.addListeningComponent((IGuiComponent) menu); + if (menu instanceof IGuiComponent guiComponentMenu) { + gui.addListeningComponent(guiComponentMenu); } return menu; diff --git a/matcher-gui/src/main/java/matcher/gui/ui/menu/MappingMenu.java b/matcher-gui/src/main/java/matcher/gui/ui/menu/MappingMenu.java index 74aaaeb9..3a28d61e 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/menu/MappingMenu.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/menu/MappingMenu.java @@ -36,7 +36,7 @@ private void init() { private void fixRecordMemberNames() { Dialog dialog = new Dialog<>(); - //dialog.initModality(Modality.APPLICATION_MODAL); + // dialog.initModality(Modality.APPLICATION_MODAL); dialog.setResizable(true); dialog.setTitle("Mapping Namespace Settings"); dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL); @@ -46,7 +46,7 @@ private void fixRecordMemberNames() { dialog.setResultConverter(button -> button == ButtonType.OK ? content.getSettings() : null); Optional result = dialog.showAndWait(); - if (!result.isPresent()) return; + if (result.isEmpty()) return; NamespaceSettings settings = result.get(); diff --git a/matcher-gui/src/main/java/matcher/gui/ui/menu/MatchingMenu.java b/matcher-gui/src/main/java/matcher/gui/ui/menu/MatchingMenu.java index e433ee49..61fd13d6 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/menu/MatchingMenu.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/menu/MatchingMenu.java @@ -106,13 +106,12 @@ public void showMatchingStatus() { MatchingStatus status = gui.getMatcher().getStatus(true); gui.showAlert(AlertType.INFORMATION, "Matching status", "Current matching status", - String.format("Classes: %d / %d (%.2f%%)%nMethods: %d / %d (%.2f%%)%nFields: %d / %d (%.2f%%)%nMethod args: %d / %d (%.2f%%)%nMethod vars: %d / %d (%.2f%%)", - status.matchedClassCount, status.totalClassCount, (status.totalClassCount == 0 ? 0 : 100. * status.matchedClassCount / status.totalClassCount), - status.matchedMethodCount, status.totalMethodCount, (status.totalMethodCount == 0 ? 0 : 100. * status.matchedMethodCount / status.totalMethodCount), - status.matchedFieldCount, status.totalFieldCount, (status.totalFieldCount == 0 ? 0 : 100. * status.matchedFieldCount / status.totalFieldCount), - status.matchedMethodArgCount, status.totalMethodArgCount, (status.totalMethodArgCount == 0 ? 0 : 100. * status.matchedMethodArgCount / status.totalMethodArgCount), - status.matchedMethodVarCount, status.totalMethodVarCount, (status.totalMethodVarCount == 0 ? 0 : 100. * status.matchedMethodVarCount / status.totalMethodVarCount) - )); + "Classes: %d / %d (%.2f%%)%nMethods: %d / %d (%.2f%%)%nFields: %d / %d (%.2f%%)%nMethod args: %d / %d (%.2f%%)%nMethod vars: %d / %d (%.2f%%)".formatted( + status.matchedClassCount, status.totalClassCount, status.totalClassCount == 0 ? 0 : 100. * status.matchedClassCount / status.totalClassCount, + status.matchedMethodCount, status.totalMethodCount, status.totalMethodCount == 0 ? 0 : 100. * status.matchedMethodCount / status.totalMethodCount, + status.matchedFieldCount, status.totalFieldCount, status.totalFieldCount == 0 ? 0 : 100. * status.matchedFieldCount / status.totalFieldCount, + status.matchedMethodArgCount, status.totalMethodArgCount, status.totalMethodArgCount == 0 ? 0 : 100. * status.matchedMethodArgCount / status.totalMethodArgCount, + status.matchedMethodVarCount, status.totalMethodVarCount, status.totalMethodVarCount == 0 ? 0 : 100. * status.matchedMethodVarCount / status.totalMethodVarCount)); } private final MatcherGui gui; diff --git a/matcher-gui/src/main/java/matcher/gui/ui/menu/NewProjectPane.java b/matcher-gui/src/main/java/matcher/gui/ui/menu/NewProjectPane.java index 28a2b782..31656f49 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/menu/NewProjectPane.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/menu/NewProjectPane.java @@ -6,7 +6,6 @@ import java.nio.file.Path; import java.nio.file.PathMatcher; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -30,7 +29,6 @@ import javafx.scene.layout.Priority; import javafx.scene.layout.RowConstraints; import javafx.scene.layout.VBox; -import javafx.stage.FileChooser; import javafx.stage.FileChooser.ExtensionFilter; import javafx.stage.Window; @@ -60,8 +58,8 @@ public NewProjectPane(ProjectConfig config, Window window, Node okButton) { } private void init() { - setHgap(4 * GuiConstants.padding); - setVgap(4 * GuiConstants.padding); + setHgap(4 * GuiConstants.PADDING); + setVgap(4 * GuiConstants.PADDING); ColumnConstraints colConstraint = new ColumnConstraints(); colConstraint.setPercentWidth(50); @@ -80,7 +78,7 @@ private void init() { add(createFilesSelectionPane("Class path A", classPathA, window, true, false), 0, 1); add(createFilesSelectionPane("Class path B", classPathB, window, true, false), 1, 1); - HBox hbox = new HBox(GuiConstants.padding); + HBox hbox = new HBox(GuiConstants.PADDING); Button swapButton = new Button("swap A ⇄ B"); hbox.getChildren().add(swapButton); swapButton.setOnAction(event -> { @@ -126,9 +124,9 @@ private void init() { } private Node createFilesSelectionPane(String name, ObservableList entries, Window window, boolean isClassPath, boolean isShared) { - VBox ret = new VBox(GuiConstants.padding); + VBox ret = new VBox(GuiConstants.PADDING); - ret.getChildren().add(new Label(name+":")); + ret.getChildren().add(new Label(name + ":")); ListView list = new ListView<>(entries); ret.getChildren().add(list); @@ -138,7 +136,7 @@ private Node createFilesSelectionPane(String name, ObservableList entries, list.setPrefHeight(isShared ? 200 : 100); VBox.setVgrow(list, Priority.ALWAYS); - HBox footer = new HBox(GuiConstants.padding); + HBox footer = new HBox(GuiConstants.PADDING); ret.getChildren().add(footer); footer.setAlignment(Pos.CENTER_RIGHT); @@ -287,7 +285,7 @@ private Node createFilesSelectionPane(String name, ObservableList entries, } private static List getInputLoadExtensionFilters() { - return Arrays.asList(new FileChooser.ExtensionFilter("Java archive", "*.jar")); + return List.of(new ExtensionFilter("Java archive", "*.jar")); } private static PathMatcher getInputLoadExtensionMatcher() { @@ -295,7 +293,7 @@ private static PathMatcher getInputLoadExtensionMatcher() { } private Node createMiscPane() { - VBox ret = new VBox(GuiConstants.padding); + VBox ret = new VBox(GuiConstants.PADDING); ret.getChildren().add(new Label("Non-obfuscated class name pattern A (regex):")); ret.getChildren().add(nonObfuscatedClassPatternA); diff --git a/matcher-gui/src/main/java/matcher/gui/ui/menu/SaveMappingsPane.java b/matcher-gui/src/main/java/matcher/gui/ui/menu/SaveMappingsPane.java index d03a139f..194b6b15 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/menu/SaveMappingsPane.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/menu/SaveMappingsPane.java @@ -22,8 +22,8 @@ class SaveMappingsPane extends GridPane { } private void init(boolean offerNamespaces) { - setHgap(GuiConstants.padding); - setVgap(GuiConstants.padding); + setHgap(GuiConstants.PADDING); + setVgap(GuiConstants.PADDING); int col23Span = offerNamespaces ? 2 : 1; diff --git a/matcher-gui/src/main/java/matcher/gui/ui/menu/UidMenu.java b/matcher-gui/src/main/java/matcher/gui/ui/menu/UidMenu.java index 5028ca5d..7ba6e2b1 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/menu/UidMenu.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/menu/UidMenu.java @@ -17,6 +17,8 @@ import javafx.scene.control.Menu; import javafx.scene.control.MenuItem; import javafx.scene.control.SeparatorMenuItem; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import matcher.core.Matcher; import matcher.gui.MatcherGui; @@ -73,7 +75,7 @@ private void init() { private void setup() { Dialog dialog = new Dialog<>(); - //dialog.initModality(Modality.APPLICATION_MODAL); + // dialog.initModality(Modality.APPLICATION_MODAL); dialog.setResizable(true); dialog.setTitle("UID Setup"); dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL); @@ -100,7 +102,7 @@ private void importMatches(DoubleConsumer progressConsumer) { HttpURLConnection conn = (HttpURLConnection) new URL("https", config.getAddress().getHostString(), config.getAddress().getPort(), - String.format("/%s/matches/%s/%s", config.getProject(), config.getVersionA(), config.getVersionB())).openConnection(); + "/%s/matches/%s/%s".formatted(config.getProject(), config.getVersionA(), config.getVersionB())).openConnection(); conn.setRequestProperty("X-Token", config.getToken()); progressConsumer.accept(0.5); @@ -196,7 +198,7 @@ private void submitMatches(DoubleConsumer progressConsumer) { HttpURLConnection conn = (HttpURLConnection) new URL("https", config.getAddress().getHostString(), config.getAddress().getPort(), - String.format("/%s/link/%s/%s", config.getProject(), config.getVersionA(), config.getVersionB())).openConnection(); + "/%s/link/%s/%s".formatted(config.getProject(), config.getVersionA(), config.getVersionB())).openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("X-Token", config.getToken()); conn.setDoOutput(true); @@ -230,8 +232,8 @@ private void submitMatches(DoubleConsumer progressConsumer) { requested.add(arg); os.writeByte(TYPE_ARG); - os.writeUTF(srcMethodId+arg.getId()); - os.writeUTF(dstMethodId+arg.getMatch().getId()); + os.writeUTF(srcMethodId + arg.getId()); + os.writeUTF(dstMethodId + arg.getMatch().getId()); } } @@ -240,8 +242,8 @@ private void submitMatches(DoubleConsumer progressConsumer) { requested.add(field); os.writeByte(TYPE_FIELD); - os.writeUTF(cls.getId()+"/"+field.getId()); - os.writeUTF(cls.getMatch().getId()+"/"+field.getMatch().getId()); + os.writeUTF(cls.getId() + "/" + field.getId()); + os.writeUTF(cls.getMatch().getId() + "/" + field.getMatch().getId()); } } } @@ -268,7 +270,7 @@ private void assignMissing() { int nextFieldUid = env.nextFieldUid; List classes = new ArrayList<>(env.getClassesB()); - classes.sort(ClassInstance.nameComparator); + classes.sort(ClassInstance.NAME_COMPARATOR); List methods = new ArrayList<>(); List fields = new ArrayList<>(); @@ -287,7 +289,7 @@ private void assignMissing() { } if (!methods.isEmpty()) { - methods.sort(MemberInstance.nameComparator); + methods.sort(MemberInstance.NAME_COMPARATOR); for (MethodInstance method : methods) { int uid = nextMethodUid++; @@ -307,7 +309,7 @@ private void assignMissing() { } if (!fields.isEmpty()) { - fields.sort(MemberInstance.nameComparator); + fields.sort(MemberInstance.NAME_COMPARATOR); for (FieldInstance field : fields) { field.setUid(nextFieldUid++); @@ -318,16 +320,22 @@ private void assignMissing() { } } - Matcher.LOGGER.info("UIDs assigned: {} class, {} method, {} field", - nextClassUid - env.nextClassUid, - nextMethodUid - env.nextMethodUid, - nextFieldUid - env.nextFieldUid); + int finalNextClassUid = nextClassUid; + int finalNextMethodUid = nextMethodUid; + int finalNextFieldUid = nextFieldUid; + + LOGGER.atInfo() + .addArgument(() -> finalNextClassUid - env.nextClassUid) + .addArgument(() -> finalNextMethodUid - env.nextMethodUid) + .addArgument(() -> finalNextFieldUid - env.nextFieldUid) + .log("UIDs assigned: {} class, {} method, {} field"); env.nextClassUid = nextClassUid; env.nextMethodUid = nextMethodUid; env.nextFieldUid = nextFieldUid; } + private static final Logger LOGGER = LoggerFactory.getLogger(UidMenu.class); private static final byte TYPE_CLASS = 0; private static final byte TYPE_METHOD = 1; private static final byte TYPE_FIELD = 2; diff --git a/matcher-gui/src/main/java/matcher/gui/ui/menu/UidSetupPane.java b/matcher-gui/src/main/java/matcher/gui/ui/menu/UidSetupPane.java index c952261a..6033aee2 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/menu/UidSetupPane.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/menu/UidSetupPane.java @@ -14,15 +14,15 @@ public class UidSetupPane extends GridPane { UidSetupPane(UidConfig config, Window window, Node okButton) { - //this.window = window; + // this.window = window; this.okButton = okButton; init(config); } private void init(UidConfig config) { - setHgap(GuiConstants.padding); - setVgap(GuiConstants.padding); + setHgap(GuiConstants.PADDING); + setVgap(GuiConstants.PADDING); InetSocketAddress address = config.getAddress(); @@ -85,7 +85,7 @@ UidConfig createConfig() { versionBField.getText()); } - //private final Window window; + // private final Window window; private final Node okButton; private TextField hostField; diff --git a/matcher-gui/src/main/java/matcher/gui/ui/menu/ViewMenu.java b/matcher-gui/src/main/java/matcher/gui/ui/menu/ViewMenu.java index 4ca80196..26c564a0 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/menu/ViewMenu.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/menu/ViewMenu.java @@ -77,7 +77,7 @@ private void init() { for (int i = 0; i < NameType.AUX_COUNT; i++) { final int index = i; - useAuxNamesItems[i] = GuiUtil.addCheckMenuItem(this, String.format("Use aux%s names", i > 0 ? Integer.toString(i + 1) : ""), + useAuxNamesItems[i] = GuiUtil.addCheckMenuItem(this, "Use aux%s names".formatted(i > 0 ? Integer.toString(i + 1) : ""), gui.getNameType() != gui.getNameType().withAux(i, false), value -> gui.setNameType(gui.getNameType().withAux(index, value))); } diff --git a/matcher-gui/src/main/java/matcher/gui/ui/tab/BytecodeTab.java b/matcher-gui/src/main/java/matcher/gui/ui/tab/BytecodeTab.java index 07155548..613ad838 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/tab/BytecodeTab.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/tab/BytecodeTab.java @@ -32,10 +32,10 @@ public void onSelectStateChange(boolean tabSelected) { if (updateNeeded > 0) update(); - if (selectedMember instanceof MethodInstance) { - onMethodSelect((MethodInstance) selectedMember); - } else if (selectedMember instanceof FieldInstance) { - onFieldSelect((FieldInstance) selectedMember); + if (selectedMember instanceof MethodInstance mth) { + onMethodSelect(mth); + } else if (selectedMember instanceof FieldInstance fld) { + onFieldSelect(fld); } } diff --git a/matcher-gui/src/main/java/matcher/gui/ui/tab/ClassInfoTab.java b/matcher-gui/src/main/java/matcher/gui/ui/tab/ClassInfoTab.java index 90026223..8f39eac5 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/tab/ClassInfoTab.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/tab/ClassInfoTab.java @@ -42,9 +42,9 @@ public ClassInfoTab(MatcherGui gui, ISelectionProvider selectionProvider, boolea private void init() { GridPane grid = new GridPane(); - grid.setPadding(new Insets(GuiConstants.padding)); - grid.setHgap(GuiConstants.padding); - grid.setVgap(GuiConstants.padding); + grid.setPadding(new Insets(GuiConstants.PADDING)); + grid.setHgap(GuiConstants.PADDING); + grid.setVgap(GuiConstants.PADDING); int row = 0; row = addRow("Name", nameLabel, grid, row); @@ -52,7 +52,7 @@ private void init() { row = addRow("Mapped name", mappedNameLabel, grid, row); for (int i = 0; i < NameType.AUX_COUNT; i++) { - row = addRow("AUX name "+(i+1), auxNameLabels[i], grid, row); + row = addRow("AUX name " + (i + 1), auxNameLabels[i], grid, row); } row = addRow("UID", uidLabel, grid, row); @@ -74,7 +74,7 @@ private void init() { } private static int addRow(String name, Node content, GridPane grid, int row) { - Label label = new Label(name+":"); + Label label = new Label(name + ":"); label.setMinWidth(Label.USE_PREF_SIZE); grid.add(label, 0, row); GridPane.setValignment(label, VPos.TOP); @@ -145,7 +145,7 @@ private void update(ClassInstance cls) { } else { String sig = cls.getSignature().toString(nameType.withMapped(false)); String sigMapped = cls.getSignature().toString(nameType.withMapped(true)); - sigLabel.setText(sig.equals(sigMapped) ? sig : sig+" - "+sigMapped); + sigLabel.setText(sig.equals(sigMapped) ? sig : sig + " - " + sigMapped); } outerLabel.setText(cls.getOuterClass() != null ? getName(cls.getOuterClass(), nameType) : "-"); @@ -183,7 +183,7 @@ static String getInputPaths(ClassInstance cls, Predicate filter) { for (int i = 0; i < cls.getAsmNodes().length; i++) { if (!filter.test(cls.getAsmNodes()[i])) continue; - if (ret.length() > 0) ret.append(", "); + if (!ret.isEmpty()) ret.append(", "); String path = cls.getAsmNodeOrigin(i).getPath(); ret.append(path, path.lastIndexOf('/') + 1, path.length()); diff --git a/matcher-gui/src/main/java/matcher/gui/ui/tab/ClassScoresTab.java b/matcher-gui/src/main/java/matcher/gui/ui/tab/ClassScoresTab.java index 9114e764..45f58ac6 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/tab/ClassScoresTab.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/tab/ClassScoresTab.java @@ -44,14 +44,14 @@ private void update() { static TableView> createClassifierTable() { TableView> ret = new TableView<>(); - ret.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); + ret.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY_FLEX_LAST_COLUMN); TableColumn, String> tab0 = new TableColumn<>("name"); tab0.setCellValueFactory(data -> new ReadOnlyObjectWrapper<>(data.getValue().getClassifier().getName())); ret.getColumns().add(tab0); TableColumn, String> tab1 = new TableColumn<>("score"); - tab1.setCellValueFactory(data -> new ReadOnlyObjectWrapper<>(String.format("%.2f", data.getValue().getScore()))); + tab1.setCellValueFactory(data -> new ReadOnlyObjectWrapper<>("%.2f".formatted(data.getValue().getScore()))); ret.getColumns().add(tab1); TableColumn, Double> tab2 = new TableColumn<>("weight"); @@ -59,7 +59,7 @@ static TableView> createClassifierTable() { ret.getColumns().add(tab2); TableColumn, String> tab3 = new TableColumn<>("w. score"); - tab3.setCellValueFactory(data -> new ReadOnlyObjectWrapper<>(String.format("%.2f", data.getValue().getScore() * data.getValue().getClassifier().getWeight()))); + tab3.setCellValueFactory(data -> new ReadOnlyObjectWrapper<>("%.2f".formatted(data.getValue().getScore() * data.getValue().getClassifier().getWeight()))); ret.getColumns().add(tab3); ret.setItems(FXCollections.observableArrayList()); diff --git a/matcher-gui/src/main/java/matcher/gui/ui/tab/FieldInfoTab.java b/matcher-gui/src/main/java/matcher/gui/ui/tab/FieldInfoTab.java index dbd7892d..f629c54b 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/tab/FieldInfoTab.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/tab/FieldInfoTab.java @@ -39,9 +39,9 @@ public FieldInfoTab(MatcherGui gui, ISelectionProvider selectionProvider, boolea private void init() { GridPane grid = new GridPane(); - grid.setPadding(new Insets(GuiConstants.padding)); - grid.setHgap(GuiConstants.padding); - grid.setVgap(GuiConstants.padding); + grid.setPadding(new Insets(GuiConstants.PADDING)); + grid.setHgap(GuiConstants.PADDING); + grid.setVgap(GuiConstants.PADDING); int row = 0; row = addRow("Owner", ownerLabel, grid, row); @@ -50,7 +50,7 @@ private void init() { row = addRow("Mapped name", mappedNameLabel, grid, row); for (int i = 0; i < NameType.AUX_COUNT; i++) { - row = addRow("AUX name "+(i+1), auxNameLabels[i], grid, row); + row = addRow("AUX name " + (i + 1), auxNameLabels[i], grid, row); } row = addRow("UID", uidLabel, grid, row); @@ -70,7 +70,7 @@ private void init() { } private static int addRow(String name, Node content, GridPane grid, int row) { - Label label = new Label(name+":"); + Label label = new Label(name + ":"); label.setMinWidth(Label.USE_PREF_SIZE); grid.add(label, 0, row); GridPane.setValignment(label, VPos.TOP); @@ -140,8 +140,8 @@ private void update(FieldInstance field) { FieldNode asmNode = field.getAsmNode(); sigLabel.setText(asmNode == null || asmNode.signature == null ? "-" : asmNode.signature); - parentLabel.setText(!field.getParents().isEmpty() ? formatClass(field.getParents(), nameType) : "-"); - childLabel.setText(!field.isFinal() ? formatClass(field.getChildren(), nameType) : "-"); + parentLabel.setText(field.getParents().isEmpty() ? "-" : formatClass(field.getParents(), nameType)); + childLabel.setText(field.isFinal() ? "-" : formatClass(field.getChildren(), nameType)); readRefLabel.setText(format(field.getReadRefs(), nameType)); writeRefLabel.setText(format(field.getWriteRefs(), nameType)); diff --git a/matcher-gui/src/main/java/matcher/gui/ui/tab/HierarchyTab.java b/matcher-gui/src/main/java/matcher/gui/ui/tab/HierarchyTab.java index 0efafee7..af79c365 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/tab/HierarchyTab.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/tab/HierarchyTab.java @@ -31,7 +31,7 @@ private void init() { vBox.getChildren().add(classHierarchyTree); vBox.getChildren().add(ifaceList); - Callback, TreeCell> cellFactory = tree -> new TreeCell() { // makes entries in highLights bold + Callback, TreeCell> cellFactory = tree -> new TreeCell<>() { // makes entries in highLights bold @Override protected void updateItem(ClassInstance item, boolean empty) { super.updateItem(item, empty); diff --git a/matcher-gui/src/main/java/matcher/gui/ui/tab/HtmlTextifier.java b/matcher-gui/src/main/java/matcher/gui/ui/tab/HtmlTextifier.java index 62d255dd..0449ebd6 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/tab/HtmlTextifier.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/tab/HtmlTextifier.java @@ -33,8 +33,6 @@ package matcher.gui.ui.tab; -import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.ListIterator; @@ -55,13 +53,14 @@ import matcher.gui.srcprocess.HtmlUtil; import matcher.model.NameType; +import matcher.model.Util; import matcher.model.type.ClassInstance; import matcher.model.type.FieldInstance; import matcher.model.type.MethodInstance; final class HtmlTextifier extends Textifier { HtmlTextifier(ClassInstance cls, NameType nameType) { - super(Opcodes.ASM9); + super(Util.ASM_API_VERSION); this.cls = cls; this.nameType = nameType; @@ -155,7 +154,7 @@ public void visit( .append(" implements") .append(" "); - for (int i = 0; i < interfaces.length; ++i) { + for (int i = 0; i < interfaces.length; i++) { appendDescriptor(INTERNAL_NAME, interfaces[i]); if (i != interfaces.length - 1) { @@ -191,7 +190,7 @@ public void visitSource(final String file, final String debug) { .append("\n"); } - if (stringBuilder.length() > 0) { + if (!stringBuilder.isEmpty()) { text.add(stringBuilder.toString()); } } @@ -339,7 +338,7 @@ public Textifier visitField( final String signature, final Object value) { FieldInstance field = cls.getField(name, descriptor, nameType); - if (field != null) text.add(String.format("
", HtmlUtil.getId(field))); + if (field != null) text.add("
".formatted(HtmlUtil.getId(field))); stringBuilder.setLength(0); stringBuilder.append('\n'); @@ -396,7 +395,7 @@ public Textifier visitMethod( final String signature, final String[] exceptions) { MethodInstance method = cls.getMethod(name, descriptor, nameType); - if (method != null) text.add(String.format("
", HtmlUtil.getId(method))); + if (method != null) text.add("
".formatted(HtmlUtil.getId(method))); stringBuilder.setLength(0); stringBuilder.append('\n'); @@ -576,7 +575,7 @@ private void visitExportOrOpen( appendRawAccess(access); if (modules != null && modules.length > 0) { - for (int i = 0; i < modules.length; ++i) { + for (int i = 0; i < modules.length; i++) { stringBuilder .append(tab2) .append("") @@ -615,7 +614,7 @@ public void visitProvide(final String provide, final String... providers) { .append(" ") .append("with") .append("\n"); - for (int i = 0; i < providers.length; ++i) { + for (int i = 0; i < providers.length; i++) { stringBuilder.append(tab2); appendDescriptor(INTERNAL_NAME, providers[i]); stringBuilder.append(i != providers.length - 1 ? ",\n" : ";\n"); @@ -633,81 +632,65 @@ public void visitProvide(final String provide, final String... providers) { public void visit(final String name, final Object value) { visitAnnotationValue(name); - if (value instanceof String) { - visitString((String) value); - } else if (value instanceof Type) { - visitType((Type) value); - } else if (value instanceof Byte) { - visitByte(((Byte) value).byteValue()); - } else if (value instanceof Boolean) { - visitBoolean(((Boolean) value).booleanValue()); - } else if (value instanceof Short) { - visitShort(((Short) value).shortValue()); - } else if (value instanceof Character) { - visitChar(((Character) value).charValue()); - } else if (value instanceof Integer) { - visitInt(((Integer) value).intValue()); - } else if (value instanceof Float) { - visitFloat(((Float) value).floatValue()); - } else if (value instanceof Long) { - visitLong(((Long) value).longValue()); - } else if (value instanceof Double) { - visitDouble(((Double) value).doubleValue()); + if (value instanceof String string) { + visitString(string); + } else if (value instanceof Type type) { + visitType(type); + } else if (value instanceof Byte boxedByte) { + visitByte(boxedByte); + } else if (value instanceof Boolean boxedBoolean) { + visitBoolean(boxedBoolean); + } else if (value instanceof Short boxedShort) { + visitShort(boxedShort); + } else if (value instanceof Character boxedChar) { + visitChar(boxedChar); + } else if (value instanceof Integer boxedInt) { + visitInt(boxedInt); + } else if (value instanceof Float boxedFloat) { + visitFloat(boxedFloat); + } else if (value instanceof Long boxedLong) { + visitLong(boxedLong); + } else if (value instanceof Double boxedDouble) { + visitDouble(boxedDouble); } else if (value.getClass().isArray()) { stringBuilder.append('{'); - if (value instanceof byte[]) { - byte[] byteArray = (byte[]) value; - + if (value instanceof byte[] byteArray) { for (int i = 0; i < byteArray.length; i++) { maybeAppendComma(i); visitByte(byteArray[i]); } - } else if (value instanceof boolean[]) { - boolean[] booleanArray = (boolean[]) value; - + } else if (value instanceof boolean[] booleanArray) { for (int i = 0; i < booleanArray.length; i++) { maybeAppendComma(i); visitBoolean(booleanArray[i]); } - } else if (value instanceof short[]) { - short[] shortArray = (short[]) value; - + } else if (value instanceof short[] shortArray) { for (int i = 0; i < shortArray.length; i++) { maybeAppendComma(i); visitShort(shortArray[i]); } - } else if (value instanceof char[]) { - char[] charArray = (char[]) value; - + } else if (value instanceof char[] charArray) { for (int i = 0; i < charArray.length; i++) { maybeAppendComma(i); visitChar(charArray[i]); } - } else if (value instanceof int[]) { - int[] intArray = (int[]) value; - + } else if (value instanceof int[] intArray) { for (int i = 0; i < intArray.length; i++) { maybeAppendComma(i); visitInt(intArray[i]); } - } else if (value instanceof long[]) { - long[] longArray = (long[]) value; - + } else if (value instanceof long[] longArray) { for (int i = 0; i < longArray.length; i++) { maybeAppendComma(i); visitLong(longArray[i]); } - } else if (value instanceof float[]) { - float[] floatArray = (float[]) value; - + } else if (value instanceof float[] floatArray) { for (int i = 0; i < floatArray.length; i++) { maybeAppendComma(i); visitFloat(floatArray[i]); } - } else if (value instanceof double[]) { - double[] doubleArray = (double[]) value; - + } else if (value instanceof double[] doubleArray) { for (int i = 0; i < doubleArray.length; i++) { maybeAppendComma(i); visitDouble(doubleArray[i]); @@ -861,7 +844,7 @@ public void visitParameter(final String name, final int access) { appendAccess(access); stringBuilder .append(' ') - .append((name == null) ? "" : name) + .append(name == null ? "" : name) .append("\n"); text.add(stringBuilder.toString()); } @@ -995,7 +978,7 @@ public void visitIntInsn(final int opcode, final int operand) { } else { stringBuilder .append("") - .append(Integer.toString(operand)); + .append(operand); } stringBuilder.append('\n'); @@ -1120,20 +1103,18 @@ public void visitInvokeDynamicInsn( for (Object value : bootstrapMethodArguments) { stringBuilder.append(tab3); - if (value instanceof String) { + if (value instanceof String string) { stringBuilder.append(""); - Printer.appendString(stringBuilder, (String) value); + Printer.appendString(stringBuilder, string); stringBuilder.append(""); - } else if (value instanceof Type) { - Type type = (Type) value; - + } else if (value instanceof Type type) { if (type.getSort() == Type.METHOD) { appendDescriptor(METHOD_DESCRIPTOR, type.getDescriptor()); } else { visitType(type); } - } else if (value instanceof Handle) { - appendHandle((Handle) value); + } else if (value instanceof Handle handle) { + appendHandle(handle); } else { stringBuilder.append(value); } @@ -1173,14 +1154,14 @@ public void visitLdcInsn(final Object value) { .append("") .append("LDC") .append(" "); - if (value instanceof String) { + if (value instanceof String string) { stringBuilder.append(""); - Printer.appendString(stringBuilder, (String) value); + Printer.appendString(stringBuilder, string); stringBuilder.append(""); - } else if (value instanceof Type) { + } else if (value instanceof Type type) { stringBuilder .append("") - .append(((Type) value).getDescriptor()) + .append(type.getDescriptor()) .append("") .append("") .append(CLASS_SUFFIX) @@ -1220,7 +1201,7 @@ public void visitTableSwitchInsn( .append("") .append("TABLESWITCH") .append("\n"); - for (int i = 0; i < labels.length; ++i) { + for (int i = 0; i < labels.length; i++) { stringBuilder .append(tab3) .append(min + i) @@ -1245,7 +1226,7 @@ public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Labe .append("") .append("LOOKUPSWITCH") .append("\n"); - for (int i = 0; i < labels.length; ++i) { + for (int i = 0; i < labels.length; i++) { stringBuilder .append(tab3) .append(keys[i]) @@ -1385,7 +1366,7 @@ public Printer visitLocalVariableAnnotation( stringBuilder .append(", ") .append(typePath); - for (int i = 0; i < start.length; ++i) { + for (int i = 0; i < start.length; i++) { stringBuilder.append(" [ "); appendLabel(start[i]); stringBuilder.append(" - "); @@ -1504,12 +1485,12 @@ public void visitAttribute(final Attribute attribute) { .append(" "); appendDescriptor(-1, attribute.type); - if (attribute instanceof TextifierSupport) { + if (attribute instanceof TextifierSupport support) { if (labelNames == null) { labelNames = new HashMap<>(); } - ((TextifierSupport) attribute).textify(stringBuilder, labelNames); + support.textify(stringBuilder, labelNames); } else { stringBuilder.append(" : unknown\n"); } @@ -1650,14 +1631,8 @@ protected void appendLabel(final Label label) { labelNames = new HashMap<>(); } - String name = labelNames.get(label); - - if (name == null) { - name = "L" + labelNames.size(); - labelNames.put(label, name); - } - - boolean number = numberPattern.matcher(name).matches(); + String name = labelNames.computeIfAbsent(label, k -> "L" + labelNames.size()); + boolean number = NUMBER_PATTERN.matcher(name).matches(); stringBuilder .append(number ? "" : "") @@ -1666,6 +1641,7 @@ protected void appendLabel(final Label label) { } @Override + @SuppressWarnings("deprecation") protected void appendHandle(final Handle handle) { int tag = handle.getTag(); stringBuilder @@ -1895,23 +1871,21 @@ private void appendTypeReference(final int typeRef) { * org.objectweb.asm.MethodVisitor#visitFrame}. */ private void appendFrameTypes(final int numTypes, final Object[] frameTypes) { - for (int i = 0; i < numTypes; ++i) { + for (int i = 0; i < numTypes; i++) { if (i > 0) { stringBuilder.append(' '); } - if (frameTypes[i] instanceof String) { - String descriptor = (String) frameTypes[i]; - + if (frameTypes[i] instanceof String descriptor) { if (descriptor.charAt(0) == '[') { appendDescriptor(FIELD_DESCRIPTOR, descriptor); } else { appendDescriptor(INTERNAL_NAME, descriptor); } - } else if (frameTypes[i] instanceof Integer) { + } else if (frameTypes[i] instanceof Integer integer) { stringBuilder .append("") - .append(FRAME_TYPES.get(((Integer) frameTypes[i]).intValue())) + .append(FRAME_TYPES.get(integer)) .append(""); } else { appendLabel((Label) frameTypes[i]); @@ -1947,11 +1921,10 @@ private static Object escape(Object o) { for (ListIterator it = ((List) o).listIterator(); it.hasNext(); ) { it.set(escape(it.next())); } - } else if (o instanceof String) { - String str = (String) o; + } else if (o instanceof String str) { o = HtmlUtil.escape(str, "div", "span"); } else { - throw new IllegalStateException("unexpected object type: "+o.getClass()); + throw new IllegalStateException("unexpected object type: " + o.getClass()); } return o; @@ -1986,9 +1959,9 @@ private static Object escape(Object o) { private static final String INVISIBLE = " // invisible\n"; private static final List FRAME_TYPES = - Collections.unmodifiableList(Arrays.asList("T", "I", "F", "D", "J", "N", "U")); + List.of("T", "I", "F", "D", "J", "N", "U"); - private static final Pattern numberPattern = Pattern.compile("-?\\d+(\\.\\d+)?"); + private static final Pattern NUMBER_PATTERN = Pattern.compile("-?\\d+(\\.\\d+)?"); /** The access flags of the visited class. */ private int access; diff --git a/matcher-gui/src/main/java/matcher/gui/ui/tab/MethodInfoTab.java b/matcher-gui/src/main/java/matcher/gui/ui/tab/MethodInfoTab.java index c26b56f8..a77f91a1 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/tab/MethodInfoTab.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/tab/MethodInfoTab.java @@ -44,9 +44,9 @@ public MethodInfoTab(MatcherGui gui, ISelectionProvider selectionProvider, boole private void init() { GridPane grid = new GridPane(); - grid.setPadding(new Insets(GuiConstants.padding)); - grid.setHgap(GuiConstants.padding); - grid.setVgap(GuiConstants.padding); + grid.setPadding(new Insets(GuiConstants.PADDING)); + grid.setHgap(GuiConstants.PADDING); + grid.setVgap(GuiConstants.PADDING); int row = 0; row = addRow("Owner", ownerLabel, grid, row); @@ -55,7 +55,7 @@ private void init() { row = addRow("Mapped name", mappedNameLabel, grid, row); for (int i = 0; i < NameType.AUX_COUNT; i++) { - row = addRow("AUX name "+(i+1), auxNameLabels[i], grid, row); + row = addRow("AUX name " + (i + 1), auxNameLabels[i], grid, row); } row = addRow("UID", uidLabel, grid, row); @@ -81,7 +81,7 @@ private void init() { } private static int addRow(String name, Node content, GridPane grid, int row) { - Label label = new Label(name+":"); + Label label = new Label(name + ":"); label.setMinWidth(Label.USE_PREF_SIZE); grid.add(label, 0, row); GridPane.setValignment(label, VPos.TOP); @@ -160,8 +160,8 @@ private void update(MethodInstance method) { typeLabel.setText(method.getType().name()); - parentLabel.setText(!method.getParents().isEmpty() ? formatClass(method.getParents(), nameType) : "-"); - childLabel.setText(!method.isFinal() ? formatClass(method.getChildren(), nameType) : "-"); + parentLabel.setText(method.getParents().isEmpty() ? "-" : formatClass(method.getParents(), nameType)); + childLabel.setText(method.isFinal() ? "-" : formatClass(method.getChildren(), nameType)); if (method.getAllHierarchyMembers() != null && method.getAllHierarchyMembers().size() > 1) { hierarchyLabel.setText(format(method.getAllHierarchyMembers().stream().filter(m -> m != method).map(MethodInstance::getCls), nameType)); diff --git a/matcher-gui/src/main/java/matcher/gui/ui/tab/SourcecodeTab.java b/matcher-gui/src/main/java/matcher/gui/ui/tab/SourcecodeTab.java index 96c5086e..3c80c3ce 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/tab/SourcecodeTab.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/tab/SourcecodeTab.java @@ -1,16 +1,18 @@ package matcher.gui.ui.tab; -import java.io.PrintWriter; -import java.io.StringWriter; import java.util.Set; import java.util.concurrent.Future; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import matcher.gui.MatcherGui; import matcher.gui.srcprocess.HtmlUtil; import matcher.gui.srcprocess.SrcDecorator; import matcher.gui.srcprocess.SrcDecorator.SrcParseException; import matcher.gui.ui.ISelectionProvider; import matcher.model.NameType; +import matcher.model.Util; import matcher.model.type.ClassInstance; import matcher.model.type.Decompiler; import matcher.model.type.FieldInstance; @@ -36,10 +38,10 @@ public void onSelectStateChange(boolean tabSelected) { if (updateNeeded != UPDATE_NONE) update(); - if (selectedMember instanceof MethodInstance) { - onMethodSelect((MethodInstance) selectedMember); - } else if (selectedMember instanceof FieldInstance) { - onFieldSelect((FieldInstance) selectedMember); + if (selectedMember instanceof MethodInstance method) { + onMethodSelect(method); + } else if (selectedMember instanceof FieldInstance field) { + onFieldSelect(field); } } @@ -95,7 +97,7 @@ private void update() { NameType nameType = gui.getNameType().withUnmatchedTmp(unmatchedTmp); Decompiler decompiler = gui.getDecompiler().get(); - //Gui.runAsyncTask(() -> gui.getEnv().decompile(selectedClass, true)) + // Gui.runAsyncTask(() -> gui.getEnv().decompile(selectedClass, true)) pendingUpdateTask = MatcherGui.runAsyncTask(() -> SrcDecorator.decorate(gui.getEnv().decompile(decompiler, selectedClass, nameType), selectedClass, nameType)) .whenComplete((res, exc) -> applyDecompilerResult(res, exc, cDecompId)); } @@ -103,23 +105,23 @@ private void update() { private void applyDecompilerResult(String res, Throwable exc, int cDecompId) { if (cDecompId != decompId) { if (exc != null) { - exc.printStackTrace(); + if (exc instanceof SrcParseException) { + LOGGER.debug("parse error (old task, ignored)", exc); + } else { + LOGGER.debug("decompile error (old task, ignored)", exc); + } } return; } if (exc != null) { - exc.printStackTrace(); - - StringWriter sw = new StringWriter(); - exc.printStackTrace(new PrintWriter(sw)); - - if (exc instanceof SrcParseException) { - SrcParseException parseExc = (SrcParseException) exc; - displayText("parse error: "+parseExc.problems+"\ndecompiled source:\n"+parseExc.source); + if (exc instanceof SrcParseException parseExc) { + LOGGER.debug("parse error", exc); + displayText("parse error: " + parseExc.problems + "\ndecompiled source:\n" + parseExc.source); } else { - displayText("decompile error: "+sw.toString()); + LOGGER.error("decompile error", exc); + displayText("decompile error: " + Util.getStackTrace(exc)); } } else { double prevScroll = updateNeeded == UPDATE_REFRESH ? getScrollTop() : 0; @@ -152,6 +154,7 @@ public void onFieldSelect(FieldInstance field) { } } + private static final Logger LOGGER = LoggerFactory.getLogger(SourcecodeTab.class); private static final int UPDATE_NONE = 0; private static final int UPDATE_RESET = 1; private static final int UPDATE_REFRESH = 2; // tries to keep scroll position diff --git a/matcher-gui/src/main/java/matcher/gui/ui/tab/VarInfoTab.java b/matcher-gui/src/main/java/matcher/gui/ui/tab/VarInfoTab.java index 282e2bb7..03806280 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/tab/VarInfoTab.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/tab/VarInfoTab.java @@ -34,9 +34,9 @@ public VarInfoTab(MatcherGui gui, ISelectionProvider selectionProvider, boolean private void init() { GridPane grid = new GridPane(); - grid.setPadding(new Insets(GuiConstants.padding)); - grid.setHgap(GuiConstants.padding); - grid.setVgap(GuiConstants.padding); + grid.setPadding(new Insets(GuiConstants.PADDING)); + grid.setHgap(GuiConstants.PADDING); + grid.setVgap(GuiConstants.PADDING); int row = 0; row = addRow("Kind", kindLabel, grid, row); @@ -46,7 +46,7 @@ private void init() { row = addRow("Mapped name", mappedNameLabel, grid, row); for (int i = 0; i < NameType.AUX_COUNT; i++) { - row = addRow("AUX name "+(i+1), auxNameLabels[i], grid, row); + row = addRow("AUX name " + (i + 1), auxNameLabels[i], grid, row); } row = addRow("UID", uidLabel, grid, row); @@ -63,7 +63,7 @@ private void init() { } private static int addRow(String name, Node content, GridPane grid, int row) { - Label label = new Label(name+":"); + Label label = new Label(name + ":"); label.setMinWidth(Label.USE_PREF_SIZE); grid.add(label, 0, row); GridPane.setValignment(label, VPos.TOP); diff --git a/matcher-gui/src/main/java/matcher/gui/ui/tab/WebViewTab.java b/matcher-gui/src/main/java/matcher/gui/ui/tab/WebViewTab.java index 7a0d2e2c..d2b3b18f 100644 --- a/matcher-gui/src/main/java/matcher/gui/ui/tab/WebViewTab.java +++ b/matcher-gui/src/main/java/matcher/gui/ui/tab/WebViewTab.java @@ -47,12 +47,12 @@ protected void displayHtml(String html) { html = template.replace("%text%", html) .replace("%theme_path%", MatcherGui.getThemeCss(Config.getTheme()).toExternalForm()); - //Matcher.LOGGER.debug(html); + // LOGGER.debug(html); webView.getEngine().loadContent(html); } protected void select(String anchorId) { - addWebViewTask(() -> webView.getEngine().executeScript("var newAnchor = document.getElementById('"+anchorId+"');" + addWebViewTask(() -> webView.getEngine().executeScript("var newAnchor = document.getElementById('" + anchorId + "');" + "if (newAnchor !== null) document.body.scrollTop = newAnchor.getBoundingClientRect().top + window.scrollY;" + "if (window.hasOwnProperty('anchorElem') && window.anchorElem !== null) window.anchorElem.classList.remove('selected');" + "if (newAnchor !== null) newAnchor.classList.add('selected');" @@ -71,7 +71,7 @@ protected double getScrollTop() { } protected void setScrollTop(double value) { - addWebViewTask(() -> webView.getEngine().executeScript("document.body.scrollTop = "+value)); + addWebViewTask(() -> webView.getEngine().executeScript("document.body.scrollTop = " + value)); } private void addWebViewTask(Runnable r) { @@ -90,7 +90,7 @@ private static String readTemplate(String name) { char[] buffer = new char[4000]; int offset = 0; - try (InputStream is = SourcecodeTab.class.getResourceAsStream("/"+name)) { + try (InputStream is = SourcecodeTab.class.getResourceAsStream("/" + name)) { if (is == null) throw new FileNotFoundException(name); Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8); diff --git a/matcher-model/build.gradle b/matcher-model/build.gradle index 68d1bfc6..c8a7bcca 100644 --- a/matcher-model/build.gradle +++ b/matcher-model/build.gradle @@ -1,6 +1,7 @@ plugins { id 'matcher.common' id 'matcher.publishing.maven' + id 'matcher.openrewrite.java11' } base { diff --git a/matcher-model/src/main/java/matcher/model/SignatureInference.java b/matcher-model/src/main/java/matcher/model/SignatureInference.java index 0ef4271d..5a719677 100644 --- a/matcher-model/src/main/java/matcher/model/SignatureInference.java +++ b/matcher-model/src/main/java/matcher/model/SignatureInference.java @@ -109,4 +109,7 @@ private static void processClsTypeSig(ClassTypeSignature sig, Set shadow } } } + + private SignatureInference() { + } } diff --git a/matcher-model/src/main/java/matcher/model/SimilarityChecker.java b/matcher-model/src/main/java/matcher/model/SimilarityChecker.java index a88e87ee..42f4e427 100644 --- a/matcher-model/src/main/java/matcher/model/SimilarityChecker.java +++ b/matcher-model/src/main/java/matcher/model/SimilarityChecker.java @@ -79,8 +79,8 @@ public static float compare(MethodInstance a, MethodInstance b) { float contentScore = 0; int[] insnMap = ClassifierUtil.mapInsns(a, b); - for (int i = 0; i < insnMap.length; i++) { - if (insnMap[i] >= 0) contentScore++; + for (int i : insnMap) { + if (i >= 0) contentScore++; } div = Math.max(insnMap.length, b.getAsmNode().instructions.size()); @@ -101,9 +101,12 @@ public static float compare(MethodVarInstance a, MethodVarInstance b) { return ClassifierUtil.checkPotentialEquality(a.getType(), b.getType()) ? 1 : SIMILARITY_MATCHED_TYPE_MISMATCH; } - private static final float SIMILARITY_MATCHED_TYPE_MISMATCH = 0.5f; + private SimilarityChecker() { + } + + private static final float SIMILARITY_MATCHED_TYPE_MISMATCH = 0.5F; - private static final float METHOD_RETTYPE_WEIGHT = 0.05f; - private static final float METHOD_ARGS_WEIGHT = 0.2f; + private static final float METHOD_RETTYPE_WEIGHT = 0.05F; + private static final float METHOD_ARGS_WEIGHT = 0.2F; private static final float METHOD_CONTENT_WEIGHT = 1 - METHOD_RETTYPE_WEIGHT - METHOD_ARGS_WEIGHT; } diff --git a/matcher-model/src/main/java/matcher/model/Util.java b/matcher-model/src/main/java/matcher/model/Util.java index 9011d76d..47716ffe 100644 --- a/matcher-model/src/main/java/matcher/model/Util.java +++ b/matcher-model/src/main/java/matcher/model/Util.java @@ -33,16 +33,16 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class Util { +public final class Util { public static Set newIdentityHashSet() { - return Collections.newSetFromMap(new IdentityHashMap<>()); //new IdentityHashSet<>(); + return Collections.newSetFromMap(new IdentityHashMap<>()); // new IdentityHashSet<>(); } public static Set newIdentityHashSet(Collection c) { Set ret = Collections.newSetFromMap(new IdentityHashMap<>(c.size())); ret.addAll(c); - return ret; //new IdentityHashSet<>(c); + return ret; // new IdentityHashSet<>(c); } public static Set copySet(Set set) { @@ -67,7 +67,7 @@ public static FileSystem iterateJar(Path archive, boolean autoClose, Consumer() { + Files.walkFileTree(fs.getPath("/"), new SimpleFileVisitor<>() { @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { if (file.toString().endsWith(".class")) { handler.accept(file); } @@ -117,10 +117,10 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO } private static synchronized void autoCloseFs(FileSystem fs) { - AtomicInteger count = usedFsMap.get(fs); + AtomicInteger count = USED_FS_MAP.get(fs); if (count.decrementAndGet() == 0) { - usedFsMap.remove(fs); + USED_FS_MAP.remove(fs); closeSilently(fs); } } @@ -132,7 +132,7 @@ public static boolean clearDir(Path path, Predicate disallowed) throws IOE AtomicBoolean ret = new AtomicBoolean(true); - Files.walkFileTree(path, new SimpleFileVisitor() { + Files.walkFileTree(path, new SimpleFileVisitor<>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if (disallowed.test(file)) { @@ -189,14 +189,14 @@ public static String formatAccessFlags(int access, AFElementType type) { int assoc = type.assoc; StringBuilder sb = new StringBuilder(); - for (int i = 0; i < accessFlags.length; i++) { - if ((accessAssoc[i] & assoc) == 0) continue; - if ((access & accessFlags[i]) == 0) continue; + for (int i = 0; i < ACCESS_FLAGS.length; i++) { + if ((ACCESS_ASSOC[i] & assoc) == 0) continue; + if ((access & ACCESS_FLAGS[i]) == 0) continue; if (sb.length() != 0) sb.append(' '); - sb.append(accessNames[i]); + sb.append(ACCESS_NAMES[i]); - access &= ~accessFlags[i]; + access &= ~ACCESS_FLAGS[i]; } if (access != 0) { @@ -218,15 +218,15 @@ public enum AFElementType { final int assoc; } - private static final int[] accessFlags = new int[] { Opcodes.ACC_PUBLIC, Opcodes.ACC_PRIVATE, Opcodes.ACC_PROTECTED, Opcodes.ACC_STATIC, + private static final int[] ACCESS_FLAGS = new int[] { Opcodes.ACC_PUBLIC, Opcodes.ACC_PRIVATE, Opcodes.ACC_PROTECTED, Opcodes.ACC_STATIC, Opcodes.ACC_FINAL, Opcodes.ACC_SUPER, Opcodes.ACC_SYNCHRONIZED, Opcodes.ACC_VOLATILE, Opcodes.ACC_BRIDGE, Opcodes.ACC_VARARGS, Opcodes.ACC_TRANSIENT, Opcodes.ACC_NATIVE, Opcodes.ACC_INTERFACE, Opcodes.ACC_ABSTRACT, Opcodes.ACC_STRICT, Opcodes.ACC_SYNTHETIC, Opcodes.ACC_ANNOTATION, Opcodes.ACC_ENUM, Opcodes.ACC_MANDATED }; - private static final String[] accessNames = new String[] { "public", "private", "protected", "static", + private static final String[] ACCESS_NAMES = new String[] { "public", "private", "protected", "static", "final", "super", "synchronized", "volatile", "bridge", "varargs", "transient", "native", "interface", "abstract", "strict", "synthetic", "annotation", "enum", "mandated" }; - private static final byte[] accessAssoc = new byte[] { 7, 7, 7, 6, + private static final byte[] ACCESS_ASSOC = new byte[] { 7, 7, 7, 6, 15, 1, 2, 4, 2, 2, 4, 2, 1, 3, 2, 15, 1, 21, 8 }; @@ -237,7 +237,7 @@ public static Handle getTargetHandle(Handle bsm, Object[] bsmArgs) { } else if (isIrrelevantBsm(bsm)) { return null; } else { - logger.warn("Unknown invokedynamic bsm: {}/{}{} (tag={} iif={})", + LOGGER.warn("Unknown invokedynamic bsm: {}/{}{} (tag={} iif={})", bsm.getOwner(), bsm.getName(), bsm.getDesc(), bsm.getTag(), bsm.isInterface()); return null; @@ -298,7 +298,7 @@ public static int compareNatural(String a, String b) { int endA = -1; int endB = -1; - for (;;) { + while (true) { int startA = posA; boolean isNumA = false; @@ -397,7 +397,11 @@ public static int compareNatural(String a, String b) { } } - private static final Logger logger = LoggerFactory.getLogger(Util.class); - private static final Map usedFsMap = new IdentityHashMap<>(); - public static final Object asmNodeSync = new Object(); + private Util() { + } + + private static final Logger LOGGER = LoggerFactory.getLogger(Util.class); + private static final Map USED_FS_MAP = new IdentityHashMap<>(); + public static final Object ASM_NODE_SYNC = new Object(); + public static final int ASM_API_VERSION = Opcodes.ASM9; } diff --git a/matcher-model/src/main/java/matcher/model/bcremap/AsmClassRemapper.java b/matcher-model/src/main/java/matcher/model/bcremap/AsmClassRemapper.java index d67bbc09..dbb0db03 100644 --- a/matcher-model/src/main/java/matcher/model/bcremap/AsmClassRemapper.java +++ b/matcher-model/src/main/java/matcher/model/bcremap/AsmClassRemapper.java @@ -17,7 +17,7 @@ import matcher.model.Util; -public class AsmClassRemapper extends ClassRemapper { +public final class AsmClassRemapper extends ClassRemapper { public static void process(ClassNode source, AsmRemapper remapper, ClassVisitor sink) { source.accept(new AsmClassRemapper(sink, remapper)); } @@ -296,13 +296,13 @@ private void checkState() { } protected final AsmRemapper remapper; + protected final Map labels = new IdentityHashMap<>(); protected int insnIndex; - protected Map labels = new IdentityHashMap<>(); private int argsVisited; } - protected final AsmRemapper remapper; - protected String methodName; - protected String methodDesc; + private final AsmRemapper remapper; + private String methodName; + private String methodDesc; } diff --git a/matcher-model/src/main/java/matcher/model/bcremap/AsmRemapper.java b/matcher-model/src/main/java/matcher/model/bcremap/AsmRemapper.java index c4697aef..50389070 100644 --- a/matcher-model/src/main/java/matcher/model/bcremap/AsmRemapper.java +++ b/matcher-model/src/main/java/matcher/model/bcremap/AsmRemapper.java @@ -3,6 +3,7 @@ import org.objectweb.asm.commons.Remapper; import matcher.model.NameType; +import matcher.model.Util; import matcher.model.type.ClassEnv; import matcher.model.type.ClassInstance; import matcher.model.type.FieldInstance; @@ -11,6 +12,8 @@ public class AsmRemapper extends Remapper { public AsmRemapper(ClassEnv env, NameType nameType) { + super(Util.ASM_API_VERSION); + this.env = env; this.nameType = nameType; } @@ -46,7 +49,7 @@ public String mapMethodName(String owner, String name, String desc) { MethodInstance method = cls.getMethod(name, desc); if (method == null) { - assert false : String.format("can't find method %s%s in %s", name, desc, cls);; + assert false : String.format("can't find method %s%s in %s", name, desc, cls); return name; } diff --git a/matcher-model/src/main/java/matcher/model/classifier/ClassClassifier.java b/matcher-model/src/main/java/matcher/model/classifier/ClassClassifier.java index a6c558f6..4646cd55 100644 --- a/matcher-model/src/main/java/matcher/model/classifier/ClassClassifier.java +++ b/matcher-model/src/main/java/matcher/model/classifier/ClassClassifier.java @@ -24,31 +24,31 @@ import matcher.model.type.MethodVarInstance; import matcher.model.type.Signature.ClassSignature; -public class ClassClassifier { +public final class ClassClassifier { public static void init() { - addClassifier(classTypeCheck, 20); - addClassifier(signature, 5); - addClassifier(hierarchyDepth, 1); - addClassifier(parentClass, 4); - addClassifier(childClasses, 3); - addClassifier(interfaces, 3); - addClassifier(implementers, 2); - addClassifier(outerClass, 6); - addClassifier(innerClasses, 5); - addClassifier(methodCount, 3); - addClassifier(fieldCount, 3); - addClassifier(hierarchySiblings, 2); - addClassifier(similarMethods, 10); - addClassifier(outReferences, 6); - addClassifier(inReferences, 6); - addClassifier(stringConstants, 8); - addClassifier(numericConstants, 6); - addClassifier(methodOutReferences, 5, ClassifierLevel.Intermediate, ClassifierLevel.Full, ClassifierLevel.Extra); - addClassifier(methodInReferences, 6, ClassifierLevel.Intermediate, ClassifierLevel.Full, ClassifierLevel.Extra); - addClassifier(fieldReadReferences, 5, ClassifierLevel.Intermediate, ClassifierLevel.Full, ClassifierLevel.Extra); - addClassifier(fieldWriteReferences, 5, ClassifierLevel.Intermediate, ClassifierLevel.Full, ClassifierLevel.Extra); - addClassifier(membersFull, 10, ClassifierLevel.Full, ClassifierLevel.Extra); - addClassifier(inRefsBci, 6, ClassifierLevel.Extra); + addClassifier(CLASS_TYPE_CHECK, 20); + addClassifier(SIGNATURE, 5); + addClassifier(HIERARCHY_DEPTH, 1); + addClassifier(PARENT_CLASS, 4); + addClassifier(CHILD_CLASSES, 3); + addClassifier(INTERFACES, 3); + addClassifier(IMPLEMENTERS, 2); + addClassifier(OUTER_CLASS, 6); + addClassifier(INNER_CLASSES, 5); + addClassifier(METHOD_COUNT, 3); + addClassifier(FIELD_COUNT, 3); + addClassifier(HIERARCHY_SIBLINGS, 2); + addClassifier(SIMILAR_METHODS, 10); + addClassifier(OUT_REFERENCES, 6); + addClassifier(IN_REFERENCES, 6); + addClassifier(STRING_CONSTANTS, 8); + addClassifier(NUMERIC_CONSTANTS, 6); + addClassifier(METHOD_OUT_REFERENCES, 5, ClassifierLevel.Intermediate, ClassifierLevel.Full, ClassifierLevel.Extra); + addClassifier(METHOD_IN_REFERENCES, 6, ClassifierLevel.Intermediate, ClassifierLevel.Full, ClassifierLevel.Extra); + addClassifier(FIELD_READ_REFERENCES, 5, ClassifierLevel.Intermediate, ClassifierLevel.Full, ClassifierLevel.Extra); + addClassifier(FIELD_WRITE_REFERENCES, 5, ClassifierLevel.Intermediate, ClassifierLevel.Full, ClassifierLevel.Extra); + addClassifier(MEMBERS_FULL, 10, ClassifierLevel.Full, ClassifierLevel.Extra); + addClassifier(IN_REFS_BCI, 6, ClassifierLevel.Extra); } public static void addClassifier(AbstractClassifier classifier, double weight, ClassifierLevel... levels) { @@ -57,40 +57,40 @@ public static void addClassifier(AbstractClassifier classifier, double weight, C classifier.weight = weight; for (ClassifierLevel level : levels) { - classifiers.computeIfAbsent(level, ignore -> new ArrayList<>()).add(classifier); - maxScore.put(level, getMaxScore(level) + weight); + CLASSIFIERS.computeIfAbsent(level, ignore -> new ArrayList<>()).add(classifier); + MAX_SCORE.put(level, getMaxScore(level) + weight); } } public static double getMaxScore(ClassifierLevel level) { - return maxScore.getOrDefault(level, 0.); + return MAX_SCORE.getOrDefault(level, 0.); } public static List> rank(ClassInstance src, ClassInstance[] dsts, ClassifierLevel level, ClassEnvironment env, double maxMismatch) { - return ClassifierUtil.rank(src, dsts, classifiers.getOrDefault(level, Collections.emptyList()), ClassifierUtil::checkPotentialEquality, env, maxMismatch); + return ClassifierUtil.rank(src, dsts, CLASSIFIERS.getOrDefault(level, Collections.emptyList()), ClassifierUtil::checkPotentialEquality, env, maxMismatch); } public static List> rankParallel(ClassInstance src, ClassInstance[] dsts, ClassifierLevel level, ClassEnvironment env, double maxMismatch) { - return ClassifierUtil.rankParallel(src, dsts, classifiers.getOrDefault(level, Collections.emptyList()), ClassifierUtil::checkPotentialEquality, env, maxMismatch); + return ClassifierUtil.rankParallel(src, dsts, CLASSIFIERS.getOrDefault(level, Collections.emptyList()), ClassifierUtil::checkPotentialEquality, env, maxMismatch); } - private static final Map>> classifiers = new EnumMap<>(ClassifierLevel.class); - private static final Map maxScore = new EnumMap<>(ClassifierLevel.class); + private static final Map>> CLASSIFIERS = new EnumMap<>(ClassifierLevel.class); + private static final Map MAX_SCORE = new EnumMap<>(ClassifierLevel.class); - private static AbstractClassifier classTypeCheck = new AbstractClassifier("class type check") { + private static final AbstractClassifier CLASS_TYPE_CHECK = new AbstractClassifier("class type check") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { int mask = Opcodes.ACC_ENUM | Opcodes.ACC_INTERFACE | Opcodes.ACC_ANNOTATION | Opcodes.ACC_RECORD | Opcodes.ACC_ABSTRACT; int resultA = clsA.getAccess() & mask; int resultB = clsB.getAccess() & mask; - //assert Integer.bitCount(resultA) <= 3 && Integer.bitCount(resultB) <= 3; + // assert Integer.bitCount(resultA) <= 3 && Integer.bitCount(resultB) <= 3; return 1 - Integer.bitCount(resultA ^ resultB) / 5.; } }; - private static AbstractClassifier signature = new AbstractClassifier("signature") { + private static final AbstractClassifier SIGNATURE = new AbstractClassifier("signature") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { ClassSignature sigA = clsA.getSignature(); @@ -103,7 +103,7 @@ public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment } }; - private static AbstractClassifier hierarchyDepth = new AbstractClassifier("hierarchy depth") { + private static final AbstractClassifier HIERARCHY_DEPTH = new AbstractClassifier("hierarchy depth") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { int countA = 0; @@ -123,14 +123,14 @@ public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment } }; - private static AbstractClassifier hierarchySiblings = new AbstractClassifier("hierarchy siblings") { + private static final AbstractClassifier HIERARCHY_SIBLINGS = new AbstractClassifier("hierarchy siblings") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { return ClassifierUtil.compareCounts(clsA.getSuperClass().getChildClasses().size(), clsB.getSuperClass().getChildClasses().size()); } }; - private static AbstractClassifier parentClass = new AbstractClassifier("parent class") { + private static final AbstractClassifier PARENT_CLASS = new AbstractClassifier("parent class") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { if (clsA.getSuperClass() == null && clsB.getSuperClass() == null) return 1; @@ -140,28 +140,28 @@ public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment } }; - private static AbstractClassifier childClasses = new AbstractClassifier("child classes") { + private static final AbstractClassifier CHILD_CLASSES = new AbstractClassifier("child classes") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { return ClassifierUtil.compareClassSets(clsA.getChildClasses(), clsB.getChildClasses(), true); } }; - private static AbstractClassifier interfaces = new AbstractClassifier("interfaces") { + private static final AbstractClassifier INTERFACES = new AbstractClassifier("interfaces") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { return ClassifierUtil.compareClassSets(clsA.getInterfaces(), clsB.getInterfaces(), true); } }; - private static AbstractClassifier implementers = new AbstractClassifier("implementers") { + private static final AbstractClassifier IMPLEMENTERS = new AbstractClassifier("implementers") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { return ClassifierUtil.compareClassSets(clsA.getImplementers(), clsB.getImplementers(), true); } }; - private static AbstractClassifier outerClass = new AbstractClassifier("outer class") { + private static final AbstractClassifier OUTER_CLASS = new AbstractClassifier("outer class") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { ClassInstance outerA = clsA.getOuterClass(); @@ -174,7 +174,7 @@ public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment } }; - private static AbstractClassifier innerClasses = new AbstractClassifier("inner classes") { + private static final AbstractClassifier INNER_CLASSES = new AbstractClassifier("inner classes") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { Set innerA = clsA.getInnerClasses(); @@ -187,21 +187,21 @@ public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment } }; - private static AbstractClassifier methodCount = new AbstractClassifier("method count") { + private static final AbstractClassifier METHOD_COUNT = new AbstractClassifier("method count") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { return ClassifierUtil.compareCounts(clsA.getMethods().length, clsB.getMethods().length); } }; - private static AbstractClassifier fieldCount = new AbstractClassifier("field count") { + private static final AbstractClassifier FIELD_COUNT = new AbstractClassifier("field count") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { return ClassifierUtil.compareCounts(clsA.getFields().length, clsB.getFields().length); } }; - private static AbstractClassifier similarMethods = new AbstractClassifier("similar methods") { + private static final AbstractClassifier SIMILAR_METHODS = new AbstractClassifier("similar methods") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { if (clsA.getMethods().length == 0 && clsB.getMethods().length == 0) return 1; @@ -258,7 +258,7 @@ public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment } }; - private static AbstractClassifier outReferences = new AbstractClassifier("out references") { + private static final AbstractClassifier OUT_REFERENCES = new AbstractClassifier("out references") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { Set refsA = getOutRefs(clsA); @@ -282,7 +282,7 @@ private static Set getOutRefs(ClassInstance cls) { return ret; } - private static AbstractClassifier inReferences = new AbstractClassifier("in references") { + private static final AbstractClassifier IN_REFERENCES = new AbstractClassifier("in references") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { Set refsA = getInRefs(clsA); @@ -306,7 +306,7 @@ private static Set getInRefs(ClassInstance cls) { return ret; } - private static AbstractClassifier methodOutReferences = new AbstractClassifier("method out references") { + private static final AbstractClassifier METHOD_OUT_REFERENCES = new AbstractClassifier("method out references") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { Set refsA = getMethodOutRefs(clsA); @@ -326,7 +326,7 @@ private static Set getMethodOutRefs(ClassInstance cls) { return ret; } - private static AbstractClassifier methodInReferences = new AbstractClassifier("method in references") { + private static final AbstractClassifier METHOD_IN_REFERENCES = new AbstractClassifier("method in references") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { Set refsA = getMethodInRefs(clsA); @@ -346,7 +346,7 @@ private static Set getMethodInRefs(ClassInstance cls) { return ret; } - private static AbstractClassifier fieldReadReferences = new AbstractClassifier("field read references") { + private static final AbstractClassifier FIELD_READ_REFERENCES = new AbstractClassifier("field read references") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { Set refsA = getFieldReadRefs(clsA); @@ -366,7 +366,7 @@ private static Set getFieldReadRefs(ClassInstance cls) { return ret; } - private static AbstractClassifier fieldWriteReferences = new AbstractClassifier("field write references") { + private static final AbstractClassifier FIELD_WRITE_REFERENCES = new AbstractClassifier("field write references") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { Set refsA = getFieldWriteRefs(clsA); @@ -386,14 +386,14 @@ private static Set getFieldWriteRefs(ClassInstance cls) { return ret; } - private static AbstractClassifier stringConstants = new AbstractClassifier("string constants") { + private static final AbstractClassifier STRING_CONSTANTS = new AbstractClassifier("string constants") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { return ClassifierUtil.compareSets(clsA.getStrings(), clsB.getStrings(), true); } }; - private static AbstractClassifier numericConstants = new AbstractClassifier("numeric constants") { + private static final AbstractClassifier NUMERIC_CONSTANTS = new AbstractClassifier("numeric constants") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { Set intsA = new HashSet<>(); @@ -415,11 +415,11 @@ public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment } }; - private static AbstractClassifier membersFull = new AbstractClassifier("members full") { + private static final AbstractClassifier MEMBERS_FULL = new AbstractClassifier("members full") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { /*if (clsA.getName().equals("agl") && clsB.getName().equals("aht")) { - Matcher.LOGGER.info(); + LOGGER.info(); }*/ final double absThreshold = 0.8; @@ -462,7 +462,7 @@ public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment } }; - private static AbstractClassifier inRefsBci = new AbstractClassifier("in refs (bci)") { + private static final AbstractClassifier IN_REFS_BCI = new AbstractClassifier("in refs (bci)") { @Override public double getScore(ClassInstance clsA, ClassInstance clsB, ClassEnvironment env) { int matched = 0; @@ -532,7 +532,7 @@ private static void extractNumbers(ClassInstance cls, Set ints, Set { - public AbstractClassifier(String name) { + protected AbstractClassifier(String name) { this.name = name; } @@ -549,4 +549,7 @@ public double getWeight() { private final String name; private double weight; } + + private ClassClassifier() { + } } diff --git a/matcher-model/src/main/java/matcher/model/classifier/ClassifierUtil.java b/matcher-model/src/main/java/matcher/model/classifier/ClassifierUtil.java index 6f4feed4..35f9667d 100644 --- a/matcher-model/src/main/java/matcher/model/classifier/ClassifierUtil.java +++ b/matcher-model/src/main/java/matcher/model/classifier/ClassifierUtil.java @@ -50,7 +50,7 @@ import matcher.model.type.MethodType; import matcher.model.type.MethodVarInstance; -public class ClassifierUtil { +public final class ClassifierUtil { public static boolean checkPotentialEquality(ClassInstance a, ClassInstance b) { if (a == b) return true; if (a.getMatch() != null) return a.getMatch() == b; @@ -93,8 +93,8 @@ public static boolean checkPotentialEquality(MethodInstance a, MethodInstance b) if (!checkNameObfMatch(a, b)) return false; if ((a.getId().startsWith("<") || b.getId().startsWith("<")) && !a.getName().equals(b.getName())) return false; // require and to match - //MethodInstance hierarchyMatch = a.getHierarchyMatch(); - //if (hierarchyMatch != null && !hierarchyMatch.getAllHierarchyMembers().contains(b)) return false; + // MethodInstance hierarchyMatch = a.getHierarchyMatch(); + // if (hierarchyMatch != null && !hierarchyMatch.getAllHierarchyMembers().contains(b)) return false; if ((a.hasHierarchyMatch() || b.hasHierarchyMatch()) && !a.hasMatchedHierarchy(b)) return false; if (a.getType() == MethodType.LAMBDA_IMPL && b.getType() == MethodType.LAMBDA_IMPL) { // require same "outer method" for lambdas @@ -290,11 +290,11 @@ public static double compareInsns(MethodInstance a, MethodInstance b) { InsnList ilA = a.getAsmNode().instructions; InsnList ilB = b.getAsmNode().instructions; - return compareLists(ilA, ilB, InsnList::get, InsnList::size, (inA, inB) -> compareInsns(inA, inB, ilA, ilB, (list, item) -> list.indexOf(item), a, b, a.getEnv().getGlobal())); + return compareLists(ilA, ilB, InsnList::get, InsnList::size, (inA, inB) -> compareInsns(inA, inB, ilA, ilB, InsnList::indexOf, a, b, a.getEnv().getGlobal())); } public static double compareInsns(List listA, List listB, ClassEnvironment env) { - return compareLists(listA, listB, List::get, List::size, (inA, inB) -> compareInsns(inA, inB, listA, listB, (list, item) -> list.indexOf(item), null, null, env)); + return compareLists(listA, listB, List::get, List::size, (inA, inB) -> compareInsns(inA, inB, listA, listB, List::indexOf, null, null, env)); } private static int compareInsns(AbstractInsnNode insnA, AbstractInsnNode insnB, T listA, T listB, ToIntBiFunction posProvider, @@ -379,10 +379,10 @@ private static int compareInsns(AbstractInsnNode insnA, AbstractInsnNode ins implB.getOwner(), implB.getName(), implB.getDesc(), Util.isCallToInterface(implB), env) ? COMPARED_SIMILAR : COMPARED_DISTINCT; default: - logger.warn("Unexpected impl tag: {}", implA.getTag()); + LOGGER.warn("Unexpected impl tag: {}", implA.getTag()); } } else if (!Util.isIrrelevantBsm(a.bsm)) { - logger.warn("Unknown invokedynamic bsm: {}/{}{} (tag={} iif={})", + LOGGER.warn("Unknown invokedynamic bsm: {}/{}{} (tag={} iif={})", a.bsm.getOwner(), a.bsm.getName(), a.bsm.getDesc(), a.bsm.getTag(), a.bsm.isInterface()); } @@ -539,9 +539,7 @@ private static double compareLists(T listA, T listB, ListElementRetriever v1[j + 1] = Math.min(Math.min(v1[j] + COMPARED_DISTINCT, v0[j + 1] + COMPARED_DISTINCT), v0[j] + cost); } - for (int j = 0; j < v0.length; j++) { - v0[j] = v1[j]; - } + System.arraycopy(v1, 0, v0, 0, v0.length); } int distance = v1[sizeB]; @@ -560,12 +558,12 @@ public static int[] mapInsns(MethodInstance a, MethodInstance b) { if (ilA.size() * ilB.size() < 1000) { return mapInsns(ilA, ilB, a, b, a.getEnv().getGlobal()); } else { - return a.getEnv().getGlobal().getCache().compute(ilMapCacheToken, a, b, (mA, mB) -> mapInsns(mA.getAsmNode().instructions, mB.getAsmNode().instructions, mA, mB, mA.getEnv().getGlobal())); + return a.getEnv().getGlobal().getCache().compute(IL_MAP_CACHE_TOKEN, a, b, (mA, mB) -> mapInsns(mA.getAsmNode().instructions, mB.getAsmNode().instructions, mA, mB, mA.getEnv().getGlobal())); } } public static int[] mapInsns(InsnList listA, InsnList listB, MethodInstance mthA, MethodInstance mthB, ClassEnvironment env) { - return mapLists(listA, listB, InsnList::get, InsnList::size, (inA, inB) -> compareInsns(inA, inB, listA, listB, (list, item) -> list.indexOf(item), mthA, mthB, env)); + return mapLists(listA, listB, InsnList::get, InsnList::size, (inA, inB) -> compareInsns(inA, inB, listA, listB, InsnList::indexOf, mthA, mthB, env)); } private static int[] mapLists(T listA, T listB, ListElementRetriever elementRetriever, ListSizeRetriever sizeRetriever, ElementComparator elementComparator) { @@ -625,15 +623,15 @@ private static int[] mapLists(T listA, T listB, ListElementRetriever 0 || j > 0) { int c = v[i + j * size]; @@ -644,10 +642,10 @@ private static int[] mapLists(T listA, T listB, ListElementRetriever= COMPARED_DISTINCT) { assert c - keepCost == COMPARED_DISTINCT; - //logger.debug("{}/{} rep {} -> {}", i-1, j-1, toString(elementRetriever.apply(listA, i - 1)), toString(elementRetriever.apply(listB, j - 1))); + // LOGGER.debug("{}/{} rep {} -> {}", i-1, j-1, toString(elementRetriever.apply(listA, i - 1)), toString(elementRetriever.apply(listB, j - 1))); ret[i - 1] = -1; } else { - //logger.debug("{}/{} eq {} - {}", i-1, j-1, toString(elementRetriever.apply(listA, i - 1)), toString(elementRetriever.apply(listB, j - 1))); + // LOGGER.debug("{}/{} eq {} - {}", i-1, j-1, toString(elementRetriever.apply(listA, i - 1)), toString(elementRetriever.apply(listB, j - 1))); ret[i - 1] = j - 1; /*U e = elementRetriever.apply(listA, i - 1); @@ -661,11 +659,11 @@ private static int[] mapLists(T listA, T listB, ListElementRetriever> RankResult rank(T src, T dst, Collect for (IClassifier classifier : classifiers) { double cScore = classifier.getScore(src, dst, env); - assert cScore > -epsilon && cScore < 1 + epsilon : "invalid score from "+classifier.getName()+": "+cScore; + assert cScore > -EPSILON && cScore < 1 + EPSILON : "invalid score from "+classifier.getName()+": "+cScore; double weight = classifier.getWeight(); double weightedScore = cScore * weight; @@ -802,9 +800,7 @@ private static void extractStrings(Iterator it, Set ou } public static void extractNumbers(MethodNode node, Set ints, Set longs, Set floats, Set doubles) { - for (Iterator it = node.instructions.iterator(); it.hasNext(); ) { - AbstractInsnNode aInsn = it.next(); - + for (AbstractInsnNode aInsn : node.instructions) { if (aInsn instanceof LdcInsnNode) { LdcInsnNode insn = (LdcInsnNode) aInsn; @@ -896,8 +892,10 @@ private static double getRelativePosition(int position, int size) { return (double) position / (size - 1); } - private static final double epsilon = 1e-6; + private ClassifierUtil() { + } - private static final Logger logger = LoggerFactory.getLogger(ClassifierUtil.class); - private static final CacheToken ilMapCacheToken = new CacheToken<>(); + private static final double EPSILON = 1e-6; + private static final Logger LOGGER = LoggerFactory.getLogger(ClassifierUtil.class); + private static final CacheToken IL_MAP_CACHE_TOKEN = new CacheToken<>(); } diff --git a/matcher-model/src/main/java/matcher/model/classifier/FieldClassifier.java b/matcher-model/src/main/java/matcher/model/classifier/FieldClassifier.java index 5ac90387..7c2b58c2 100644 --- a/matcher-model/src/main/java/matcher/model/classifier/FieldClassifier.java +++ b/matcher-model/src/main/java/matcher/model/classifier/FieldClassifier.java @@ -21,20 +21,20 @@ import matcher.model.type.MethodInstance; import matcher.model.type.Signature.FieldSignature; -public class FieldClassifier { +public final class FieldClassifier { public static void init() { - addClassifier(fieldTypeCheck, 10); - addClassifier(accessFlags, 4); - addClassifier(type, 10); - addClassifier(signature, 5); - addClassifier(readReferences, 6); - addClassifier(writeReferences, 6); - addClassifier(position, 3); - addClassifier(initValue, 7); - addClassifier(initStrings, 8); - addClassifier(initCode, 10, ClassifierLevel.Intermediate, ClassifierLevel.Full, ClassifierLevel.Extra); - addClassifier(readRefsBci, 6, ClassifierLevel.Extra); - addClassifier(writeRefsBci, 6, ClassifierLevel.Extra); + addClassifier(FIELD_TYPE_CHECK, 10); + addClassifier(ACCESS_FLAGS, 4); + addClassifier(TYPE, 10); + addClassifier(SIGNATURE, 5); + addClassifier(READ_REFERENCES, 6); + addClassifier(WRITE_REFERENCES, 6); + addClassifier(POSITION, 3); + addClassifier(INIT_VALUE, 7); + addClassifier(INIT_STRINGS, 8); + addClassifier(INIT_CODE, 10, ClassifierLevel.Intermediate, ClassifierLevel.Full, ClassifierLevel.Extra); + addClassifier(READ_REFS_BCI, 6, ClassifierLevel.Extra); + addClassifier(WRITE_REFS_BCI, 6, ClassifierLevel.Extra); } public static void addClassifier(AbstractClassifier classifier, double weight, ClassifierLevel... levels) { @@ -43,13 +43,13 @@ public static void addClassifier(AbstractClassifier classifier, double weight, C classifier.weight = weight; for (ClassifierLevel level : levels) { - classifiers.computeIfAbsent(level, ignore -> new ArrayList<>()).add(classifier); - maxScore.put(level, getMaxScore(level) + weight); + CLASSIFIERS.computeIfAbsent(level, ignore -> new ArrayList<>()).add(classifier); + MAX_SCORE.put(level, getMaxScore(level) + weight); } } public static double getMaxScore(ClassifierLevel level) { - return maxScore.getOrDefault(level, 0.); + return MAX_SCORE.getOrDefault(level, 0.); } public static List> rank(FieldInstance src, FieldInstance[] dsts, ClassifierLevel level, ClassEnvironment env) { @@ -57,13 +57,13 @@ public static List> rank(FieldInstance src, FieldInsta } public static List> rank(FieldInstance src, FieldInstance[] dsts, ClassifierLevel level, ClassEnvironment env, double maxMismatch) { - return ClassifierUtil.rank(src, dsts, classifiers.getOrDefault(level, Collections.emptyList()), ClassifierUtil::checkPotentialEquality, env, maxMismatch); + return ClassifierUtil.rank(src, dsts, CLASSIFIERS.getOrDefault(level, Collections.emptyList()), ClassifierUtil::checkPotentialEquality, env, maxMismatch); } - private static final Map>> classifiers = new IdentityHashMap<>(); - private static final Map maxScore = new EnumMap<>(ClassifierLevel.class); + private static final Map>> CLASSIFIERS = new IdentityHashMap<>(); + private static final Map MAX_SCORE = new EnumMap<>(ClassifierLevel.class); - private static AbstractClassifier fieldTypeCheck = new AbstractClassifier("field type check") { + private static final AbstractClassifier FIELD_TYPE_CHECK = new AbstractClassifier("field type check") { @Override public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironment env) { if (!checkAsmNodes(fieldA, fieldB)) return compareAsmNodes(fieldA, fieldB); @@ -76,7 +76,7 @@ public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironm } }; - private static AbstractClassifier accessFlags = new AbstractClassifier("access flags") { + private static final AbstractClassifier ACCESS_FLAGS = new AbstractClassifier("access flags") { @Override public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironment env) { if (!checkAsmNodes(fieldA, fieldB)) return compareAsmNodes(fieldA, fieldB); @@ -89,14 +89,14 @@ public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironm } }; - private static AbstractClassifier type = new AbstractClassifier("types") { + private static final AbstractClassifier TYPE = new AbstractClassifier("types") { @Override public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironment env) { return ClassifierUtil.checkPotentialEquality(fieldA.getType(), fieldB.getType()) ? 1 : 0; } }; - private static AbstractClassifier signature = new AbstractClassifier("signature") { + private static final AbstractClassifier SIGNATURE = new AbstractClassifier("signature") { @Override public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironment env) { FieldSignature sigA = fieldA.getSignature(); @@ -109,21 +109,21 @@ public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironm } }; - private static AbstractClassifier readReferences = new AbstractClassifier("read references") { + private static final AbstractClassifier READ_REFERENCES = new AbstractClassifier("read references") { @Override public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironment env) { return ClassifierUtil.compareMethodSets(fieldA.getReadRefs(), fieldB.getReadRefs(), true); } }; - private static AbstractClassifier writeReferences = new AbstractClassifier("write references") { + private static final AbstractClassifier WRITE_REFERENCES = new AbstractClassifier("write references") { @Override public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironment env) { return ClassifierUtil.compareMethodSets(fieldA.getWriteRefs(), fieldB.getWriteRefs(), true); } }; - private static AbstractClassifier position = new AbstractClassifier("position") { + private static final AbstractClassifier POSITION = new AbstractClassifier("position") { @Override public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironment env) { /*if (fieldA.position == fieldB.position) return 1; @@ -136,7 +136,7 @@ public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironm } }; - private static AbstractClassifier initValue = new AbstractClassifier("init value") { + private static final AbstractClassifier INIT_VALUE = new AbstractClassifier("init value") { @Override public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironment env) { if (!checkAsmNodes(fieldA, fieldB)) return compareAsmNodes(fieldA, fieldB); @@ -151,7 +151,7 @@ public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironm } }; - private static AbstractClassifier initStrings = new AbstractClassifier("init strings") { + private static final AbstractClassifier INIT_STRINGS = new AbstractClassifier("init strings") { @Override public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironment env) { List initA = fieldA.getInitializer(); @@ -169,7 +169,7 @@ public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironm } }; - private static AbstractClassifier initCode = new AbstractClassifier("init code") { + private static final AbstractClassifier INIT_CODE = new AbstractClassifier("init code") { @Override public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironment env) { List initA = fieldA.getInitializer(); @@ -182,7 +182,7 @@ public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironm } }; - private static AbstractClassifier readRefsBci = new AbstractClassifier("read refs (bci)") { + private static final AbstractClassifier READ_REFS_BCI = new AbstractClassifier("read refs (bci)") { @Override public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironment env) { String ownerA = fieldA.getCls().getName(); @@ -237,7 +237,7 @@ public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironm } }; - private static AbstractClassifier writeRefsBci = new AbstractClassifier("write refs (bci)") { + private static final AbstractClassifier WRITE_REFS_BCI = new AbstractClassifier("write refs (bci)") { @Override public double getScore(FieldInstance fieldA, FieldInstance fieldB, ClassEnvironment env) { String ownerA = fieldA.getCls().getName(); @@ -309,7 +309,7 @@ private static double compareAsmNodes(FieldInstance a, FieldInstance b) { } public abstract static class AbstractClassifier implements IClassifier { - public AbstractClassifier(String name) { + protected AbstractClassifier(String name) { this.name = name; } @@ -326,4 +326,7 @@ public double getWeight() { private final String name; private double weight; } + + private FieldClassifier() { + } } diff --git a/matcher-model/src/main/java/matcher/model/classifier/MatchingCache.java b/matcher-model/src/main/java/matcher/model/classifier/MatchingCache.java index e2674a0a..39626eb8 100644 --- a/matcher-model/src/main/java/matcher/model/classifier/MatchingCache.java +++ b/matcher-model/src/main/java/matcher/model/classifier/MatchingCache.java @@ -9,12 +9,12 @@ public class MatchingCache { @SuppressWarnings("unchecked") public > T get(CacheToken token, U a, U b) { - return (T) cache.get(new CacheKey(token, a, b)); + return (T) cache.get(new CacheKey<>(token, a, b)); } @SuppressWarnings("unchecked") public > T compute(CacheToken token, U a, U b, BiFunction f) { - return (T) cache.computeIfAbsent(new CacheKey(token, a, b), k -> f.apply((U) k.a, (U) k.b)); + return (T) cache.computeIfAbsent(new CacheKey<>(token, a, b), k -> f.apply((U) k.a, (U) k.b)); } public void clear() { diff --git a/matcher-model/src/main/java/matcher/model/classifier/MethodClassifier.java b/matcher-model/src/main/java/matcher/model/classifier/MethodClassifier.java index 87017b24..a8c25d36 100644 --- a/matcher-model/src/main/java/matcher/model/classifier/MethodClassifier.java +++ b/matcher-model/src/main/java/matcher/model/classifier/MethodClassifier.java @@ -24,25 +24,25 @@ import matcher.model.type.MethodVarInstance; import matcher.model.type.Signature.MethodSignature; -public class MethodClassifier { +public final class MethodClassifier { public static void init() { - addClassifier(methodTypeCheck, 10); - addClassifier(accessFlags, 4); - addClassifier(argTypes, 10); - addClassifier(retType, 5); - addClassifier(signature, 5); - addClassifier(classRefs, 3); - addClassifier(stringConstants, 5); - addClassifier(numericConstants, 5); - addClassifier(parentMethods, 10); - addClassifier(childMethods, 3); - addClassifier(inReferences, 6); - addClassifier(outReferences, 6); - addClassifier(fieldReads, 5); - addClassifier(fieldWrites, 5); - addClassifier(position, 3); - addClassifier(code, 12, ClassifierLevel.Full, ClassifierLevel.Extra); - addClassifier(inRefsBci, 6, ClassifierLevel.Extra); + addClassifier(METHOD_TYPE_CHECK, 10); + addClassifier(ACCESS_FLAGS, 4); + addClassifier(ARG_TYPES, 10); + addClassifier(RET_TYPE, 5); + addClassifier(SIGNATURE, 5); + addClassifier(CLASS_REFS, 3); + addClassifier(STRING_CONSTANTS, 5); + addClassifier(NUMERIC_CONSTANTS, 5); + addClassifier(PARENT_METHODS, 10); + addClassifier(CHILD_METHODS, 3); + addClassifier(IN_REFERENCES, 6); + addClassifier(OUT_REFERENCES, 6); + addClassifier(FIELD_READS, 5); + addClassifier(FIELD_WRITES, 5); + addClassifier(POSITION, 3); + addClassifier(CODE, 12, ClassifierLevel.Full, ClassifierLevel.Extra); + addClassifier(IN_REFS_BCI, 6, ClassifierLevel.Extra); } public static void addClassifier(AbstractClassifier classifier, double weight, ClassifierLevel... levels) { @@ -51,13 +51,13 @@ public static void addClassifier(AbstractClassifier classifier, double weight, C classifier.weight = weight; for (ClassifierLevel level : levels) { - classifiers.computeIfAbsent(level, ignore -> new ArrayList<>()).add(classifier); - maxScore.put(level, getMaxScore(level) + weight); + CLASSIFIERS.computeIfAbsent(level, ignore -> new ArrayList<>()).add(classifier); + MAX_SCORE.put(level, getMaxScore(level) + weight); } } public static double getMaxScore(ClassifierLevel level) { - return maxScore.getOrDefault(level, 0.); + return MAX_SCORE.getOrDefault(level, 0.); } public static List> rank(MethodInstance src, MethodInstance[] dsts, ClassifierLevel level, ClassEnvironment env) { @@ -79,9 +79,7 @@ public static List> rank(MethodInstance src, MethodIn MethodInstance[] newDsts = new MethodInstance[dsts.length]; int writeIdx = 0; - for (int readIdx = 0; readIdx < dsts.length; readIdx++) { - MethodInstance m = dsts[readIdx]; - + for (MethodInstance m : dsts) { if (dstHierarchyMembers.contains(m)) { newDsts[writeIdx++] = m; } @@ -94,13 +92,13 @@ public static List> rank(MethodInstance src, MethodIn } } - return ClassifierUtil.rank(src, dsts, classifiers.getOrDefault(level, Collections.emptyList()), ClassifierUtil::checkPotentialEquality, env, maxMismatch); + return ClassifierUtil.rank(src, dsts, CLASSIFIERS.getOrDefault(level, Collections.emptyList()), ClassifierUtil::checkPotentialEquality, env, maxMismatch); } - private static final Map>> classifiers = new EnumMap<>(ClassifierLevel.class); - private static final Map maxScore = new EnumMap<>(ClassifierLevel.class); + private static final Map>> CLASSIFIERS = new EnumMap<>(ClassifierLevel.class); + private static final Map MAX_SCORE = new EnumMap<>(ClassifierLevel.class); - private static AbstractClassifier methodTypeCheck = new AbstractClassifier("method type check") { + private static final AbstractClassifier METHOD_TYPE_CHECK = new AbstractClassifier("method type check") { @Override public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvironment env) { if (!checkAsmNodes(methodA, methodB)) return compareAsmNodes(methodA, methodB); @@ -113,7 +111,7 @@ public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvi } }; - private static AbstractClassifier accessFlags = new AbstractClassifier("access flags") { + private static final AbstractClassifier ACCESS_FLAGS = new AbstractClassifier("access flags") { @Override public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvironment env) { if (!checkAsmNodes(methodA, methodB)) return compareAsmNodes(methodA, methodB); @@ -126,7 +124,7 @@ public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvi } }; - private static AbstractClassifier argTypes = new AbstractClassifier("arg types") { + private static final AbstractClassifier ARG_TYPES = new AbstractClassifier("arg types") { @Override public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvironment env) { return ClassifierUtil.compareClassLists(getArgTypes(methodA), getArgTypes(methodB)); @@ -146,14 +144,14 @@ private static List getArgTypes(MethodInstance method) { return ret; } - private static AbstractClassifier retType = new AbstractClassifier("ret type") { + private static final AbstractClassifier RET_TYPE = new AbstractClassifier("ret type") { @Override public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvironment env) { return ClassifierUtil.checkPotentialEquality(methodA.getRetType(), methodB.getRetType()) ? 1 : 0; } }; - private static AbstractClassifier signature = new AbstractClassifier("signature") { + private static final AbstractClassifier SIGNATURE = new AbstractClassifier("signature") { @Override public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvironment env) { MethodSignature sigA = methodA.getSignature(); @@ -166,14 +164,14 @@ public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvi } }; - private static AbstractClassifier classRefs = new AbstractClassifier("class refs") { + private static final AbstractClassifier CLASS_REFS = new AbstractClassifier("class refs") { @Override public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvironment env) { return ClassifierUtil.compareClassSets(methodA.getClassRefs(), methodB.getClassRefs(), true); } }; - private static AbstractClassifier stringConstants = new AbstractClassifier("string constants") { + private static final AbstractClassifier STRING_CONSTANTS = new AbstractClassifier("string constants") { @Override public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvironment env) { if (!checkAsmNodes(methodA, methodB)) return compareAsmNodes(methodA, methodB); @@ -187,7 +185,7 @@ public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvi } }; - private static AbstractClassifier numericConstants = new AbstractClassifier("numeric constants") { + private static final AbstractClassifier NUMERIC_CONSTANTS = new AbstractClassifier("numeric constants") { @Override public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvironment env) { if (!checkAsmNodes(methodA, methodB)) return compareAsmNodes(methodA, methodB); @@ -211,56 +209,56 @@ public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvi } }; - private static AbstractClassifier parentMethods = new AbstractClassifier("parent methods") { + private static final AbstractClassifier PARENT_METHODS = new AbstractClassifier("parent methods") { @Override public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvironment env) { return ClassifierUtil.compareMethodSets(methodA.getParents(), methodB.getParents(), true); } }; - private static AbstractClassifier childMethods = new AbstractClassifier("child methods") { + private static final AbstractClassifier CHILD_METHODS = new AbstractClassifier("child methods") { @Override public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvironment env) { return ClassifierUtil.compareMethodSets(methodA.getChildren(), methodB.getChildren(), true); } }; - private static AbstractClassifier outReferences = new AbstractClassifier("out references") { + private static final AbstractClassifier OUT_REFERENCES = new AbstractClassifier("out references") { @Override public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvironment env) { return ClassifierUtil.compareMethodSets(methodA.getRefsOut(), methodB.getRefsOut(), true); } }; - private static AbstractClassifier inReferences = new AbstractClassifier("in references") { + private static final AbstractClassifier IN_REFERENCES = new AbstractClassifier("in references") { @Override public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvironment env) { return ClassifierUtil.compareMethodSets(methodA.getRefsIn(), methodB.getRefsIn(), true); } }; - private static AbstractClassifier fieldReads = new AbstractClassifier("field reads") { + private static final AbstractClassifier FIELD_READS = new AbstractClassifier("field reads") { @Override public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvironment env) { return ClassifierUtil.compareFieldSets(methodA.getFieldReadRefs(), methodB.getFieldReadRefs(), true); } }; - private static AbstractClassifier fieldWrites = new AbstractClassifier("field writes") { + private static final AbstractClassifier FIELD_WRITES = new AbstractClassifier("field writes") { @Override public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvironment env) { return ClassifierUtil.compareFieldSets(methodA.getFieldWriteRefs(), methodB.getFieldWriteRefs(), true); } }; - private static AbstractClassifier position = new AbstractClassifier("position") { + private static final AbstractClassifier POSITION = new AbstractClassifier("position") { @Override public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvironment env) { return ClassifierUtil.classifyPosition(methodA, methodB, MemberInstance::getPosition, (m, idx) -> m.getCls().getMethod(idx), m -> m.getCls().getMethods()); } }; - private static AbstractClassifier code = new AbstractClassifier("code") { + private static final AbstractClassifier CODE = new AbstractClassifier("code") { @Override public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvironment env) { if (!checkAsmNodes(methodA, methodB)) return compareAsmNodes(methodA, methodB); @@ -269,7 +267,7 @@ public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvi } }; - private static AbstractClassifier inRefsBci = new AbstractClassifier("in refs (bci)") { + private static final AbstractClassifier IN_REFS_BCI = new AbstractClassifier("in refs (bci)") { @Override public double getScore(MethodInstance methodA, MethodInstance methodB, ClassEnvironment env) { String ownerA = methodA.getCls().getName(); @@ -365,7 +363,7 @@ private static double compareAsmNodes(MethodInstance a, MethodInstance b) { } public abstract static class AbstractClassifier implements IClassifier { - public AbstractClassifier(String name) { + protected AbstractClassifier(String name) { this.name = name; } @@ -382,4 +380,7 @@ public double getWeight() { private final String name; private double weight; } + + private MethodClassifier() { + } } diff --git a/matcher-model/src/main/java/matcher/model/classifier/MethodVarClassifier.java b/matcher-model/src/main/java/matcher/model/classifier/MethodVarClassifier.java index 7a9a0db7..0e26be51 100644 --- a/matcher-model/src/main/java/matcher/model/classifier/MethodVarClassifier.java +++ b/matcher-model/src/main/java/matcher/model/classifier/MethodVarClassifier.java @@ -14,12 +14,12 @@ import matcher.model.type.ClassEnvironment; import matcher.model.type.MethodVarInstance; -public class MethodVarClassifier { +public final class MethodVarClassifier { public static void init() { - addClassifier(type, 10); - addClassifier(position, 3); - addClassifier(lvIndex, 2); - addClassifier(usage, 8); + addClassifier(TYPE, 10); + addClassifier(POSITION, 3); + addClassifier(LV_INDEX, 2); + addClassifier(USAGE, 8); } public static void addClassifier(AbstractClassifier classifier, double weight, ClassifierLevel... levels) { @@ -28,30 +28,30 @@ public static void addClassifier(AbstractClassifier classifier, double weight, C classifier.weight = weight; for (ClassifierLevel level : levels) { - classifiers.computeIfAbsent(level, ignore -> new ArrayList<>()).add(classifier); - maxScore.put(level, getMaxScore(level) + weight); + CLASSIFIERS.computeIfAbsent(level, ignore -> new ArrayList<>()).add(classifier); + MAX_SCORE.put(level, getMaxScore(level) + weight); } } public static double getMaxScore(ClassifierLevel level) { - return maxScore.getOrDefault(level, 0.); + return MAX_SCORE.getOrDefault(level, 0.); } public static List> rank(MethodVarInstance src, MethodVarInstance[] dsts, ClassifierLevel level, ClassEnvironment env, double maxMismatch) { - return ClassifierUtil.rank(src, dsts, classifiers.getOrDefault(level, Collections.emptyList()), ClassifierUtil::checkPotentialEquality, env, maxMismatch); + return ClassifierUtil.rank(src, dsts, CLASSIFIERS.getOrDefault(level, Collections.emptyList()), ClassifierUtil::checkPotentialEquality, env, maxMismatch); } - private static final Map>> classifiers = new EnumMap<>(ClassifierLevel.class); - private static final Map maxScore = new EnumMap<>(ClassifierLevel.class); + private static final Map>> CLASSIFIERS = new EnumMap<>(ClassifierLevel.class); + private static final Map MAX_SCORE = new EnumMap<>(ClassifierLevel.class); - private static AbstractClassifier type = new AbstractClassifier("type") { + private static final AbstractClassifier TYPE = new AbstractClassifier("type") { @Override public double getScore(MethodVarInstance argA, MethodVarInstance argB, ClassEnvironment env) { return ClassifierUtil.checkPotentialEquality(argA.getType(), argB.getType()) ? 1 : 0; } }; - private static AbstractClassifier position = new AbstractClassifier("position") { + private static final AbstractClassifier POSITION = new AbstractClassifier("position") { @Override public double getScore(MethodVarInstance methodA, MethodVarInstance methodB, ClassEnvironment env) { return ClassifierUtil.classifyPosition(methodA, methodB, @@ -61,14 +61,14 @@ public double getScore(MethodVarInstance methodA, MethodVarInstance methodB, Cla } }; - private static AbstractClassifier lvIndex = new AbstractClassifier("lv index") { + private static final AbstractClassifier LV_INDEX = new AbstractClassifier("lv index") { @Override public double getScore(MethodVarInstance argA, MethodVarInstance argB, ClassEnvironment env) { return argA.getLvIndex() == argB.getLvIndex() ? 1 : 0; } }; - private static AbstractClassifier usage = new AbstractClassifier("usage") { + private static final AbstractClassifier USAGE = new AbstractClassifier("usage") { @Override public double getScore(MethodVarInstance argA, MethodVarInstance argB, ClassEnvironment env) { int[] map = ClassifierUtil.mapInsns(argA.getMethod(), argB.getMethod()); @@ -115,7 +115,7 @@ public double getScore(MethodVarInstance argA, MethodVarInstance argB, ClassEnvi }; public abstract static class AbstractClassifier implements IClassifier { - public AbstractClassifier(String name) { + protected AbstractClassifier(String name) { this.name = name; } @@ -132,4 +132,7 @@ public double getWeight() { private final String name; private double weight; } + + private MethodVarClassifier() { + } } diff --git a/matcher-model/src/main/java/matcher/model/config/Config.java b/matcher-model/src/main/java/matcher/model/config/Config.java index 641463b7..073ecef2 100644 --- a/matcher-model/src/main/java/matcher/model/config/Config.java +++ b/matcher-model/src/main/java/matcher/model/config/Config.java @@ -1,7 +1,6 @@ package matcher.model.config; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -9,19 +8,19 @@ import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; -public class Config { +public final class Config { public static void init(String themeId) { Preferences prefs = Preferences.userRoot(); // in ~/.java/.userPrefs try { - if (prefs.nodeExists(userPrefFolder)) { - prefs = prefs.node(userPrefFolder); + if (prefs.nodeExists(USER_PREF_FOLDER)) { + prefs = prefs.node(USER_PREF_FOLDER); - if (prefs.nodeExists(lastProjectSetupKey)) setProjectConfig(new ProjectConfig.Builder(prefs.node(lastProjectSetupKey)).build()); - setInputDirs(loadList(prefs, lastInputDirsKey, Config::deserializePath)); - setVerifyInputFiles(prefs.getBoolean(lastVerifyInputFilesKey, true)); + if (prefs.nodeExists(LAST_PROJECT_SETUP_KEY)) setProjectConfig(new ProjectConfig.Builder(prefs.node(LAST_PROJECT_SETUP_KEY)).build()); + setInputDirs(loadList(prefs, LAST_INPUT_DIRS_KEY, Config::deserializePath)); + setVerifyInputFiles(prefs.getBoolean(LAST_VERIFY_INPUT_FILES_KEY, true)); setUidConfig(new UidConfig(prefs)); - setTheme(Theme.getById(prefs.get(themeKey, Theme.getDefault().getId()))); + setTheme(Theme.getById(prefs.get(THEME_KEY, Theme.getDefault().getId()))); } } catch (BackingStoreException e) { // ignored @@ -49,7 +48,7 @@ public static boolean getVerifyInputFiles() { } public static List getInputDirs() { - return inputDirs; + return INPUT_DIRS; } public static UidConfig getUidConfig() { @@ -69,8 +68,8 @@ public static boolean setProjectConfig(ProjectConfig config) { } public static void setInputDirs(List dirs) { - inputDirs.clear(); - inputDirs.addAll(dirs); + INPUT_DIRS.clear(); + INPUT_DIRS.addAll(dirs); } public static void setVerifyInputFiles(boolean value) { @@ -92,10 +91,10 @@ public static void setTheme(Theme value) { } public static void saveTheme() { - Preferences root = Preferences.userRoot().node(userPrefFolder); + Preferences root = Preferences.userRoot().node(USER_PREF_FOLDER); try { - root.put(themeKey, getTheme().getId()); + root.put(THEME_KEY, getTheme().getId()); root.flush(); } catch (BackingStoreException e) { // ignored @@ -103,12 +102,12 @@ public static void saveTheme() { } public static void saveAsLast() { - Preferences root = Preferences.userRoot().node(userPrefFolder); + Preferences root = Preferences.userRoot().node(USER_PREF_FOLDER); try { - if (projectConfig.isValid()) projectConfig.save(root.node(lastProjectSetupKey)); - saveList(root.node(lastInputDirsKey), inputDirs); - root.putBoolean(lastVerifyInputFilesKey, verifyInputFiles); + if (projectConfig.isValid()) projectConfig.save(root.node(LAST_PROJECT_SETUP_KEY)); + saveList(root.node(LAST_INPUT_DIRS_KEY), INPUT_DIRS); + root.putBoolean(LAST_VERIFY_INPUT_FILES_KEY, verifyInputFiles); uidConfig.save(root); root.flush(); @@ -140,17 +139,17 @@ static void saveList(Preferences parent, List list) throws BackingStoreExcept } static Path deserializePath(String path) { - return Paths.get(path); + return Path.of(path); } - private static final String userPrefFolder = "player-obf-matcher"; - private static final String lastProjectSetupKey = "last-project-setup"; - private static final String lastInputDirsKey = "last-input-dirs"; - private static final String lastVerifyInputFilesKey = "last-verify-input-files"; - private static final String themeKey = "theme"; + private static final String USER_PREF_FOLDER = "player-obf-matcher"; + private static final String LAST_PROJECT_SETUP_KEY = "last-project-setup"; + private static final String LAST_INPUT_DIRS_KEY = "last-input-dirs"; + private static final String LAST_VERIFY_INPUT_FILES_KEY = "last-verify-input-files"; + private static final String THEME_KEY = "theme"; private static ProjectConfig projectConfig = ProjectConfig.EMPTY; - private static final List inputDirs = new ArrayList<>(); + private static final List INPUT_DIRS = new ArrayList<>(); private static boolean verifyInputFiles = true; private static UidConfig uidConfig = new UidConfig(); private static Theme theme; diff --git a/matcher-model/src/main/java/matcher/model/config/ProjectConfig.java b/matcher-model/src/main/java/matcher/model/config/ProjectConfig.java index 535dd287..1d30047c 100644 --- a/matcher-model/src/main/java/matcher/model/config/ProjectConfig.java +++ b/matcher-model/src/main/java/matcher/model/config/ProjectConfig.java @@ -8,7 +8,7 @@ import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; -public class ProjectConfig { +public final class ProjectConfig { public static class Builder { public Builder(List pathsA, List pathsB) { this.pathsA = pathsA; @@ -16,23 +16,23 @@ public Builder(List pathsA, List pathsB) { } Builder(Preferences prefs) throws BackingStoreException { - pathsA = Config.loadList(prefs, pathsAKey, Config::deserializePath); - pathsB = Config.loadList(prefs, pathsBKey, Config::deserializePath); - classPathA = Config.loadList(prefs, classPathAKey, Config::deserializePath); - classPathB = Config.loadList(prefs, classPathBKey, Config::deserializePath); - sharedClassPath = Config.loadList(prefs, pathsSharedKey, Config::deserializePath); - inputsBeforeClassPath = prefs.getBoolean(inputsBeforeClassPathKey, false); - - String storedMappingsPathA = prefs.get(mappingsPathAKey, null); - String storedMappingsPathB = prefs.get(mappingsPathBKey, null); + pathsA = Config.loadList(prefs, PATHS_A_KEY, Config::deserializePath); + pathsB = Config.loadList(prefs, PATHS_B_KEY, Config::deserializePath); + classPathA = Config.loadList(prefs, CLASS_PATH_A_KEY, Config::deserializePath); + classPathB = Config.loadList(prefs, CLASS_PATH_B_KEY, Config::deserializePath); + sharedClassPath = Config.loadList(prefs, PATHS_SHARED_KEY, Config::deserializePath); + inputsBeforeClassPath = prefs.getBoolean(INPUTS_BEFORE_CLASS_PATH_KEY, false); + + String storedMappingsPathA = prefs.get(MAPPINGS_PATH_A_KEY, null); + String storedMappingsPathB = prefs.get(MAPPINGS_PATH_B_KEY, null); mappingsPathA = storedMappingsPathA == null ? null : Path.of(storedMappingsPathA); mappingsPathB = storedMappingsPathB == null ? null : Path.of(storedMappingsPathB); - saveUnmappedMatches = prefs.getBoolean(inputsBeforeClassPathKey, false); + saveUnmappedMatches = prefs.getBoolean(INPUTS_BEFORE_CLASS_PATH_KEY, false); - nonObfuscatedClassPatternA = prefs.get(nonObfuscatedClassPatternAKey, ""); - nonObfuscatedClassPatternB = prefs.get(nonObfuscatedClassPatternBKey, ""); - nonObfuscatedMemberPatternA = prefs.get(nonObfuscatedMemberPatternAKey, ""); - nonObfuscatedMemberPatternB = prefs.get(nonObfuscatedMemberPatternBKey, ""); + nonObfuscatedClassPatternA = prefs.get(NON_OBFUSCATED_CLASS_PATTERN_A_KEY, ""); + nonObfuscatedClassPatternB = prefs.get(NON_OBFUSCATED_CLASS_PATTERN_B_KEY, ""); + nonObfuscatedMemberPatternA = prefs.get(NON_OBFUSCATED_MEMBER_PATTERN_A_KEY, ""); + nonObfuscatedMemberPatternB = prefs.get(NON_OBFUSCATED_MEMBER_PATTERN_B_KEY, ""); } public Builder classPathA(List classPathA) { @@ -186,7 +186,7 @@ public boolean isValid() { && Collections.disjoint(pathsA, pathsB) && Collections.disjoint(pathsA, sharedClassPath) && Collections.disjoint(pathsB, sharedClassPath) - //&& Collections.disjoint(classPathA, classPathB) + // && Collections.disjoint(classPathA, classPathB) && Collections.disjoint(classPathA, pathsA) && Collections.disjoint(classPathB, pathsA) && Collections.disjoint(classPathA, pathsB) @@ -211,37 +211,37 @@ private static boolean tryCompilePattern(String regex) { void save(Preferences prefs) throws BackingStoreException { if (!isValid()) return; - Config.saveList(prefs.node(pathsAKey), pathsA); - Config.saveList(prefs.node(pathsBKey), pathsB); - Config.saveList(prefs.node(classPathAKey), classPathA); - Config.saveList(prefs.node(classPathBKey), classPathB); - Config.saveList(prefs.node(pathsSharedKey), sharedClassPath); - prefs.putBoolean(inputsBeforeClassPathKey, inputsBeforeClassPath); - if (mappingsPathA != null) prefs.put(mappingsPathAKey, mappingsPathA.toString()); - if (mappingsPathB != null) prefs.put(mappingsPathBKey, mappingsPathB.toString()); - prefs.putBoolean(saveUnmappedMatchesKey, saveUnmappedMatches); - prefs.put(nonObfuscatedClassPatternAKey, nonObfuscatedClassPatternA); - prefs.put(nonObfuscatedClassPatternBKey, nonObfuscatedClassPatternB); - prefs.put(nonObfuscatedMemberPatternAKey, nonObfuscatedMemberPatternA); - prefs.put(nonObfuscatedMemberPatternBKey, nonObfuscatedMemberPatternB); + Config.saveList(prefs.node(PATHS_A_KEY), pathsA); + Config.saveList(prefs.node(PATHS_B_KEY), pathsB); + Config.saveList(prefs.node(CLASS_PATH_A_KEY), classPathA); + Config.saveList(prefs.node(CLASS_PATH_B_KEY), classPathB); + Config.saveList(prefs.node(PATHS_SHARED_KEY), sharedClassPath); + prefs.putBoolean(INPUTS_BEFORE_CLASS_PATH_KEY, inputsBeforeClassPath); + if (mappingsPathA != null) prefs.put(MAPPINGS_PATH_A_KEY, mappingsPathA.toString()); + if (mappingsPathB != null) prefs.put(MAPPINGS_PATH_B_KEY, mappingsPathB.toString()); + prefs.putBoolean(SAVE_UNMAPPED_MATCHES_KEY, saveUnmappedMatches); + prefs.put(NON_OBFUSCATED_CLASS_PATTERN_A_KEY, nonObfuscatedClassPatternA); + prefs.put(NON_OBFUSCATED_CLASS_PATTERN_B_KEY, nonObfuscatedClassPatternB); + prefs.put(NON_OBFUSCATED_MEMBER_PATTERN_A_KEY, nonObfuscatedMemberPatternA); + prefs.put(NON_OBFUSCATED_MEMBER_PATTERN_B_KEY, nonObfuscatedMemberPatternB); } public static final ProjectConfig EMPTY = new ProjectConfig(Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), false, null, null, true, "", "", "", ""); - private static final String pathsAKey = "paths-a"; - private static final String pathsBKey = "paths-b"; - private static final String classPathAKey = "class-path-a"; - private static final String classPathBKey = "class-path-b"; - private static final String pathsSharedKey = "paths-shared"; - private static final String inputsBeforeClassPathKey = "inputs-before-classpath"; - private static final String mappingsPathAKey = "mappings-path-a"; - private static final String mappingsPathBKey = "mappings-path-b"; - private static final String saveUnmappedMatchesKey = "save-unmapped-matches"; - private static final String nonObfuscatedClassPatternAKey = "non-obfuscated-class-pattern-a"; - private static final String nonObfuscatedClassPatternBKey = "non-obfuscated-class-pattern-b"; - private static final String nonObfuscatedMemberPatternAKey = "non-obfuscated-member-pattern-a"; - private static final String nonObfuscatedMemberPatternBKey = "non-obfuscated-member-pattern-b"; + private static final String PATHS_A_KEY = "paths-a"; + private static final String PATHS_B_KEY = "paths-b"; + private static final String CLASS_PATH_A_KEY = "class-path-a"; + private static final String CLASS_PATH_B_KEY = "class-path-b"; + private static final String PATHS_SHARED_KEY = "paths-shared"; + private static final String INPUTS_BEFORE_CLASS_PATH_KEY = "inputs-before-classpath"; + private static final String MAPPINGS_PATH_A_KEY = "mappings-path-a"; + private static final String MAPPINGS_PATH_B_KEY = "mappings-path-b"; + private static final String SAVE_UNMAPPED_MATCHES_KEY = "save-unmapped-matches"; + private static final String NON_OBFUSCATED_CLASS_PATTERN_A_KEY = "non-obfuscated-class-pattern-a"; + private static final String NON_OBFUSCATED_CLASS_PATTERN_B_KEY = "non-obfuscated-class-pattern-b"; + private static final String NON_OBFUSCATED_MEMBER_PATTERN_A_KEY = "non-obfuscated-member-pattern-a"; + private static final String NON_OBFUSCATED_MEMBER_PATTERN_B_KEY = "non-obfuscated-member-pattern-b"; private final List pathsA; private final List pathsB; diff --git a/matcher-model/src/main/java/matcher/model/mapping/MappedElementComparators.java b/matcher-model/src/main/java/matcher/model/mapping/MappedElementComparators.java index 83a52ac6..357e074a 100644 --- a/matcher-model/src/main/java/matcher/model/mapping/MappedElementComparators.java +++ b/matcher-model/src/main/java/matcher/model/mapping/MappedElementComparators.java @@ -11,61 +11,50 @@ public final class MappedElementComparators { public static > Comparator byName(NameType ns) { - return new Comparator() { - @Override - public int compare(T a, T b) { - return compareNullLast(a.getName(ns), b.getName(ns)); - } - }; + return (a, b) -> compareNullLast(a.getName(ns), b.getName(ns)); } public static > Comparator byNameShortFirst(NameType ns) { - return new Comparator() { - @Override - public int compare(T a, T b) { - String nameA = a.getName(ns); - String nameB = b.getName(ns); - - if (nameA == null || nameB == null) { - return compareNullLast(nameA, nameB); - } else { - return compareNameShortFirst(nameA, 0, nameA.length(), nameB, 0, nameB.length()); - } + return (a, b) -> { + String nameA = a.getName(ns); + String nameB = b.getName(ns); + + if (nameA == null || nameB == null) { + return compareNullLast(nameA, nameB); + } else { + return compareNameShortFirst(nameA, 0, nameA.length(), nameB, 0, nameB.length()); } }; } public static Comparator byNameShortFirstNestaware(NameType ns) { - return new Comparator() { - @Override - public int compare(ClassInstance a, ClassInstance b) { - String nameA = a.getName(ns); - String nameB = b.getName(ns); - - if (nameA == null || nameB == null) { - return compareNullLast(nameA, nameB); - } + return (a, b) -> { + String nameA = a.getName(ns); + String nameB = b.getName(ns); - int pos = 0; + if (nameA == null || nameB == null) { + return compareNullLast(nameA, nameB); + } - do { - int endA = nameA.indexOf('$', pos); - int endB = nameB.indexOf('$', pos); + int pos = 0; - int ret = compareNameShortFirst(nameA, pos, endA >= 0 ? endA : nameA.length(), - nameB, pos, endB >= 0 ? endB : nameB.length()); + do { + int endA = nameA.indexOf('$', pos); + int endB = nameB.indexOf('$', pos); - if (ret != 0) { - return ret; - } else if ((endA < 0) != (endB < 0)) { - return endA < 0 ? -1 : 1; - } + int ret = compareNameShortFirst(nameA, pos, endA >= 0 ? endA : nameA.length(), + nameB, pos, endB >= 0 ? endB : nameB.length()); - pos = endA + 1; - } while (pos > 0); + if (ret != 0) { + return ret; + } else if ((endA < 0) != (endB < 0)) { + return endA < 0 ? -1 : 1; + } - return 0; - } + pos = endA + 1; + } while (pos > 0); + + return 0; }; } @@ -87,44 +76,27 @@ private static int compareNameShortFirst(String nameA, int startA, int endA, Str } public static > Comparator byNameDescConcat(NameType ns) { - return new Comparator() { - @Override - public int compare(T a, T b) { - String valA = Objects.toString(a.getName(ns)).concat(Objects.toString(a.getDesc(ns))); - String valB = Objects.toString(b.getName(ns)).concat(Objects.toString(b.getDesc(ns))); + return (a, b) -> { + String valA = Objects.toString(a.getName(ns)).concat(Objects.toString(a.getDesc(ns))); + String valB = Objects.toString(b.getName(ns)).concat(Objects.toString(b.getDesc(ns))); - return valA.compareTo(valB); - } + return valA.compareTo(valB); }; } public static Comparator byLvIndex() { - return lvIndexComparator; + return LV_INDEX_COMPARATOR; } - private static final Comparator lvIndexComparator = new Comparator() { - @Override - public int compare(MethodVarInstance a, MethodVarInstance b) { - int ret = Integer.compare(a.getLvIndex(), b.getLvIndex()); - - if (ret == 0) { - ret = Integer.compare(a.getStartOpIdx(), b.getStartOpIdx()); - } - - return ret; - } - }; + private static final Comparator LV_INDEX_COMPARATOR = Comparator + .comparingInt(MethodVarInstance::getLvIndex) + .thenComparingInt(MethodVarInstance::getStartOpIdx); public static Comparator byLvtIndex() { - return lvtIndexComparator; + return LVT_INDEX_COMPARATOR; } - private static final Comparator lvtIndexComparator = new Comparator() { - @Override - public int compare(MethodVarInstance a, MethodVarInstance b) { - return Integer.compare(a.getAsmIndex(), b.getAsmIndex()); - } - }; + private static final Comparator LVT_INDEX_COMPARATOR = Comparator.comparingInt(MethodVarInstance::getAsmIndex); private static int compareNullLast(String a, String b) { if (a == null) { @@ -139,4 +111,7 @@ private static int compareNullLast(String a, String b) { return a.compareTo(b); } } + + private MappedElementComparators() { + } } diff --git a/matcher-model/src/main/java/matcher/model/mapping/MappingPropagator.java b/matcher-model/src/main/java/matcher/model/mapping/MappingPropagator.java index 813816ba..6ea03b0f 100644 --- a/matcher-model/src/main/java/matcher/model/mapping/MappingPropagator.java +++ b/matcher-model/src/main/java/matcher/model/mapping/MappingPropagator.java @@ -24,7 +24,7 @@ public static boolean propagateNames(ClassEnvironment env, DoubleConsumer progre int propagatedArgNames = 0; for (ClassInstance cls : env.getClassesB()) { - if (cls.isInput() && cls.getMethods().length > 0) { + if (cls.isInput()) { for (MethodInstance method : cls.getMethods()) { if (method.getAllHierarchyMembers().size() <= 1) continue; if (checked.contains(method)) continue; @@ -85,12 +85,12 @@ public static boolean propagateNames(ClassEnvironment env, DoubleConsumer progre } } - if (((++current & (1 << 4) - 1)) == 0) { + if ((++current & (1 << 4) - 1) == 0) { progressReceiver.accept((double) current / total); } } - logger.info("Propagated {} method names and {} method arg names", propagatedMethodNames, propagatedArgNames); + LOGGER.info("Propagated {} method names and {} method arg names", propagatedMethodNames, propagatedArgNames); return propagatedMethodNames > 0 || propagatedArgNames > 0; } @@ -99,7 +99,7 @@ public static boolean propagateNames(ClassEnvironment env, DoubleConsumer progre * Ensure that fields and methods representing the same record component share the same mapped name. */ public static boolean fixRecordMemberNames(ClassEnvironment env, NameType nameType, NameType linkingNameType) { - if (!nameType.mapped) throw new IllegalArgumentException("non-mapped nameType: "+nameType); + if (!nameType.mapped) throw new IllegalArgumentException("non-mapped nameType: " + nameType); int modified = 0; @@ -117,10 +117,10 @@ public static boolean fixRecordMemberNames(ClassEnvironment env, NameType nameTy if (linkedMethod.isNameObfuscated() && (!field.isNameObfuscated() || !linkedMethod.hasMappedName() || field.hasMappedName())) { - logger.debug("Copying record component name for method {} from field {} -> {}", linkedMethod, field, fieldName); + LOGGER.debug("Copying record component name for method {} from field {} -> {}", linkedMethod, field, fieldName); linkedMethod.setMappedName(fieldName); } else { - logger.debug("Copying record component name for field {} from method {} -> {}", field, linkedMethod, methodName); + LOGGER.debug("Copying record component name for field {} from method {} -> {}", field, linkedMethod, methodName); field.setMappedName(methodName); } @@ -128,10 +128,13 @@ public static boolean fixRecordMemberNames(ClassEnvironment env, NameType nameTy } } - logger.info("Fixed {} record names.", modified); + LOGGER.info("Fixed {} record names.", modified); return modified > 0; } - private static final Logger logger = LoggerFactory.getLogger(MappingPropagator.class); + private MappingPropagator() { + } + + private static final Logger LOGGER = LoggerFactory.getLogger(MappingPropagator.class); } diff --git a/matcher-model/src/main/java/matcher/model/mapping/Mappings.java b/matcher-model/src/main/java/matcher/model/mapping/Mappings.java index 95f394e1..bd7f41ef 100644 --- a/matcher-model/src/main/java/matcher/model/mapping/Mappings.java +++ b/matcher-model/src/main/java/matcher/model/mapping/Mappings.java @@ -18,11 +18,13 @@ import net.fabricmc.mappingio.MappingWriter; import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; import net.fabricmc.mappingio.adapter.RegularAsFlatMappingVisitor; +import net.fabricmc.mappingio.format.FeatureSet.ElementCommentSupport; import net.fabricmc.mappingio.format.MappingFormat; import matcher.model.NameType; import matcher.model.Util; import matcher.model.type.ClassEnv; +import matcher.model.type.ClassEnvironment; import matcher.model.type.ClassInstance; import matcher.model.type.FieldInstance; import matcher.model.type.LocalClassEnv; @@ -32,7 +34,7 @@ import matcher.model.type.MethodInstance; import matcher.model.type.MethodVarInstance; -public class Mappings { +public final class Mappings { public static void load(Path path, MappingFormat format, String nsSource, String nsTarget, MappingField fieldSource, MappingField fieldTarget, @@ -47,24 +49,24 @@ public static void load(Path path, MappingFormat format, @Override public void visitNamespaces(String srcNamespace, List dstNamespaces) { dstNs = dstNamespaces.indexOf(nsTarget); - if (dstNs < 0) throw new RuntimeException("missing target namespace: "+nsTarget); + if (dstNs < 0) throw new RuntimeException("missing target namespace: " + nsTarget); } @Override public void visitMetadata(String key, String value) { if (fieldTarget == MappingField.UID) { switch (key) { - case Mappings.metaUidNextClass: { + case Mappings.META_UID_NEXT_CLASS: { int val = Integer.parseInt(value); if (replace || env.getGlobal().nextClassUid < val) env.getGlobal().nextClassUid = val; break; } - case Mappings.metaUidNextMethod: { + case Mappings.META_UID_NEXT_METHOD: { int val = Integer.parseInt(value); if (replace || env.getGlobal().nextMethodUid < val) env.getGlobal().nextMethodUid = val; break; } - case Mappings.metaUidNextField: { + case Mappings.META_UID_NEXT_FIELD: { int val = Integer.parseInt(value); if (replace || env.getGlobal().nextFieldUid < val) env.getGlobal().nextFieldUid = val; break; @@ -83,7 +85,7 @@ public boolean visitClass(String srcName) { cur = cls = findClass(srcName, fieldSource, env); if (cls == null) { - if (warnedClasses.add(srcName)) logger.warn("Can't find mapped class {}", srcName); + if (warnedClasses.add(srcName)) LOGGER.warn("Can't find mapped class {}", srcName); return false; } @@ -99,7 +101,7 @@ public boolean visitMethod(String srcName, String srcDesc) { cur = method = cls.getMethod(srcName, srcDesc, fieldSource.type); if (method == null || !method.isReal()) { - logger.warn("Can't find mapped method {}/{}{}", + LOGGER.warn("Can't find mapped method {}/{}{}", cls.getName(fieldSource.type), srcName, srcDesc); return false; } @@ -135,28 +137,28 @@ public boolean visitMethodVar(int asmIndex, int lvIndex, int startOpIdx, int end private MethodVarInstance getMethodVar(int varIndex, int lvIndex, int startOpIdx, int asmIndex, boolean isArg) { if (isArg && varIndex < -1 || varIndex >= method.getArgs().length) { - logger.warn("Invalid var index {} for method {}", varIndex, method); + LOGGER.warn("Invalid var index {} for method {}", varIndex, method); } else if (lvIndex < -1 || lvIndex >= (isArg ? method.getArgs() : method.getVars()).length * 2 + 1) { - logger.warn("Invalid lv index {} for method {}", lvIndex, method); + LOGGER.warn("Invalid lv index {} for method {}", lvIndex, method); } else if (asmIndex < -1) { - logger.warn("Invalid lv asm index {} for method {}", asmIndex, method); + LOGGER.warn("Invalid lv asm index {} for method {}", asmIndex, method); } else { if (!isArg || varIndex == -1) { if (asmIndex >= 0) { varIndex = findVarIndexByAsm(isArg ? method.getArgs() : method.getVars(), asmIndex); if (varIndex == -1) { - logger.warn("Invalid lv asm index {} for method {}", asmIndex, method); + LOGGER.warn("Invalid lv asm index {} for method {}", asmIndex, method); return null; } } else if (lvIndex <= -1) { - logger.warn("Missing arg+lvt index {} for method {}", lvIndex, method); + LOGGER.warn("Missing arg+lvt index {} for method {}", lvIndex, method); return null; } else { varIndex = findVarIndexByLv(isArg ? method.getArgs() : method.getVars(), lvIndex, startOpIdx); if (varIndex == -1) { - logger.warn("Invalid lv index {} for method {}", lvIndex, method); + LOGGER.warn("Invalid lv index {} for method {}", lvIndex, method); return null; } } @@ -165,12 +167,12 @@ private MethodVarInstance getMethodVar(int varIndex, int lvIndex, int startOpIdx MethodVarInstance var = isArg ? method.getArg(varIndex) : method.getVar(varIndex); if (lvIndex != -1 && var.getLvIndex() != lvIndex) { - logger.warn("Mismatched lv index {} for method {}", lvIndex, method); + LOGGER.warn("Mismatched lv index {} for method {}", lvIndex, method); return null; } if (asmIndex != -1 && var.getAsmIndex() != asmIndex) { - logger.warn("Mismatched lv asm index {} for method {}", asmIndex, method); + LOGGER.warn("Mismatched lv asm index {} for method {}", asmIndex, method); return null; } @@ -189,7 +191,7 @@ public boolean visitField(String srcName, String srcDesc) { cur = field = cls.getField(srcName, srcDesc, fieldSource.type); if (field == null || !field.isReal()) { - logger.warn("Can't find mapped field {}/{}", cls.getName(fieldSource.type), srcName); + LOGGER.warn("Can't find mapped field {}/{}", cls.getName(fieldSource.type), srcName); return false; } @@ -225,10 +227,10 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam break; case UID: - String prefix = env.getGlobal().classUidPrefix; + String prefix = ClassEnvironment.CLASS_UID_PREFIX; if (!name.startsWith(prefix)) { - logger.warn("Invalid uid class name {}", name); + LOGGER.warn("Invalid uid class name {}", name); return; } else { int innerNameStart = name.lastIndexOf('$') + 1; @@ -238,7 +240,7 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam int subPrefixStart = prefix.lastIndexOf('/') + 1; if (!name.startsWith(prefix.substring(subPrefixStart), innerNameStart)) { - logger.warn("Invalid uid class name {}", name); + LOGGER.warn("Invalid uid class name {}", name); return; } else { uidStr = name.substring(innerNameStart + prefix.length() - subPrefixStart); @@ -250,7 +252,7 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam int uid = Integer.parseInt(uidStr); if (uid < 0) { - logger.warn("Invalid class uid {}", uid); + LOGGER.warn("Invalid class uid {}", uid); return; } else if (cls.getUid() < 0 || cls.getUid() > uid || replace) { cls.setUid(uid); @@ -283,16 +285,16 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam break; case UID: - String prefix = env.getGlobal().fieldUidPrefix; + String prefix = ClassEnvironment.FIELD_UID_PREFIX; if (!name.startsWith(prefix)) { - logger.warn("Invalid uid field name {}", name); + LOGGER.warn("Invalid uid field name {}", name); return; } else { int uid = Integer.parseInt(name.substring(prefix.length())); if (uid < 0) { - logger.warn("Invalid field uid {}", uid); + LOGGER.warn("Invalid field uid {}", uid); return; } else if (field.getUid() < 0 || field.getUid() > uid || replace) { for (FieldInstance f : field.getAllHierarchyMembers()) { @@ -327,16 +329,16 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam break; case UID: - String prefix = env.getGlobal().methodUidPrefix; + String prefix = ClassEnvironment.METHOD_UID_PREFIX; if (!name.startsWith(prefix)) { - logger.warn("Invalid uid method name {}", name); + LOGGER.warn("Invalid uid method name {}", name); return; } else { int uid = Integer.parseInt(name.substring(prefix.length())); if (uid < 0) { - logger.warn("Invalid method uid {}", uid); + LOGGER.warn("Invalid method uid {}", uid); return; } else if (method.getUid() < 0 || method.getUid() > uid || replace) { for (MethodInstance m : method.getAllHierarchyMembers()) { @@ -413,15 +415,16 @@ public void visitComment(MappedElementKind targetKind, String comment) { throw t; } - logger.info("Loaded mappings for {} classes, {} methods ({} args, {} vars) and {} fields (comments: {}/{}/{}).", - dstNameCounts[MatchableKind.CLASS.ordinal()], - dstNameCounts[MatchableKind.METHOD.ordinal()], - dstNameCounts[MatchableKind.METHOD_ARG.ordinal()], - dstNameCounts[MatchableKind.METHOD_VAR.ordinal()], - dstNameCounts[MatchableKind.FIELD.ordinal()], - commentCounts[MatchableKind.CLASS.ordinal()], - commentCounts[MatchableKind.METHOD.ordinal()], - commentCounts[MatchableKind.FIELD.ordinal()]); + LOGGER.atInfo() + .addArgument(() -> dstNameCounts[MatchableKind.CLASS.ordinal()]) + .addArgument(() -> dstNameCounts[MatchableKind.METHOD.ordinal()]) + .addArgument(() -> dstNameCounts[MatchableKind.METHOD_ARG.ordinal()]) + .addArgument(() -> dstNameCounts[MatchableKind.METHOD_VAR.ordinal()]) + .addArgument(() -> dstNameCounts[MatchableKind.FIELD.ordinal()]) + .addArgument(() -> commentCounts[MatchableKind.CLASS.ordinal()]) + .addArgument(() -> commentCounts[MatchableKind.METHOD.ordinal()]) + .addArgument(() -> commentCounts[MatchableKind.FIELD.ordinal()]) + .log("Loaded mappings for {} classes, {} methods ({} args, {} vars) and {} fields (comments: {}/{}/{})."); } private static ClassInstance findClass(String name, MappingField type, LocalClassEnv env) { @@ -465,7 +468,7 @@ private static int findVarIndexByAsm(MethodVarInstance[] vars, int asmIndex) { public static boolean save(Path file, MappingFormat format, LocalClassEnv env, List nsTypes, List nsNames, MappingsExportVerbosity verbosity, boolean forAnyInput, boolean fieldsFirst) throws IOException { - if (nsTypes.size() < 2 || nsTypes.size() > 2 && !format.hasNamespaces) throw new IllegalArgumentException("invalid namespace count"); + if (nsTypes.size() < 2 || nsTypes.size() > 2 && !format.features().hasNamespaces()) throw new IllegalArgumentException("invalid namespace count"); if (nsNames != null && nsNames.size() != nsTypes.size()) throw new IllegalArgumentException("namespace types and names don't have the same number of entries"); if (nsNames == null) { @@ -530,7 +533,7 @@ public static boolean save(Path file, MappingFormat format, LocalClassEnv env, } if (!hasAnyDstName - && (!format.supportsComments || cls.getMappedComment() == null) + && (!supportsElementComments(format) || cls.getMappedComment() == null) && !shouldExportAny(cls.getMethods(), format, nsTypes, verbosity, forAnyInput, exportedHierarchies) && !shouldExportAny(cls.getFields(), format, nsTypes)) { continue; // no data for the class, skip @@ -566,6 +569,10 @@ public static boolean save(Path file, MappingFormat format, LocalClassEnv env, return true; } + private static boolean supportsElementComments(MappingFormat format) { + return format.features().elementComments() != ElementCommentSupport.NONE; + } + private static void exportMethods(ClassInstance cls, String srcClsName, String[] dstClassNames, MappingFormat format, List nsTypes, MappingsExportVerbosity verbosity, boolean forAnyInput, String[] dstMemberNames, String[] dstMemberDescs, String[] dstVarNames, @@ -613,23 +620,23 @@ private static void exportMethods(ClassInstance cls, String srcClsName, String[] continue; } - if (format.supportsComments) { + if (supportsElementComments(format)) { String comment = m.getMappedComment(); if (comment != null) writer.visitMethodComment(srcClsName, srcName, desc, dstClassNames, dstMethodNames, dstMemberDescs, comment); } // method args, vars - if (format.supportsArgs || format.supportsLocals) { + if (format.features().supportsArgs() || format.features().supportsVars()) { for (int k = 0; k < 2; k++) { boolean isArg = k == 0; MethodVarInstance[] instances; if (isArg) { // arg - if (!format.supportsArgs) continue; + if (!format.features().supportsArgs()) continue; instances = m.getArgs(); } else { // var - if (!format.supportsLocals) continue; + if (!format.features().supportsVars()) continue; instances = m.getVars(); } @@ -668,7 +675,7 @@ private static void exportMethods(ClassInstance cls, String srcClsName, String[] } } - if (format.supportsComments) { + if (supportsElementComments(format)) { String comment = var.getMappedComment(); if (comment != null) { @@ -730,7 +737,7 @@ private static void exportFields(ClassInstance cls, String srcClsName, String[] continue; } - if (format.supportsComments) { + if (supportsElementComments(format)) { String comment = f.getMappedComment(); if (comment != null) writer.visitFieldComment(srcClsName, srcName, desc, dstClassNames, dstMemberNames, dstMemberDescs, comment); } @@ -770,23 +777,23 @@ private static boolean shouldExport(MethodInstance method, MappingFormat format, String srcName = method.getName(nsTypes.get(0)); if (srcName == null) return false; - return format.supportsComments && method.getMappedComment() != null - || format.supportsArgs && shouldExportAny(method.getArgs(), format, nsTypes) - || format.supportsLocals && shouldExportAny(method.getVars(), format, nsTypes) + return supportsElementComments(format) && method.getMappedComment() != null + || format.features().supportsArgs() && shouldExportAny(method.getArgs(), format, nsTypes) + || format.features().supportsVars() && shouldExportAny(method.getVars(), format, nsTypes) || hasAnyNames(method, srcName, nsTypes) && shouldExportName(method, verbosity, forAnyInput, exportedHierarchies); } private static boolean shouldExport(MethodVarInstance var, MappingFormat format, List nsTypes) { String srcName = var.getName(nsTypes.get(0)); - return format.supportsComments && var.getMappedComment() != null || hasAnyNames(var, srcName, nsTypes); + return supportsElementComments(format) && var.getMappedComment() != null || hasAnyNames(var, srcName, nsTypes); } private static boolean shouldExport(FieldInstance field, MappingFormat format, List nsTypes) { String srcName = field.getName(nsTypes.get(0)); return srcName != null - && (format.supportsComments && field.getMappedComment() != null || hasAnyNames(field, srcName, nsTypes)); + && (supportsElementComments(format) && field.getMappedComment() != null || hasAnyNames(field, srcName, nsTypes)); } private static boolean hasAnyNames(Matchable m, String srcName, List nsTypes) { @@ -859,8 +866,11 @@ public static void clear(ClassEnv env) { } } - private static final Logger logger = LoggerFactory.getLogger(Mappings.class); - public static final String metaUidNextClass = "uid-next-class"; - public static final String metaUidNextMethod = "uid-next-method"; - public static final String metaUidNextField = "uid-next-field"; + private Mappings() { + } + + private static final Logger LOGGER = LoggerFactory.getLogger(Mappings.class); + public static final String META_UID_NEXT_CLASS = "uid-next-class"; + public static final String META_UID_NEXT_METHOD = "uid-next-method"; + public static final String META_UID_NEXT_FIELD = "uid-next-field"; } diff --git a/matcher-model/src/main/java/matcher/model/mapping/MappingsExportVerbosity.java b/matcher-model/src/main/java/matcher/model/mapping/MappingsExportVerbosity.java index c6ad13d7..676c06d3 100644 --- a/matcher-model/src/main/java/matcher/model/mapping/MappingsExportVerbosity.java +++ b/matcher-model/src/main/java/matcher/model/mapping/MappingsExportVerbosity.java @@ -1,5 +1,5 @@ package matcher.model.mapping; public enum MappingsExportVerbosity { - MINIMAL, ROOTS, FULL; + MINIMAL, ROOTS, FULL } diff --git a/matcher-model/src/main/java/matcher/model/type/Analysis.java b/matcher-model/src/main/java/matcher/model/type/Analysis.java index 8abcd5ea..1e6fdc07 100644 --- a/matcher-model/src/main/java/matcher/model/type/Analysis.java +++ b/matcher-model/src/main/java/matcher/model/type/Analysis.java @@ -52,19 +52,19 @@ import matcher.model.NameType; import matcher.model.Util; -class Analysis { +final class Analysis { static void analyzeMethod(MethodInstance method, CommonClasses common) { MethodNode asmNode = method.getAsmNode(); if (asmNode == null || (asmNode.access & Opcodes.ACC_ABSTRACT) != 0 || asmNode.instructions.size() == 0) return; - logger.debug(method.getDisplayName(NameType.MAPPED_PLAIN, true)); + LOGGER.atDebug().log(() -> method.getDisplayName(NameType.MAPPED_PLAIN, true)); dump(asmNode); StateRecorder rec = new StateRecorder(method, common); InsnList il = asmNode.instructions; Map exitPoints = new IdentityHashMap<>(); - exitPoints.put(null, new int[] { 0 }); + exitPoints.put(null, new int[]{0}); Queue queue = new ArrayDeque<>(); queue.add(new QueueElement(0, rec.getState())); @@ -416,7 +416,7 @@ static void analyzeMethod(MethodInstance method, CommonClasses common) { if (handler != null) { int dstIdx = il.indexOf(handler); - if (!exitPoints.containsKey(ain)) exitPoints.put(ain, new int[] { dstIdx }); + if (!exitPoints.containsKey(ain)) exitPoints.put(ain, new int[]{dstIdx}); rec.jump(dstIdx); idx = dstIdx; } else { @@ -453,7 +453,7 @@ static void analyzeMethod(MethodInstance method, CommonClasses common) { case Opcodes.T_INT: arrayType = "[I"; break; case Opcodes.T_LONG: arrayType = "[J"; break; default: - throw new UnsupportedOperationException("unknown NEWARRAY operand: "+((IntInsnNode) ain).operand); + throw new UnsupportedOperationException("unknown NEWARRAY operand: " + ((IntInsnNode) ain).operand); } rec.push(method.getEnv().getCreateClassInstance(arrayType), rec.getNextVarId(VarSource.New)); @@ -491,10 +491,10 @@ static void analyzeMethod(MethodInstance method, CommonClasses common) { String desc = ((TypeInsnNode) ain).desc; if (desc.startsWith("[")) { - desc = "["+desc; + desc = "[" + desc; } else { assert !desc.startsWith("L"); - desc = "[L"+desc+";"; + desc = "[L" + desc + ";"; } rec.pop(); @@ -518,7 +518,7 @@ static void analyzeMethod(MethodInstance method, CommonClasses common) { case Opcodes.PUTFIELD: { FieldInsnNode in = (FieldInsnNode) ain; FieldInstance field = method.getEnv().getClsByName(in.owner).resolveField(in.name, in.desc); - boolean isWrite = (op == Opcodes.PUTFIELD || op == Opcodes.PUTSTATIC); + boolean isWrite = op == Opcodes.PUTFIELD || op == Opcodes.PUTSTATIC; if (isWrite) { // put* if (field.getType().getSlotSize() == 1) { @@ -603,17 +603,17 @@ static void analyzeMethod(MethodInstance method, CommonClasses common) { if (dstIdx != idx + 1) { if (op == Opcodes.GOTO) { - if (!exitPoints.containsKey(ain)) exitPoints.put(ain, new int[] { dstIdx }); + if (!exitPoints.containsKey(ain)) exitPoints.put(ain, new int[]{dstIdx}); if (!rec.jump(dstIdx)) break insnLoop; idx = dstIdx; } else { - if (!exitPoints.containsKey(ain)) exitPoints.put(ain, new int[] { dstIdx, idx + 1 }); + if (!exitPoints.containsKey(ain)) exitPoints.put(ain, new int[]{dstIdx, idx + 1}); QueueElement e = new QueueElement(dstIdx, rec.getState()); if (queued.add(e)) queue.add(e); } } else { // no-op jump - if (!exitPoints.containsKey(ain)) exitPoints.put(ain, new int[] { dstIdx }); + if (!exitPoints.containsKey(ain)) exitPoints.put(ain, new int[]{dstIdx}); } break; @@ -649,10 +649,10 @@ static void analyzeMethod(MethodInstance method, CommonClasses common) { rec.push(method.getEnv().getCreateClassInstance("Ljava/lang/invoke/MethodType;"), rec.getNextVarId(VarSource.Constant)); break; default: - throw new UnsupportedOperationException("unsupported type sort: "+type.getSort()); + throw new UnsupportedOperationException("unsupported type sort: " + type.getSort()); } } else { - throw new UnsupportedOperationException("unknown ldc constant type: "+val.getClass()); + throw new UnsupportedOperationException("unknown ldc constant type: " + val.getClass()); } break; @@ -731,7 +731,7 @@ static void analyzeMethod(MethodInstance method, CommonClasses common) { break; } default: - throw new UnsupportedOperationException("unknown opcode: "+ain.getOpcode()+" (type "+ain.getType()+")"); + throw new UnsupportedOperationException("unknown opcode: " + ain.getOpcode() + " (type " + ain.getType() + ")"); } if (!rec.next()) break; @@ -895,7 +895,7 @@ private static void applyTryCatchExits(MethodNode asmNode, BitSet entryPoints, M int dst = il.indexOf(n.handler); if (exits == null) { - exitPoints.put(ain, new int[] { dst, idx + 1 }); + exitPoints.put(ain, new int[]{dst, idx + 1}); } else { boolean found = false; @@ -929,7 +929,7 @@ private static void addDirectExits(InsnList il, BitSet entryPoints, Map 1 = not used) changed = true; int newLocalsSize = localsUsed.previousClearBit(state.locals.length - 1) + 1; - ClassInstance[] newLocals = newLocalsSize == 0 ? ExecState.empty : Arrays.copyOf(state.locals, newLocalsSize); - int[] newLocalVarIds = newLocalsSize == 0 ? ExecState.emptyIds : Arrays.copyOf(state.localVarIds, newLocalsSize); + ClassInstance[] newLocals = newLocalsSize == 0 ? ExecState.EMPTY : Arrays.copyOf(state.locals, newLocalsSize); + int[] newLocalVarIds = newLocalsSize == 0 ? ExecState.EMPTY_IDS : Arrays.copyOf(state.localVarIds, newLocalsSize); int idx = -1; while ((idx = localsUsed.nextSetBit(idx + 1)) != -1 && idx < newLocalsSize) { @@ -1018,7 +1018,7 @@ private static void purgeLocals(InsnList il, StateRecorder rec, BitSet entryPoin for (int i = 0; i < state.locals.length; i++) { if ((state.locals[i] != null) != localsSupplied.get(i)) { if (state.locals[i] == null) { - throw new IllegalStateException("missing local "+i); + throw new IllegalStateException("missing local " + i); } foundMismatch = true; @@ -1030,8 +1030,8 @@ private static void purgeLocals(InsnList il, StateRecorder rec, BitSet entryPoin changed = true; int newLocalsSize = localsSupplied.previousSetBit(state.locals.length - 1) + 1; - ClassInstance[] newLocals = newLocalsSize == 0 ? ExecState.empty : Arrays.copyOf(state.locals, newLocalsSize); - int[] newLocalVarIds = newLocalsSize == 0 ? ExecState.emptyIds : Arrays.copyOf(state.localVarIds, newLocalsSize); + ClassInstance[] newLocals = newLocalsSize == 0 ? ExecState.EMPTY : Arrays.copyOf(state.locals, newLocalsSize); + int[] newLocalVarIds = newLocalsSize == 0 ? ExecState.EMPTY_IDS : Arrays.copyOf(state.localVarIds, newLocalsSize); for (int i = 0; i < newLocals.length - 1; i++) { if (!localsSupplied.get(i)) { @@ -1145,13 +1145,22 @@ private static List createLocalVariables(InsnList il, StateRe lvToVar = null; - logger.debug("Local vars raw:"); + LOGGER.debug("Local vars raw:"); for (int i = 0; i < varCount; i++) { ExecState state = rec.getState(startIndices[i]); + int lv = varToLv[i]; + int startIdx = startIndices[i]; + int endIdx = endIndices[i]; - logger.debug(" {}: LV {} @ {} - {}: {}\t\t({})", - i, varToLv[i], startIndices[i], endIndices[i], state.locals[varToLv[i]].toString(), rec.varSources[state.localVarIds[varToLv[i]] - 1].name()); + LOGGER.atDebug() + .addArgument(i) + .addArgument(() -> lv) + .addArgument(() -> startIdx) + .addArgument(() -> endIdx) + .addArgument(state.locals[lv]::toString) + .addArgument(rec.varSources[state.localVarIds[lv] - 1]::name) + .log(" {}: LV {} @ {} - {}: {}\t\t({})"); } // merge variables if they are adjacent and reachable without interruption, TODO: this currently only merges blocks that are reachable by the preceding block, the other way is also possible @@ -1256,13 +1265,22 @@ private static List createLocalVariables(InsnList il, StateRe } } - logger.debug("Local vars:"); + LOGGER.debug("Local vars:"); for (int i = 0; i < varCount; i++) { ExecState state = rec.getState(startIndices[i]); + int lv = varToLv[i]; + int startIdx = startIndices[i]; + int endIdx = endIndices[i]; - logger.debug(" {}: LV {} @ {} - {}: {}\t\t({})", - i, varToLv[i], startIndices[i], endIndices[i], state.locals[varToLv[i]].toString(), rec.varSources[state.localVarIds[varToLv[i]] - 1].name()); + LOGGER.atDebug() + .addArgument(i) + .addArgument(() -> lv) + .addArgument(() -> startIdx) + .addArgument(() -> endIdx) + .addArgument(state.locals[lv]::toString) + .addArgument(rec.varSources[state.localVarIds[lv] - 1]::name) + .log(" {}: LV {} @ {} - {}: {}\t\t({})"); } if (orig != null) { @@ -1283,14 +1301,14 @@ private static List createLocalVariables(InsnList il, StateRe } if (!mismatch) { - logger.debug("Existing vars matched!"); + LOGGER.debug("Existing vars matched!"); } else { - logger.debug("Existing vars mismatch:"); + LOGGER.debug("Existing vars mismatch:"); for (int i = 0; i < orig.size(); i++) { LocalVariableNode lvn = orig.get(i); - logger.debug(" {}: LV {} @ {} - {}: {}", + LOGGER.debug(" {}: LV {} @ {} - {}: {}", i, lvn.index, il.indexOf(lvn.start), il.indexOf(lvn.end) - 1, lvn.desc); } } @@ -1604,7 +1622,7 @@ private ExecState mergeStates(ExecState oldState) { ClassInstance commonCls = getCommonSuperClass(a, b); if (commonCls == null) { - throw new IllegalStateException("incompatible stack types: "+a+" "+b); + throw new IllegalStateException("incompatible stack types: " + a + " " + b); } if (commonCls != a) { @@ -1658,7 +1676,7 @@ private void recordVarIdMap(int srcId, int dstId) { if (srcId >= varIdMap.length) varIdMap = Arrays.copyOf(varIdMap, Math.max(varIdMap.length * 2, srcId + 1)); - for (;;) { + while (true) { int prev = varIdMap[srcId]; if (prev == dstId) { @@ -1856,13 +1874,13 @@ public void dump(InsnList il) { sb.append(((LineNumberNode) ain).line); break; default: - throw new UnsupportedOperationException("unknown insn: "+ain); + throw new UnsupportedOperationException("unknown insn: " + ain); } sb.append('\n'); } - logger.debug(sb.toString()); + LOGGER.atDebug().log(sb::toString); } private void dumpVars(ClassInstance[] types, int[] ids, StringBuilder sb) { @@ -1889,7 +1907,7 @@ private void dumpVars(ClassInstance[] types, int[] ids, StringBuilder sb) { sb.append(':'); if (type != common.NULL) { - sb.append(type.toString()); + sb.append(type); } else { sb.append("null"); } @@ -1897,7 +1915,7 @@ private void dumpVars(ClassInstance[] types, int[] ids, StringBuilder sb) { } sb.append(']'); - logger.debug(sb.toString()); + LOGGER.atDebug().log(sb::toString); } final ExecState[] states; // state at the start of every instruction index @@ -1925,15 +1943,15 @@ private static class Variable { } private enum VarSource { - Constant, Arg, Merge, ExtException, IntException, ArrayElement, Cast, Computed, New, Field, MethodRet; + Constant, Arg, Merge, ExtException, IntException, ArrayElement, Cast, Computed, New, Field, MethodRet } private static class ExecState { ExecState(ClassInstance[] locals, int[] localVarIds, int localsSize, ClassInstance[] stack, int[] stackVarIds, int stackSize) { - this((localsSize != 0 ? Arrays.copyOf(locals, localsSize) : empty), - (localsSize != 0 ? Arrays.copyOf(localVarIds, localsSize) : emptyIds), - (stackSize != 0 ? Arrays.copyOf(stack, stackSize) : empty), - (stackSize != 0 ? Arrays.copyOf(stackVarIds, stackSize) : emptyIds)); + this(localsSize != 0 ? Arrays.copyOf(locals, localsSize) : EMPTY, + localsSize != 0 ? Arrays.copyOf(localVarIds, localsSize) : EMPTY_IDS, + stackSize != 0 ? Arrays.copyOf(stack, stackSize) : EMPTY, + stackSize != 0 ? Arrays.copyOf(stackVarIds, stackSize) : EMPTY_IDS); } ExecState(ClassInstance[] locals, int[] localVarIds, ClassInstance[] stack, int[] stackVarIds) { @@ -1963,8 +1981,8 @@ public int hashCode() { return Arrays.hashCode(locals) ^ Arrays.hashCode(stack); } - private static final ClassInstance[] empty = new ClassInstance[0]; - private static final int[] emptyIds = new int[0]; + private static final ClassInstance[] EMPTY = new ClassInstance[0]; + private static final int[] EMPTY_IDS = new int[0]; final ClassInstance[] locals; final int[] localVarIds; @@ -1980,12 +1998,10 @@ static void checkInitializer(FieldInstance field, ClassFeatureExtractor context) InsnList il = asmNode.instructions; AbstractInsnNode fieldWrite = null; - //dump(method.asmNode); - //Matcher.LOGGER.debug("\n------------------------\n"); - - for (Iterator it = il.iterator(); it.hasNext(); ) { - AbstractInsnNode aInsn = it.next(); + // dump(method.asmNode); + // LOGGER.debug("\n------------------------\n"); + for (AbstractInsnNode aInsn : il) { if (aInsn.getOpcode() == Opcodes.PUTFIELD || aInsn.getOpcode() == Opcodes.PUTSTATIC) { FieldInsnNode in = (FieldInsnNode) aInsn; ClassInstance cls; @@ -2001,7 +2017,7 @@ static void checkInitializer(FieldInstance field, ClassFeatureExtractor context) if (fieldWrite == null) { dump(asmNode); - throw new IllegalStateException("can't find field write insn for "+field+" in "+method); + throw new IllegalStateException("can't find field write insn for " + field + " in " + method); } Interpreter interpreter = new SourceInterpreter(); @@ -2076,19 +2092,19 @@ static void checkInitializer(FieldInstance field, ClassFeatureExtractor context) } } - //Textifier textifier = new Textifier(); - //MethodVisitor visitor = new TraceMethodVisitor(textifier); - List initIl = new ArrayList(tracedPositions.cardinality()); + // Textifier textifier = new Textifier(); + // MethodVisitor visitor = new TraceMethodVisitor(textifier); + List initIl = new ArrayList<>(tracedPositions.cardinality()); int pos = 0; while ((pos = tracedPositions.nextSetBit(pos)) != -1) { in = il.get(pos); initIl.add(in); - /*Matcher.LOGGER.debug(pos+": "); + /*LOGGER.debug(pos+": "); il.get(pos).accept(visitor); - Matcher.LOGGER.debug(textifier.getText().get(0)); + LOGGER.debug(textifier.getText().get(0)); textifier.getText().clear();*/ pos++; @@ -2099,7 +2115,7 @@ static void checkInitializer(FieldInstance field, ClassFeatureExtractor context) /* int pos = fieldWritePos; for (int i = 0; i < 100; i++) { - Matcher.LOGGER.debug(i+" ("+pos+"):"); + LOGGER.debug(i+" ("+pos+"):"); Frame frame = frames[pos]; Frame nextFrame = frames[pos + 1]; @@ -2109,24 +2125,24 @@ static void checkInitializer(FieldInstance field, ClassFeatureExtractor context) SourceValue value = frame.getStack(frame.getStackSize() - 1); if (value.insns.isEmpty()) { - Matcher.LOGGER.debug("empty"); + LOGGER.debug("empty"); break; } for (AbstractInsnNode ain : value.insns) { ain.accept(visitor); - Matcher.LOGGER.debug(textifier.getText().get(0)); + LOGGER.debug(textifier.getText().get(0)); textifier.getText().clear(); } pos = method.asmNode.instructions.indexOf(value.insns.iterator().next()); }*/ - /*Matcher.LOGGER.debug(frame); - Matcher.LOGGER.debug("\n------------------------\n"); + /*LOGGER.debug(frame); + LOGGER.debug("\n------------------------\n"); dump(frame.getStack(frame.getStackSize() - 1).insns);*/ - //Matcher.LOGGER.debug(); + // LOGGER.debug(); } private static int getStackDemand(AbstractInsnNode ain, Frame frame) { @@ -2274,7 +2290,7 @@ private static int getStackDemand(AbstractInsnNode ain, Frame frame) { case Opcodes.MONITOREXIT: return 1; default: - throw new IllegalArgumentException("unknown insn opcode "+ain.getOpcode()); + throw new IllegalArgumentException("unknown insn opcode " + ain.getOpcode()); } case AbstractInsnNode.INT_INSN: switch (ain.getOpcode()) { @@ -2284,7 +2300,7 @@ private static int getStackDemand(AbstractInsnNode ain, Frame frame) { case Opcodes.NEWARRAY: return 1; // +1 default: - throw new IllegalArgumentException("unknown int insn opcode "+ain.getOpcode()); + throw new IllegalArgumentException("unknown int insn opcode " + ain.getOpcode()); } case AbstractInsnNode.VAR_INSN: switch (ain.getOpcode()) { @@ -2303,7 +2319,7 @@ private static int getStackDemand(AbstractInsnNode ain, Frame frame) { case Opcodes.RET: return 0; default: - throw new IllegalArgumentException("unknown var insn opcode "+ain.getOpcode()); + throw new IllegalArgumentException("unknown var insn opcode " + ain.getOpcode()); } case AbstractInsnNode.TYPE_INSN: switch (ain.getOpcode()) { @@ -2315,7 +2331,7 @@ private static int getStackDemand(AbstractInsnNode ain, Frame frame) { case Opcodes.INSTANCEOF: return 1; // +1 default: - throw new IllegalArgumentException("unknown type insn opcode "+ain.getOpcode()); + throw new IllegalArgumentException("unknown type insn opcode " + ain.getOpcode()); } case AbstractInsnNode.FIELD_INSN: switch (ain.getOpcode()) { @@ -2328,7 +2344,7 @@ private static int getStackDemand(AbstractInsnNode ain, Frame frame) { case Opcodes.PUTFIELD: return 2; default: - throw new IllegalArgumentException("unknown field insn opcode "+ain.getOpcode()); + throw new IllegalArgumentException("unknown field insn opcode " + ain.getOpcode()); } case AbstractInsnNode.METHOD_INSN: return Type.getArgumentTypes(((MethodInsnNode) ain).desc).length + (ain.getOpcode() != Opcodes.INVOKESTATIC ? 1 : 0); // +1 if ret type != void @@ -2360,7 +2376,7 @@ private static int getStackDemand(AbstractInsnNode ain, Frame frame) { case Opcodes.IFNONNULL: return 1; default: - throw new IllegalArgumentException("unknown jump insn opcode "+ain.getOpcode()); + throw new IllegalArgumentException("unknown jump insn opcode " + ain.getOpcode()); } case AbstractInsnNode.LABEL: return 0; @@ -2379,7 +2395,7 @@ private static int getStackDemand(AbstractInsnNode ain, Frame frame) { case AbstractInsnNode.LINE: return 0; default: - throw new IllegalArgumentException("unknown insn type "+ain.getType()+" for opcode "+ain.getOpcode()+", in "+ain.getClass().getName()); + throw new IllegalArgumentException("unknown insn type " + ain.getType() + " for opcode " + ain.getOpcode() + ", in " + ain.getClass().getName()); } } @@ -2393,15 +2409,14 @@ private static void dump(MethodNode method) { textifier.print(pw); } - logger.debug(writer.toString()); + LOGGER.atDebug().log(writer::toString); } private static void dump(Iterable il) { Textifier textifier = new Textifier(); MethodVisitor visitor = new TraceMethodVisitor(textifier); - for (Iterator it = il.iterator(); it.hasNext(); ) { - AbstractInsnNode in = it.next(); + for (AbstractInsnNode in : il) { in.accept(visitor); } @@ -2411,8 +2426,11 @@ private static void dump(Iterable il) { textifier.print(pw); } - logger.debug(writer.toString()); + LOGGER.atDebug().log(writer::toString); + } + + private Analysis() { } - private static final Logger logger = LoggerFactory.getLogger(Analysis.class); + private static final Logger LOGGER = LoggerFactory.getLogger(Analysis.class); } diff --git a/matcher-model/src/main/java/matcher/model/type/ClassEnvironment.java b/matcher-model/src/main/java/matcher/model/type/ClassEnvironment.java index 3fd8dfc9..f783a42d 100644 --- a/matcher-model/src/main/java/matcher/model/type/ClassEnvironment.java +++ b/matcher-model/src/main/java/matcher/model/type/ClassEnvironment.java @@ -10,7 +10,6 @@ import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.AbstractCollection; import java.util.ArrayList; import java.util.Collection; @@ -80,7 +79,7 @@ public void init(ProjectConfig config, DoubleConsumer progressReceiver) { extractorB.process(nonObfuscatedMemberPatternB); progressReceiver.accept(0.98); - } catch (InterruptedException | ExecutionException | IOException e) { + } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); } finally { classPathIndex.clear(); @@ -91,13 +90,13 @@ public void init(ProjectConfig config, DoubleConsumer progressReceiver) { progressReceiver.accept(1); } - private void initClassPath(Collection sharedClassPath, boolean checkExisting) throws IOException { + private void initClassPath(Collection sharedClassPath, boolean checkExisting) { for (Path archive : sharedClassPath) { cpFiles.add(new InputFile(archive)); FileSystem fs = Util.iterateJar(archive, false, file -> { String name = file.toAbsolutePath().toString(); - if (!name.startsWith("/") || !name.endsWith(".class") || name.startsWith("//")) throw new RuntimeException("invalid path: "+archive+" ("+name+")"); + if (!name.startsWith("/") || !name.endsWith(".class") || name.startsWith("//")) throw new RuntimeException("invalid path: " + archive + " (" + name + ")"); name = name.substring(1, name.length() - ".class".length()); if (!checkExisting || extractorA.getLocalClsByName(name) == null || extractorB.getLocalClsByName(name) == null) { @@ -171,10 +170,10 @@ public LocalClassEnv getEnvB() { @Override public Collection getClasses() { - return new AbstractCollection() { + return new AbstractCollection<>() { @Override public Iterator iterator() { - return new Iterator() { + return new Iterator<>() { @Override public boolean hasNext() { checkAdvance(); @@ -322,7 +321,7 @@ public String decompile(Decompiler decompiler, ClassInstance cls, NameType nameT } else if (extractorB.getLocalClsById(cls.getId()) == cls) { extractor = extractorB; } else { - throw new IllegalArgumentException("unknown class: "+cls); + throw new IllegalArgumentException("unknown class: " + cls); } return decompiler.decompile(cls, extractor, nameType); @@ -354,7 +353,7 @@ static ClassInstance getArrayCls(ClassEnv env, String id) { assert id.startsWith("["); String elementId = id.substring(id.lastIndexOf('[') + 1); - if (elementId.isEmpty()) throw new IllegalArgumentException("invalid class desc: "+id); + if (elementId.isEmpty()) throw new IllegalArgumentException("invalid class desc: " + id); assert elementId.length() == 1 || elementId.charAt(elementId.length() - 1) == ';' : elementId; return env.getCreateClassInstance(elementId); @@ -373,7 +372,7 @@ ClassInstance getMissingCls(String id, boolean createUnknown) { Path file = getSharedClassLocation(name); if (file == null) { - URL url = ClassLoader.getSystemResource(name+".class"); + URL url = ClassLoader.getSystemResource(name + ".class"); if (url != null) { file = getPath(url); @@ -383,7 +382,7 @@ ClassInstance getMissingCls(String id, boolean createUnknown) { if (file != null) { ClassNode cn = readClass(file, true); ClassInstance cls = new ClassInstance(ClassInstance.getId(cn.name), getContainingUri(file.toUri(), cn.name), this, cn); - if (!cls.getId().equals(id)) throw new RuntimeException("mismatched cls id "+id+" for "+file+", expected "+name); + if (!cls.getId().equals(id)) throw new RuntimeException("mismatched cls id " + id + " for " + file + ", expected " + name); ClassInstance ret = addSharedCls(cls); @@ -408,11 +407,11 @@ private Path getPath(URL url) { try { uri = url.toURI(); - Path ret = Paths.get(uri); + Path ret = Path.of(uri); if (uri.getScheme().equals("jrt") && !Files.exists(ret)) { // workaround for https://bugs.openjdk.java.net/browse/JDK-8224946 - ret = Paths.get(new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), "/modules".concat(uri.getPath()), uri.getQuery(), uri.getFragment())); + ret = Path.of(new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), "/modules".concat(uri.getPath()), uri.getQuery(), uri.getFragment())); } return ret; @@ -422,9 +421,9 @@ private Path getPath(URL url) { try { addOpenFileSystem(FileSystems.newFileSystem(uri, Collections.emptyMap())); - return Paths.get(uri); + return Path.of(uri); } catch (FileSystemNotFoundException e2) { - throw new RuntimeException("can't find fs for "+url, e2); + throw new RuntimeException("can't find fs for " + url, e2); } catch (IOException e2) { throw new UncheckedIOException(e2); } @@ -445,20 +444,20 @@ static URI getContainingUri(URI uri, String clsName) { throw new RuntimeException(e); } } else { - throw new UnsupportedOperationException("jar uri without !/: "+uri); + throw new UnsupportedOperationException("jar uri without !/: " + uri); } } else { path = uri.getPath(); } if (path == null) { - throw new UnsupportedOperationException("uri without path: "+uri); + throw new UnsupportedOperationException("uri without path: " + uri); } int rootPos = path.length() - ".class".length() - clsName.length(); if (rootPos <= 0 || !path.endsWith(".class") || !path.startsWith(clsName, rootPos)) { - throw new UnsupportedOperationException("unknown path format: "+uri); + throw new UnsupportedOperationException("unknown path format: " + uri); } path = path.substring(0, rootPos - 1); @@ -508,7 +507,7 @@ static void processClassA(ClassInstance cls, Pattern nonObfuscatedMemberPattern) && !mn.name.equals("") && (!mn.name.equals("main") || !mn.desc.equals("([Ljava/lang/String;)V") || mn.access != (Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC)) && (!isEnum || !isStandardEnumMethod(cn.name, mn)) - && (nonObfuscatedMemberPattern == null || !nonObfuscatedMemberPattern.matcher(cn.name+"/"+mn.name+mn.desc).matches()); + && (nonObfuscatedMemberPattern == null || !nonObfuscatedMemberPattern.matcher(cn.name + "/" + mn.name + mn.desc).matches()); cls.addMethod(new MethodInstance(cls, mn.name, mn.desc, mn, nameObfuscated, i)); @@ -521,7 +520,7 @@ static void processClassA(ClassInstance cls, Pattern nonObfuscatedMemberPattern) if (cls.getField(fn.name, fn.desc) == null) { boolean nameObfuscated = cls.isInput() - && (nonObfuscatedMemberPattern == null || !nonObfuscatedMemberPattern.matcher(cn.name+"/"+fn.name+";;"+fn.desc).matches()); + && (nonObfuscatedMemberPattern == null || !nonObfuscatedMemberPattern.matcher(cn.name + "/" + fn.name + ";;" + fn.desc).matches()); cls.addField(new FieldInstance(cls, fn.name, fn.desc, fn, nameObfuscated, i)); @@ -587,7 +586,7 @@ private static void addOuterClass(ClassInstance cls, String name, boolean create outerClass = cls.getEnv().getCreateClassInstance(ClassInstance.getId(name), createUnknown); if (outerClass == null) { - logger.error("Missing outer cls: {} for {}", name, cls); + LOGGER.warn("Missing outer class {} for {}", name, cls); return; } } @@ -615,7 +614,7 @@ public MatchingCache getCache() { return cache; } - private static final Logger logger = LoggerFactory.getLogger(ClassEnvironment.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ClassEnvironment.class); private final List cpFiles = new ArrayList<>(); private final Map sharedClasses = new HashMap<>(); private final List openFileSystems = new ArrayList<>(); @@ -630,13 +629,13 @@ public MatchingCache getCache() { private Pattern nonObfuscatedMemberPatternA; private Pattern nonObfuscatedMemberPatternB; - public boolean assumeBothOrNoneObfuscated = false; + public boolean assumeBothOrNoneObfuscated; - public String classUidPrefix = "class_"; - public String methodUidPrefix = "method_"; - public String fieldUidPrefix = "field_"; - public String argUidPrefix = "arg_"; - public String varUidPrefix = "var_"; + public static final String CLASS_UID_PREFIX = "class_"; + public static final String METHOD_UID_PREFIX = "method_"; + public static final String FIELD_UID_PREFIX = "field_"; + public static final String ARG_UID_PREFIX = "arg_"; + public static final String VAR_UID_PREFIX = "var_"; public int nextClassUid; public int nextMethodUid; public int nextFieldUid; diff --git a/matcher-model/src/main/java/matcher/model/type/ClassFeatureExtractor.java b/matcher-model/src/main/java/matcher/model/type/ClassFeatureExtractor.java index 43e6e404..689145e3 100644 --- a/matcher-model/src/main/java/matcher/model/type/ClassFeatureExtractor.java +++ b/matcher-model/src/main/java/matcher/model/type/ClassFeatureExtractor.java @@ -9,7 +9,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -73,7 +72,7 @@ public void processClassPath(Collection classPath, boolean checkExisting) FileSystem fs = Util.iterateJar(archive, false, file -> { String name = file.toAbsolutePath().toString(); - if (!name.startsWith("/") || !name.endsWith(".class") || name.startsWith("//")) throw new RuntimeException("invalid path: "+archive+" ("+name+")"); + if (!name.startsWith("/") || !name.endsWith(".class") || name.startsWith("//")) throw new RuntimeException("invalid path: " + archive + " (" + name + ")"); name = name.substring(1, name.length() - ".class".length()); if (!checkExisting || getLocalClsByName(name) == null && env.getSharedClassLocation(name) == null && env.getLocalClsByName(name) == null) { @@ -242,13 +241,11 @@ private void processClassB(ClassInstance cls) { private void processMethodInsns(MethodInstance method) { if (!method.isReal()) { // artificial method to capture calls to types with incomplete/unknown hierarchy/super type method info - logger.debug("Skipping empty method {}", method); + LOGGER.debug("Skipping empty method {}", method); return; } - for (Iterator it = method.getAsmNode().instructions.iterator(); it.hasNext(); ) { - AbstractInsnNode ain = it.next(); - + for (AbstractInsnNode ain : method.getAsmNode().instructions) { switch (ain.getType()) { case AbstractInsnNode.METHOD_INSN: { MethodInsnNode in = (MethodInsnNode) ain; @@ -305,7 +302,7 @@ private void processMethodInsns(MethodInstance method) { Util.isCallToInterface(impl), impl.getTag() == Opcodes.H_INVOKESTATIC); break; default: - logger.warn("Unexpected impl tag: {}", impl.getTag()); + LOGGER.warn("Unexpected impl tag: {}", impl.getTag()); } break; @@ -330,7 +327,7 @@ private MethodInstance resolveMethod(String owner, String name, String desc, boo MethodInstance ret = cls.resolveMethod(name, desc, toInterface); if (ret == null && create) { - logger.trace("Creating synthetic method {}/{}{}", owner, name, desc); + LOGGER.trace("Creating synthetic method {}/{}{}", owner, name, desc); ret = new MethodInstance(cls, name, desc, isStatic); cls.addMethod(ret); @@ -377,7 +374,7 @@ private static void processClassC(ClassInstance cls) { if (isHierarchyBarrier(method)) { if (method.hierarchyData == null) { - method.hierarchyData = new MemberHierarchyData<>(Collections.singleton(method), method.nameObfuscatedLocal); + method.hierarchyData = new MemberHierarchyData<>(Set.of(method), method.nameObfuscatedLocal); } } else if ((prev = methods.get(method.id)) != null) { if (method.hierarchyData == null) { @@ -438,11 +435,11 @@ private void processClassD(ClassInstance cls, CommonClasses common) { } determineMethodType(method); - //Analysis.analyzeMethod(method, common); + // Analysis.analyzeMethod(method, common); } for (FieldInstance field : cls.getFields()) { - field.hierarchyData = new MemberHierarchyData<>(Collections.singleton(field), field.nameObfuscatedLocal); + field.hierarchyData = new MemberHierarchyData<>(Set.of(field), field.nameObfuscatedLocal); if (field.writeRefs.size() == 1) { Analysis.checkInitializer(field, this); @@ -499,9 +496,7 @@ private boolean isLambdaMethod(MethodInstance method) { for (MethodInstance m : method.refsIn) { boolean found = false; - for (Iterator it = m.getAsmNode().instructions.iterator(); it.hasNext(); ) { - AbstractInsnNode ain = it.next(); - + for (AbstractInsnNode ain : m.getAsmNode().instructions) { switch (ain.getType()) { case AbstractInsnNode.METHOD_INSN: if (resolveMethod((MethodInsnNode) ain) == method) return false; @@ -548,7 +543,7 @@ private void processClassE(ClassInstance cls, int clsIndex, AtomicInteger vmIdx) if (cls.isNameObfuscated()) { assert clsIndex >= 0; - cls.setTmpName("c"+envName+clsIndex); + cls.setTmpName("c" + envName + clsIndex); } int memberIndex = 0; @@ -559,7 +554,7 @@ private void processClassE(ClassInstance cls, int clsIndex, AtomicInteger vmIdx) assert !method.getName().equals("") && !method.getName().equals(""); if (method.getAllHierarchyMembers().size() == 1) { - method.setTmpName("m"+envName+memberIndex); + method.setTmpName("m" + envName + memberIndex); memberIndex++; } else if (!method.hasLocalTmpName()) { String name = "vm"+envName+vmIdx.getAndIncrement(); @@ -574,7 +569,7 @@ private void processClassE(ClassInstance cls, int clsIndex, AtomicInteger vmIdx) assert field.getAllHierarchyMembers().size() == 1; - field.setTmpName("f"+envName+memberIndex); + field.setTmpName("f" + envName + memberIndex); memberIndex++; } @@ -644,7 +639,7 @@ public ClassInstance getClsById(String id, NameType nameType) { @Override public ClassInstance getCreateClassInstance(String id, boolean createUnknown) { - if (id.length() == 0) throw new IllegalArgumentException("empty class desc"); + if (id.isEmpty()) throw new IllegalArgumentException("empty class desc"); assert id.length() == 1 || id.charAt(id.length() - 1) == ';' || id.charAt(0) == '[' && id.lastIndexOf('[') == id.length() - 2 : id; ClassInstance ret; @@ -680,7 +675,7 @@ public ClassInstance getCreateClassInstance(String id, boolean createUnknown) { if (sharedRet != null) return sharedRet; // create shared missing class - //ret = env.getMissingCls(id, createUnknown); + // ret = env.getMissingCls(id, createUnknown); // try shared jvm-cp class if ((ret = env.getMissingCls(id, false)) != null || !createUnknown) return ret; @@ -703,7 +698,7 @@ private ClassInstance createClassPathClass(String id) { ClassNode cn = ClassEnvironment.readClass(file, false); ClassInstance cls = new ClassInstance(ClassInstance.getId(cn.name), ClassEnvironment.getContainingUri(file.toUri(), cn.name), this, cn); - if (!cls.getId().equals(id)) throw new RuntimeException("mismatched cls id "+id+" for "+file+", expected "+name); + if (!cls.getId().equals(id)) throw new RuntimeException("mismatched cls id " + id + " for " + file + ", expected " + name); ClassInstance prev = classes.putIfAbsent(cls.getId(), cls); assert prev == null; @@ -724,7 +719,7 @@ public ClassEnv getOther() { return this == env.getEnvA() ? env.getEnvB() : env.getEnvA(); } - private static final Logger logger = LoggerFactory.getLogger(ClassFeatureExtractor.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ClassFeatureExtractor.class); final ClassEnvironment env; private final List inputFiles = new ArrayList<>(); private final List cpFiles = new ArrayList<>(); diff --git a/matcher-model/src/main/java/matcher/model/type/ClassInstance.java b/matcher-model/src/main/java/matcher/model/type/ClassInstance.java index ceec9c83..c0b7c7de 100644 --- a/matcher-model/src/main/java/matcher/model/type/ClassInstance.java +++ b/matcher-model/src/main/java/matcher/model/type/ClassInstance.java @@ -121,7 +121,7 @@ public String getName(NameType type, boolean includeOuter) { return ret.toString(); } else if (type == NameType.UID_PLAIN) { int uid = getUid(); - if (uid >= 0) return env.getGlobal().classUidPrefix+uid; + if (uid >= 0) return ClassEnvironment.CLASS_UID_PREFIX +uid; } boolean locTmp = type == NameType.MAPPED_LOCTMP_PLAIN || type == NameType.LOCTMP_PLAIN; @@ -226,7 +226,7 @@ public String getDisplayName(NameType type, boolean full) { case 'S': ret = "short"; break; case 'V': ret = "void"; break; case 'Z': ret = "boolean"; break; - default: throw new IllegalStateException("invalid class desc: "+id); + default: throw new IllegalStateException("invalid class desc: " + id); } } else { ret = getName(type).replace('/', '.'); @@ -249,9 +249,7 @@ public String getDisplayName(NameType type, boolean full) { sb.append(ret, dims + 1, ret.length() - 1); } - for (int i = 0; i < dims; i++) { - sb.append("[]"); - } + sb.append("[]".repeat(dims)); ret = sb.toString(); } @@ -417,7 +415,7 @@ public boolean isPrimitive() { public int getSlotSize() { char start = id.charAt(0); - return (start == 'D' || start == 'J') ? 2 : 1; + return start == 'D' || start == 'J' ? 2 : 1; } public boolean isArray() { @@ -431,7 +429,7 @@ public int getArrayDimensions() { if (id.charAt(i) != '[') return i; } - throw new IllegalStateException("invalid id: "+id); + throw new IllegalStateException("invalid id: " + id); } public ClassInstance[] getArrays() { @@ -730,14 +728,7 @@ private MethodInstance resolveInterfaceMethod(String name, String desc) { // non-abstract methods take precedence over non-abstract methods, remove all abstract ones if there's at least 1 non-abstract if (foundNonAbstract) { - for (Iterator it = matches.iterator(); it.hasNext(); ) { - MethodInstance m = it.next(); - - if (!m.isReal() || (m.access & Opcodes.ACC_ABSTRACT) != 0) { - it.remove(); - } - } - + matches.removeIf(m -> !m.isReal() || (m.access & Opcodes.ACC_ABSTRACT) != 0); assert !matches.isEmpty(); if (matches.size() == 1) return matches.iterator().next(); } @@ -779,8 +770,7 @@ public FieldInstance resolveField(String name, String desc) { if (ret != null) return ret; if (!interfaces.isEmpty()) { - Deque queue = new ArrayDeque<>(); - queue.addAll(interfaces); + Deque queue = new ArrayDeque<>(interfaces); ClassInstance cls; while ((cls = queue.pollFirst()) != null) { @@ -1052,7 +1042,7 @@ public ClassInstance getCommonSuperClass(ClassInstance o) { } if (!ret.isEmpty()) { - if (ret.size() >= 1) { + if (ret.size() > 1) { for (Iterator it = ret.iterator(); it.hasNext(); ) { cls = it.next(); @@ -1076,9 +1066,9 @@ public ClassInstance getCommonSuperClass(ClassInstance o) { public void accept(ClassVisitor visitor, NameType nameType) { ClassNode cn = getMergedAsmNode(); - if (cn == null) throw new IllegalArgumentException("cls without asm node: "+this); + if (cn == null) throw new IllegalArgumentException("cls without asm node: " + this); - synchronized (Util.asmNodeSync) { + synchronized (Util.ASM_NODE_SYNC) { if (nameType != NameType.PLAIN) { AsmClassRemapper.process(cn, new AsmRemapper(env, nameType), visitor); } else { @@ -1103,7 +1093,7 @@ void addMethod(MethodInstance method) { if (method == null) throw new NullPointerException("null method"); MethodInstance prev = methodIdx.putIfAbsent(method.id, method); - if (prev != null) throw new IllegalStateException("duplicate method "+method.id); + if (prev != null) throw new IllegalStateException("duplicate method " + method.id); methods = Arrays.copyOf(methods, methods.length + 1); methods[methods.length - 1] = method; @@ -1113,7 +1103,7 @@ void addField(FieldInstance field) { if (field == null) throw new NullPointerException("null field"); FieldInstance prev = fieldIdx.putIfAbsent(field.id, field); - if (prev != null) throw new IllegalStateException("duplicate field "+field.id); + if (prev != null) throw new IllegalStateException("duplicate field " + field.id); fields = Arrays.copyOf(fields, fields.length + 1); fields[fields.length - 1] = field; @@ -1172,11 +1162,11 @@ public static String getClassName(String name) { return name.substring(name.lastIndexOf('/') + 1); } - public static final Comparator nameComparator = Comparator.comparing(ClassInstance::getName); + public static final Comparator NAME_COMPARATOR = Comparator.comparing(ClassInstance::getName); - private static final ClassInstance[] noArrays = new ClassInstance[0]; - private static final MethodInstance[] noMethods = new MethodInstance[0]; - private static final FieldInstance[] noFields = new FieldInstance[0]; + private static final ClassInstance[] NO_ARRAYS = new ClassInstance[0]; + private static final MethodInstance[] NO_METHODS = new MethodInstance[0]; + private static final FieldInstance[] NO_FIELDS = new FieldInstance[0]; final String id; private final URI origin; @@ -1188,12 +1178,12 @@ public static String getClassName(String name) { final ClassInstance elementClass; // 0-dim class TODO: improve handling of array classes (references etc.) private ClassSignature signature; - MethodInstance[] methods = noMethods; - FieldInstance[] fields = noFields; + MethodInstance[] methods = NO_METHODS; + FieldInstance[] fields = NO_FIELDS; final Map methodIdx = new HashMap<>(); final Map fieldIdx = new HashMap<>(); - private ClassInstance[] arrays = noArrays; + private ClassInstance[] arrays = NO_ARRAYS; ClassInstance outerClass; final Set innerClasses = Util.newIdentityHashSet(); diff --git a/matcher-model/src/main/java/matcher/model/type/FieldInstance.java b/matcher-model/src/main/java/matcher/model/type/FieldInstance.java index dfc6c492..91763603 100644 --- a/matcher-model/src/main/java/matcher/model/type/FieldInstance.java +++ b/matcher-model/src/main/java/matcher/model/type/FieldInstance.java @@ -48,13 +48,9 @@ public MatchableKind getKind() { @Override public String getDisplayName(NameType type, boolean full) { - StringBuilder ret = new StringBuilder(64); - - ret.append(super.getDisplayName(type, full)); - ret.append(' '); - ret.append(this.type.getDisplayName(type, full)); - - return ret.toString(); + return super.getDisplayName(type, full) + + ' ' + + this.type.getDisplayName(type, full); } @Override @@ -145,7 +141,7 @@ protected String getUidString() { int uid = getUid(); if (uid < 0) return null; - return cls.env.getGlobal().fieldUidPrefix+uid; + return ClassEnvironment.FIELD_UID_PREFIX +uid; } @Override diff --git a/matcher-model/src/main/java/matcher/model/type/InputFile.java b/matcher-model/src/main/java/matcher/model/type/InputFile.java index 090ec6fc..aeca5e03 100644 --- a/matcher-model/src/main/java/matcher/model/type/InputFile.java +++ b/matcher-model/src/main/java/matcher/model/type/InputFile.java @@ -13,7 +13,6 @@ import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.security.MessageDigest; @@ -56,19 +55,19 @@ public static List resolve(Collection inputFiles, Collection inputDirs) throws IOException { for (Path inputDir : inputDirs) { Files.walkFileTree(inputDir, new SimpleFileVisitor<>() { - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { if (InputFile.this.equals(file)) { res.set(file); @@ -141,11 +141,11 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO try { return downloadToTmp(url); } catch (IOException | InterruptedException e) { - throw new IOException("download of "+url+" failed: "+e.toString()); + throw new IOException("download of " + url + " failed: " + e); } } - throw new IOException("can't find input "+this); + throw new IOException("can't find input " + this); } public boolean hasPath() { @@ -221,7 +221,7 @@ public MessageDigest createDigest() { } public byte[] hash(Path path) throws IOException { - TlData tlData = tlDatas.get(); + TlData tlData = TL_DATAS.get(); MessageDigest digest = tlData.digests.get(this); ByteBuffer buffer = tlData.buffer; @@ -251,7 +251,7 @@ private static class TlData { final ByteBuffer buffer; } - private static final ThreadLocal tlDatas = ThreadLocal.withInitial(TlData::new); + private static final ThreadLocal TL_DATAS = ThreadLocal.withInitial(TlData::new); public final String algorithm; } @@ -260,7 +260,7 @@ private static synchronized Path getDlTmp(boolean create) { Path ret = dlTmp; if (ret != null || !create) return ret; - Path dir = Paths.get("dlTmp"); + Path dir = Path.of("dlTmp"); int suffix = 0; Path path; @@ -277,36 +277,37 @@ private static synchronized Path getDlTmp(boolean create) { final Path res = ret; - Runtime.getRuntime().addShutdownHook(new Thread() { - @Override - public void run() { - try { - Files.walkFileTree(res, new SimpleFileVisitor<>() { - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - System.out.println("delete file "+file); + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + LOGGER.info("Deleting dlTmp {}", res); - if (file.normalize().toAbsolutePath().startsWith(res)) { - Files.delete(file); - } + try { + Files.walkFileTree(res, new SimpleFileVisitor<>() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + LOGGER.debug("Deleting file {}", file); - return FileVisitResult.CONTINUE; + if (file.normalize().toAbsolutePath().startsWith(res)) { + Files.delete(file); } - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - System.out.println("delete dir "+dir); + return FileVisitResult.CONTINUE; + } - if (dir.normalize().toAbsolutePath().startsWith(res)) { - Files.delete(dir); - } + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + LOGGER.debug("Deleting dir {}", dir); - return FileVisitResult.CONTINUE; + if (dir.normalize().toAbsolutePath().startsWith(res)) { + Files.delete(dir); } - }); - } catch (IOException e) { - e.printStackTrace(); - } + + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + LOGGER.error("Exception while deleting dlTmp", e); } - }); + })); dlTmp = ret; @@ -316,7 +317,7 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOEx private static Path downloadToTmp(String url) throws IOException, InterruptedException { LOGGER.info("downloading {}", url); - String name = url.substring(url.lastIndexOf('/') + 1).replaceAll("[^\\w\\.\\- ]", "x"); + String name = url.substring(url.lastIndexOf('/') + 1).replaceAll("[^\\w.\\- ]", "x"); if (name.isEmpty()) name = "dl"; int suffix = 0; Path dlTmp = getDlTmp(true); @@ -330,7 +331,7 @@ private static Path downloadToTmp(String url) throws IOException, InterruptedExc HttpResponse response = HTTP_CLIENT.send(request, BodyHandlers.ofInputStream()); if (response.statusCode() != 200) { - throw new IOException("bad http status code: "+response.statusCode()); + throw new IOException("bad http status code: " + response.statusCode()); } try (InputStream is = response.body()) { @@ -340,7 +341,7 @@ private static Path downloadToTmp(String url) throws IOException, InterruptedExc return out; } - public static final long unknownSize = -1; + public static final long UNKNOWN_SIZE = -1; private static final Logger LOGGER = LoggerFactory.getLogger(InputFile.class); private static final HttpClient HTTP_CLIENT = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10)).build(); diff --git a/matcher-model/src/main/java/matcher/model/type/InvalidSharedEnvException.java b/matcher-model/src/main/java/matcher/model/type/InvalidSharedEnvException.java index f42dfa76..b4e08633 100644 --- a/matcher-model/src/main/java/matcher/model/type/InvalidSharedEnvException.java +++ b/matcher-model/src/main/java/matcher/model/type/InvalidSharedEnvException.java @@ -3,7 +3,7 @@ @SuppressWarnings("serial") public final class InvalidSharedEnvException extends RuntimeException { InvalidSharedEnvException(ClassInstance cls, InvalidSharedEnvQueryException queryExc) { - super("Shared env class "+cls.id+" ("+cls.getOrigin()+") requires a/b types: "+queryExc.getMessage()); + super("Shared env class " + cls.id + " (" + cls.getOrigin() + ") requires a/b types: " + queryExc.getMessage()); this.cls = cls; this.queryExc = queryExc; diff --git a/matcher-model/src/main/java/matcher/model/type/InvalidSharedEnvQueryException.java b/matcher-model/src/main/java/matcher/model/type/InvalidSharedEnvQueryException.java index 8119e5a4..8715503b 100644 --- a/matcher-model/src/main/java/matcher/model/type/InvalidSharedEnvQueryException.java +++ b/matcher-model/src/main/java/matcher/model/type/InvalidSharedEnvQueryException.java @@ -3,7 +3,7 @@ @SuppressWarnings("serial") public final class InvalidSharedEnvQueryException extends RuntimeException { InvalidSharedEnvQueryException(ClassInstance a, ClassInstance b) { - super("Querying shared env for "+(a != null ? a.getId() : b.getId())+" which is present in "+(a != null ? (b != null ? "a+b" : "a") : "b")); + super("Querying shared env for " + (a != null ? a.getId() : b.getId()) + " which is present in " + (a != null ? (b != null ? "a+b" : "a") : "b")); this.a = a; this.b = b; @@ -15,7 +15,7 @@ public RuntimeException checkOrigin(ClassInstance cls) { } else { return this; } - }; + } public final ClassInstance a; public final ClassInstance b; diff --git a/matcher-model/src/main/java/matcher/model/type/MatchType.java b/matcher-model/src/main/java/matcher/model/type/MatchType.java index e709be3b..b8750ed8 100644 --- a/matcher-model/src/main/java/matcher/model/type/MatchType.java +++ b/matcher-model/src/main/java/matcher/model/type/MatchType.java @@ -1,5 +1,5 @@ package matcher.model.type; public enum MatchType { - Class, Method, Field, MethodVar; + Class, Method, Field, MethodVar } diff --git a/matcher-model/src/main/java/matcher/model/type/MemberInstance.java b/matcher-model/src/main/java/matcher/model/type/MemberInstance.java index df764ce4..21a098c5 100644 --- a/matcher-model/src/main/java/matcher/model/type/MemberInstance.java +++ b/matcher-model/src/main/java/matcher/model/type/MemberInstance.java @@ -357,12 +357,12 @@ public String toString() { return getDisplayName(NameType.PLAIN, true); } - public static final Comparator> nameComparator = Comparator., String>comparing(MemberInstance::getName).thenComparing(m -> m.getDesc()); + public static final Comparator> NAME_COMPARATOR = Comparator., String>comparing(MemberInstance::getName).thenComparing(m -> m.getDesc()); final ClassInstance cls; final String id; final String origName; - boolean nameObfuscatedLocal; + final boolean nameObfuscatedLocal; final int position; final boolean isStatic; diff --git a/matcher-model/src/main/java/matcher/model/type/MethodInstance.java b/matcher-model/src/main/java/matcher/model/type/MethodInstance.java index 735f2e45..af1f5553 100644 --- a/matcher-model/src/main/java/matcher/model/type/MethodInstance.java +++ b/matcher-model/src/main/java/matcher/model/type/MethodInstance.java @@ -3,7 +3,6 @@ import java.net.URI; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Set; @@ -42,10 +41,10 @@ private MethodInstance(ClassInstance cls, String origName, String desc, MethodNo this.real = asmNode != null; this.access = asmNode != null ? asmNode.access : approximateAccess(isStatic); this.args = gatherArgs(this, desc, asmNode); - this.vars = cls.isInput() ? gatherVars(this, asmNode) : emptyVars; + this.vars = cls.isInput() ? gatherVars(this, asmNode) : EMPTY_VARS; this.retType = cls.getEnv().getCreateClassInstance(Type.getReturnType(desc).getDescriptor()); this.signature = asmNode == null || asmNode.signature == null || !cls.isInput() ? null : MethodSignature.parse(asmNode.signature, cls.getEnv()); - this.asmNode = !cls.getEnv().isShared() ? asmNode : null; + this.asmNode = cls.getEnv().isShared() ? null : asmNode; } catch (InvalidSharedEnvQueryException e) { throw e.checkOrigin(cls); } @@ -63,7 +62,7 @@ private static int approximateAccess(boolean isStatic) { private static MethodVarInstance[] gatherArgs(MethodInstance method, String desc, MethodNode asmNode) { Type[] argTypes = Type.getArgumentTypes(desc); - if (argTypes.length == 0) return emptyVars; + if (argTypes.length == 0) return EMPTY_VARS; MethodVarInstance[] args = new MethodVarInstance[argTypes.length]; List locals; @@ -123,9 +122,9 @@ private static MethodVarInstance[] gatherArgs(MethodInstance method, String desc } private static MethodVarInstance[] gatherVars(MethodInstance method, MethodNode asmNode) { - if (asmNode == null) return emptyVars; - if (asmNode.localVariables == null) return emptyVars; // TODO: generate? - if (asmNode.localVariables.isEmpty()) return emptyVars; + if (asmNode == null) return EMPTY_VARS; + if (asmNode.localVariables == null) return EMPTY_VARS; // TODO: generate? + if (asmNode.localVariables.isEmpty()) return EMPTY_VARS; InsnList il = asmNode.instructions; AbstractInsnNode firstInsn = il.getFirst(); @@ -147,10 +146,10 @@ private static MethodVarInstance[] gatherVars(MethodInstance method, MethodNode vars.add(var); } - if (vars.isEmpty()) return emptyVars; + if (vars.isEmpty()) return EMPTY_VARS; // stable sort by start bci - Collections.sort(vars, Comparator.comparingInt(var -> il.indexOf(var.start))); // Collections.sort is specified as stable, List.sort isn't (only implNote in OpenJDK 8) + vars.sort(Comparator.comparingInt(var -> il.indexOf(var.start))); MethodVarInstance[] ret = new MethodVarInstance[vars.size()]; @@ -260,7 +259,7 @@ public MethodNode getAsmNode() { } public MethodVarInstance getArg(int index) { - if (index < 0 || index >= args.length) throw new IllegalArgumentException("invalid arg index: "+index); + if (index < 0 || index >= args.length) throw new IllegalArgumentException("invalid arg index: " + index); return args[index]; } @@ -270,7 +269,7 @@ public MethodVarInstance getArg(String id) { } public MethodVarInstance getVar(int index) { - if (index < 0 || index >= vars.length) throw new IllegalArgumentException("invalid var index: "+index); + if (index < 0 || index >= vars.length) throw new IllegalArgumentException("invalid var index: " + index); return vars[index]; } @@ -289,13 +288,11 @@ public MethodVarInstance getArgOrVar(int lvIndex, int pos) { public MethodVarInstance getArgOrVar(int lvIndex, int start, int end) { if (args.length > 0 && lvIndex <= args[args.length - 1].getLvIndex()) { - for (int i = 0; i < args.length; i++) { - MethodVarInstance arg = args[i]; - + for (MethodVarInstance arg : args) { if (arg.getLvIndex() == lvIndex) { assert arg.getStartInsn() < 0 - || start < arg.getEndInsn() && end > arg.getStartInsn() - || arg.getStartInsn() < end && arg.getEndInsn() > start; + || start < arg.getEndInsn() && end > arg.getStartInsn() + || arg.getStartInsn() < end && arg.getEndInsn() > start; return arg; } @@ -304,8 +301,7 @@ public MethodVarInstance getArgOrVar(int lvIndex, int start, int end) { MethodVarInstance candidate = null; boolean conflict = false; - for (int i = 0; i < vars.length; i++) { - MethodVarInstance var = vars[i]; + for (MethodVarInstance var : vars) { if (var.getLvIndex() != lvIndex) continue; if (start < var.getEndInsn() && end > var.getStartInsn()) { // requested interval within var interval (assumes matcher's interval never too loose) @@ -501,7 +497,7 @@ public String getUidString() { int uid = getUid(); if (uid < 0) return null; - return cls.env.getGlobal().methodUidPrefix+uid; + return ClassEnvironment.METHOD_UID_PREFIX +uid; } @Override @@ -570,7 +566,7 @@ public static String getId(String name, String desc) { return name+desc; } - private static final MethodVarInstance[] emptyVars = new MethodVarInstance[0]; + private static final MethodVarInstance[] EMPTY_VARS = new MethodVarInstance[0]; final boolean real; final int access; diff --git a/matcher-model/src/main/java/matcher/model/type/MethodType.java b/matcher-model/src/main/java/matcher/model/type/MethodType.java index 346a4d36..af896c7d 100644 --- a/matcher-model/src/main/java/matcher/model/type/MethodType.java +++ b/matcher-model/src/main/java/matcher/model/type/MethodType.java @@ -1,5 +1,5 @@ package matcher.model.type; public enum MethodType { - UNKNOWN, OTHER, CLASS_INIT, CONSTRUCTOR, LAMBDA_IMPL; + UNKNOWN, OTHER, CLASS_INIT, CONSTRUCTOR, LAMBDA_IMPL } diff --git a/matcher-model/src/main/java/matcher/model/type/MethodVarInstance.java b/matcher-model/src/main/java/matcher/model/type/MethodVarInstance.java index 1e7ac900..c4fe0a18 100644 --- a/matcher-model/src/main/java/matcher/model/type/MethodVarInstance.java +++ b/matcher-model/src/main/java/matcher/model/type/MethodVarInstance.java @@ -84,7 +84,7 @@ public String getName(NameType type) { } else if (type == NameType.UID_PLAIN) { ClassEnvironment env = method.cls.env.getGlobal(); int uid = getUid(); - if (uid >= 0) return (isArg ? env.argUidPrefix : env.varUidPrefix)+uid; + if (uid >= 0) return (isArg ? ClassEnvironment.ARG_UID_PREFIX : ClassEnvironment.VAR_UID_PREFIX)+uid; } boolean locTmp = type == NameType.MAPPED_LOCTMP_PLAIN || type == NameType.LOCTMP_PLAIN; diff --git a/matcher-model/src/main/java/matcher/model/type/Signature.java b/matcher-model/src/main/java/matcher/model/type/Signature.java index d5121ec6..6acab54e 100644 --- a/matcher-model/src/main/java/matcher/model/type/Signature.java +++ b/matcher-model/src/main/java/matcher/model/type/Signature.java @@ -175,7 +175,7 @@ static ReferenceTypeSignature parse(String sig, MutableInt pos, ClassEnv env) { pos.val++; ret.arrayElemCls = JavaTypeSignature.parse(sig, pos, env); } else { - throw new RuntimeException("invalid char: "+next); + throw new RuntimeException("invalid char: " + next); } return ret; @@ -213,7 +213,7 @@ public boolean isPotentiallyEqual(ReferenceTypeSignature o) { if (cls != null) { return o.cls != null && cls.isPotentiallyEqual(o.cls); } else if (var != null) { - return true; //var.equals(o.var); + return true; // var.equals(o.var); } else { assert arrayElemCls != null; return o.arrayElemCls != null && arrayElemCls.isPotentiallyEqual(o.arrayElemCls); @@ -645,7 +645,7 @@ static ThrowsSignature parse(String sig, MutableInt pos, ClassEnv env) { ret.var = sig.substring(pos.val, end); pos.val = end + 1; } else { - throw new RuntimeException("invalid char: "+next); + throw new RuntimeException("invalid char: " + next); } return ret; @@ -677,7 +677,7 @@ public boolean isPotentiallyEqual(ThrowsSignature o) { if (cls != null) { return o.cls != null && cls.isPotentiallyEqual(o.cls); } else { - return true; //var.equals(o.var); + return true; // var.equals(o.var); } } diff --git a/matcher-model/src/main/java/module-info.java b/matcher-model/src/main/java/module-info.java index 5dd9710d..585669f7 100644 --- a/matcher-model/src/main/java/module-info.java +++ b/matcher-model/src/main/java/module-info.java @@ -1,3 +1,4 @@ +@SuppressWarnings("requires-transitive-automatic") module matcher.model { requires java.prefs; requires org.objectweb.asm.commons;