From 791aba7087e2b4d5fd61016f43c514c6eb51db84 Mon Sep 17 00:00:00 2001 From: Mumfrey Date: Tue, 31 Jan 2017 19:15:31 +0000 Subject: [PATCH] Increase checkstyle checks. Javadoc all the things. --- build.gradle | 11 +- checkstyle.xml | 51 ++++ gradle/wrapper/gradle-wrapper.properties | 2 +- .../spongepowered/tools/agent/MixinAgent.java | 8 +- .../AnnotatedMixinElementHandlerAccessor.java | 5 + ...atedMixinElementHandlerSoftImplements.java | 3 +- .../tools/obfuscation/AnnotatedMixins.java | 2 +- .../MixinObfuscationProcessor.java | 2 + .../tools/obfuscation/ObfuscationData.java | 29 +++ .../obfuscation/ObfuscationEnvironment.java | 2 +- .../tools/obfuscation/ObfuscationType.java | 53 +++- .../tools/obfuscation/SupportedOptions.java | 3 + .../tools/obfuscation/TargetMap.java | 4 +- .../interfaces/IObfuscationDataProvider.java | 22 ++ .../obfuscation/mapping/IMappingProvider.java | 5 +- .../obfuscation/mapping/IMappingWriter.java | 11 +- .../mapping/common/MappingWriter.java | 5 + .../obfuscation/mirror/AnnotationHandle.java | 26 +- .../obfuscation/mirror/MemberHandle.java | 7 + .../tools/obfuscation/mirror/TypeHandle.java | 28 +- .../tools/obfuscation/mirror/TypeUtils.java | 240 ++++++++++++------ .../service/ObfuscationServices.java | 13 +- .../obfuscation/struct/InjectorRemap.java | 26 ++ .../tools/obfuscation/struct/Message.java | 43 +++- .../asm/bridge/RemapperAdapter.java | 5 +- .../asm/bridge/RemapperAdapterFML.java | 10 +- .../spongepowered/asm/launch/Blackboard.java | 31 +++ .../launch/platform/IMixinPlatformAgent.java | 2 +- .../asm/launch/platform/MainAttributes.java | 2 +- .../asm/launch/platform/MixinContainer.java | 23 +- .../platform/MixinPlatformAgentAbstract.java | 3 +- .../platform/MixinPlatformAgentDefault.java | 4 + .../platform/MixinPlatformAgentFML.java | 3 +- .../launch/platform/MixinPlatformManager.java | 25 ++ .../spongepowered/asm/mixin/Interface.java | 3 + .../asm/mixin/MixinEnvironment.java | 56 +++- .../org/spongepowered/asm/mixin/Mixins.java | 5 + .../extensibility/IMixinErrorHandler.java | 3 + .../asm/mixin/gen/AccessorInfo.java | 38 +++ .../spongepowered/asm/mixin/injection/At.java | 20 +- .../asm/mixin/injection/InjectionNodes.java | 6 +- .../asm/mixin/injection/InjectionPoint.java | 6 + .../injection/callback/CallbackInfo.java | 8 + .../mixin/injection/code/ISliceContext.java | 8 + .../asm/mixin/injection/code/Injector.java | 30 +++ .../mixin/injection/code/InjectorTarget.java | 7 +- .../asm/mixin/injection/code/MethodSlice.java | 2 +- .../mixin/injection/code/MethodSlices.java | 4 +- .../injection/invoke/RedirectInjector.java | 29 ++- .../injection/modify/BeforeLoadLocal.java | 4 +- .../modify/LocalVariableDiscriminator.java | 38 ++- .../modify/ModifyVariableInjector.java | 11 +- .../injection/points/BeforeFieldAccess.java | 19 +- .../injection/points/BeforeFinalReturn.java | 6 +- .../mixin/injection/points/BeforeInvoke.java | 6 + .../asm/mixin/injection/points/BeforeNew.java | 5 +- .../mixin/injection/struct/InjectionInfo.java | 32 ++- .../injection/struct/InjectionPointData.java | 161 +++++++++--- .../mixin/injection/struct/MemberInfo.java | 37 ++- .../struct/ModifyConstantInjectionInfo.java | 4 +- .../asm/mixin/injection/struct/Target.java | 39 ++- .../asm/mixin/refmap/IMixinContext.java | 20 +- .../asm/mixin/transformer/ClassInfo.java | 27 +- .../asm/mixin/transformer/InterfaceInfo.java | 2 +- .../asm/mixin/transformer/MemberRef.java | 7 +- .../asm/mixin/transformer/MethodMapper.java | 13 + .../transformer/MixinApplicatorStandard.java | 40 +-- .../asm/mixin/transformer/MixinConfig.java | 8 +- .../asm/mixin/transformer/MixinInfo.java | 37 +-- .../MixinPreProcessorStandard.java | 6 +- .../mixin/transformer/MixinTargetContext.java | 36 ++- .../mixin/transformer/MixinTransformer.java | 5 +- .../mixin/transformer/TargetClassContext.java | 4 +- .../asm/mixin/transformer/TreeInfo.java | 8 +- .../asm/mixin/transformer/debug/IHotSwap.java | 6 +- .../asm/mixin/transformer/meta/SourceMap.java | 37 ++- .../asm/obfuscation/RemapperChain.java | 6 + .../mapping/common/MappingMethod.java | 7 + .../org/spongepowered/asm/util/ASMHelper.java | 144 +++++++++-- .../asm/util/ClassSignature.java | 2 +- .../asm/util/ConstraintParser.java | 32 ++- .../spongepowered/asm/util/JavaVersion.java | 3 + .../org/spongepowered/asm/util/Locals.java | 7 +- .../asm/util/ObfuscationUtil.java | 14 + .../spongepowered/asm/util/PrettyPrinter.java | 2 +- .../asm/util/SignaturePrinter.java | 36 +++ .../spongepowered/asm/util/VersionNumber.java | 6 +- .../launchwrapper/LaunchClassLoaderUtil.java | 6 + .../throwables/LVTGeneratorException.java | 4 +- 89 files changed, 1517 insertions(+), 304 deletions(-) diff --git a/build.gradle b/build.gradle index 1ef29a319..048eea056 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { } dependencies { classpath 'nl.javadude.gradle.plugins:license-gradle-plugin:0.11.0' - classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.0' + classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3' } } @@ -199,12 +199,13 @@ license { checkstyle { configProperties = [ - "name" : project.name, - "organization": project.organization, - "url" : project.url, - "year" : project.inceptionYear + "name" : project.name, + "organization": project.organization, + "url" : project.url, + "year" : project.inceptionYear ] configFile = file("checkstyle.xml") + toolVersion = '7.5' } // Source compiler configuration diff --git a/checkstyle.xml b/checkstyle.xml index 74525cb51..534f91c5d 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -95,6 +95,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e7e56722d..552180eee 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-bin.zip diff --git a/src/agent/java/org/spongepowered/tools/agent/MixinAgent.java b/src/agent/java/org/spongepowered/tools/agent/MixinAgent.java index 04bc68e66..42af6383e 100644 --- a/src/agent/java/org/spongepowered/tools/agent/MixinAgent.java +++ b/src/agent/java/org/spongepowered/tools/agent/MixinAgent.java @@ -197,8 +197,8 @@ public static void init(Instrumentation instrumentation) { /** * Initialize the java agent * - * This will be called automatically if the jar is in a -javaagent java - * command line argument + *

This will be called automatically if the jar is in a -javaagent java + * command line argument

* * @param arg Ignored * @param instrumentation Instance to use to transform the mixins @@ -211,8 +211,8 @@ public static void premain(String arg, Instrumentation instrumentation) { /** * Initialize the java agent * - * This will be called automatically if the java agent is loaded after jvm - * startup + *

This will be called automatically if the java agent is loaded after + * JVVM startup

* * @param arg Ignored * @param instrumentation Instance to use to re-define the mixins diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/AnnotatedMixinElementHandlerAccessor.java b/src/ap/java/org/spongepowered/tools/obfuscation/AnnotatedMixinElementHandlerAccessor.java index e2a61cd0a..d7cea3444 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/AnnotatedMixinElementHandlerAccessor.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/AnnotatedMixinElementHandlerAccessor.java @@ -174,6 +174,11 @@ public Target getTargetMethod(MethodNode into) { throw new UnsupportedOperationException("Target not available at compile time"); } + /** + * Register a new accessor + * + * @param elem accessor element + */ public void registerAccessor(AnnotatedElementAccessor elem) { if (elem.getAccessorType() == null) { elem.printMessage(this.ap, Kind.WARNING, "Unsupported accessor type"); diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/AnnotatedMixinElementHandlerSoftImplements.java b/src/ap/java/org/spongepowered/tools/obfuscation/AnnotatedMixinElementHandlerSoftImplements.java index 786d0c3c3..4b2086186 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/AnnotatedMixinElementHandlerSoftImplements.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/AnnotatedMixinElementHandlerSoftImplements.java @@ -55,7 +55,8 @@ public class AnnotatedMixinElementHandlerSoftImplements extends AnnotatedMixinEl * in the mixin are then tested for remapability based on the strategy * defined in the soft-implements decoration * - * @param implementsAnnotation + * @param implementsAnnotation the @Implements annotation on the + * element */ public void process(AnnotationHandle implementsAnnotation) { if (!this.mixin.remap()) { diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/AnnotatedMixins.java b/src/ap/java/org/spongepowered/tools/obfuscation/AnnotatedMixins.java index 44d168116..eec3fbdd5 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/AnnotatedMixins.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/AnnotatedMixins.java @@ -78,7 +78,7 @@ * Mixin info manager, stores all of the mixin info during processing and also * manages access to the mappings */ -class AnnotatedMixins implements IMixinAnnotationProcessor, ITokenProvider, ITypeHandleProvider, IJavadocProvider { +final class AnnotatedMixins implements IMixinAnnotationProcessor, ITokenProvider, ITypeHandleProvider, IJavadocProvider { private static final String MAPID_SYSTEM_PROPERTY = "mixin.target.mapid"; diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/MixinObfuscationProcessor.java b/src/ap/java/org/spongepowered/tools/obfuscation/MixinObfuscationProcessor.java index bebf0e225..669703c41 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/MixinObfuscationProcessor.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/MixinObfuscationProcessor.java @@ -59,6 +59,8 @@ public synchronized void init(ProcessingEnvironment processingEnv) { /** * Searches and catalogues all annotated mixin classes + * + * @param roundEnv round environment */ protected void processMixins(RoundEnvironment roundEnv) { this.mixins.onPassStarted(); diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/ObfuscationData.java b/src/ap/java/org/spongepowered/tools/obfuscation/ObfuscationData.java index 3c664c2b7..61500871f 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/ObfuscationData.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/ObfuscationData.java @@ -47,8 +47,15 @@ */ public class ObfuscationData implements Iterable { + /** + * Data points stored in this struct, entries are stored by type + */ private final Map data = new HashMap(); + /** + * Default obfuscation value to return when an obfuscation entry is + * requested but not present in the map + */ private final T defaultValue; public ObfuscationData() { @@ -59,24 +66,46 @@ public ObfuscationData(T defaultValue) { this.defaultValue = defaultValue; } + /** + * Add an entry to the map + * + * @param type obfuscation type + * @param value new entry + */ public void add(ObfuscationType type, T value) { this.data.put(type, value); } + /** + * Returns true if this store contains no entries + */ public boolean isEmpty() { return this.data.isEmpty(); } + /** + * Get the obfuscation entry for the specified obfuscation type, returns the + * default (if present) if no entry is found for the specified type + * + * @param type obfuscation type + * @return obfuscation entry or default value if absent + */ public T get(ObfuscationType type) { T value = this.data.get(type); return value != null ? value : this.defaultValue; } + /* (non-Javadoc) + * @see java.lang.Iterable#iterator() + */ @Override public Iterator iterator() { return this.data.keySet().iterator(); } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ @Override public String toString() { return String.format("ObfuscationData[%sDEFAULT=%s]", this.listValues(), this.defaultValue); diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/ObfuscationEnvironment.java b/src/ap/java/org/spongepowered/tools/obfuscation/ObfuscationEnvironment.java index 959fb753e..8d34209f9 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/ObfuscationEnvironment.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/ObfuscationEnvironment.java @@ -143,7 +143,7 @@ private boolean initMappings() { if (this.inFileNames == null) { this.ap.printMessage(Kind.ERROR, "The " + this.type.getConfig().getInputFileOption() - + " argument was not supplied, obfuscation processing will not occur"); + + " argument was not supplied, obfuscation processing will not occur"); return false; } diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/ObfuscationType.java b/src/ap/java/org/spongepowered/tools/obfuscation/ObfuscationType.java index d9f484443..1515f1b87 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/ObfuscationType.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/ObfuscationType.java @@ -42,14 +42,29 @@ */ public final class ObfuscationType { + /** + * Available obfuscation types indexed by key + */ private static final Map types = new LinkedHashMap(); + /** + * Key for this type + */ private final String key; + /** + * Descriptor contains the majority of the metadata for the obfuscation type + */ private final ObfuscationTypeDescriptor descriptor; + /** + * Annotation Processor + */ private final IMixinAnnotationProcessor ap; + /** + * Option provider + */ private final IOptionProvider options; private ObfuscationType(ObfuscationTypeDescriptor descriptor, IMixinAnnotationProcessor ap) { @@ -59,6 +74,9 @@ private ObfuscationType(ObfuscationTypeDescriptor descriptor, IMixinAnnotationPr this.options = ap; } + /** + * Create obfuscation environment instance for this obfuscation type + */ public final ObfuscationEnvironment createEnvironment() { try { Class cls = this.descriptor.getEnvironmentType(); @@ -88,16 +106,25 @@ public IMixinAnnotationProcessor getAnnotationProcessor() { return this.ap; } + /** + * Get whether this is ithe default obfuscation environment + */ public boolean isDefault() { String defaultEnv = this.options.getOption(SupportedOptions.DEFAULT_OBFUSCATION_ENV); return (defaultEnv == null && this.key.equals(ObfuscationServiceMCP.SEARGE)) || (defaultEnv != null && this.key.equals(defaultEnv.toLowerCase())); } + /** + * Get whether this obfuscation type has data available + */ public boolean isSupported() { return this.getInputFileNames().size() > 0; } + /** + * Get the input file names specified for this obfuscation type + */ public List getInputFileNames() { Builder builder = ImmutableList.builder(); @@ -116,24 +143,44 @@ public List getInputFileNames() { return builder.build(); } + /** + * Get the output filenames specified for this obfuscation type + */ public String getOutputFileName() { return this.options.getOption(this.descriptor.getOutputFileOption()); } + /** + * All available obfuscation types + */ public static Iterable types() { return ObfuscationType.types.values(); } - public static ObfuscationType create(ObfuscationTypeDescriptor config, IMixinAnnotationProcessor ap) { - String key = config.getKey(); + /** + * Create a new obfuscation type from the supplied descriptor + * + * @param descriptor obfuscation type metadata + * @param ap annotation processor + * @return new obfuscation type + */ + public static ObfuscationType create(ObfuscationTypeDescriptor descriptor, IMixinAnnotationProcessor ap) { + String key = descriptor.getKey(); if (ObfuscationType.types.containsKey(key)) { throw new IllegalArgumentException("Obfuscation type with key " + key + " was already registered"); } - ObfuscationType type = new ObfuscationType(config, ap); + ObfuscationType type = new ObfuscationType(descriptor, ap); ObfuscationType.types.put(key, type); return type; } + /** + * Retrieve an obfuscation type by key + * + * @param key obfuscation type key to retrieve + * @return obfuscation type or null if no matching type is + * available + */ public static ObfuscationType get(String key) { ObfuscationType type = ObfuscationType.types.get(key); if (type == null) { diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/SupportedOptions.java b/src/ap/java/org/spongepowered/tools/obfuscation/SupportedOptions.java index af172a6dd..ad6f07dcb 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/SupportedOptions.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/SupportedOptions.java @@ -48,6 +48,9 @@ public final class SupportedOptions { private SupportedOptions() {} + /** + * Return all supported options + */ public static Set getAllOptions() { Builder options = ImmutableSet.builder(); options.add( diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/TargetMap.java b/src/ap/java/org/spongepowered/tools/obfuscation/TargetMap.java index a220c9d10..718d04319 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/TargetMap.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/TargetMap.java @@ -49,7 +49,7 @@ * Serialisable map of classes to their associated mixins, used so that we can * pass target information for supermixins from one compiler session to another */ -public class TargetMap extends HashMap> { +public final class TargetMap extends HashMap> { private static final long serialVersionUID = 1L; @@ -68,7 +68,7 @@ private TargetMap() { /** * Create a TargetMap with the specified session ID * - * @param sessionId + * @param sessionId session id */ private TargetMap(String sessionId) { this.sessionId = sessionId; diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/interfaces/IObfuscationDataProvider.java b/src/ap/java/org/spongepowered/tools/obfuscation/interfaces/IObfuscationDataProvider.java index 8435b9dcb..2e7eab72d 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/interfaces/IObfuscationDataProvider.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/interfaces/IObfuscationDataProvider.java @@ -43,8 +43,10 @@ public interface IObfuscationDataProvider { * owner class. * * @param targetMember Member to search for + * @param the type of the obfuscation mapping (MappingMethod for methods * @return ObfuscationData with remapped owner class corresponding to the * original owner class + * or String for fields) */ public abstract ObfuscationData getObfEntryRecursive(MemberInfo targetMember); @@ -52,7 +54,9 @@ public interface IObfuscationDataProvider { * Resolves a field or method reference to an ObfuscationData set * * @param targetMember member to search for + * @param the type of the obfuscation mapping (MappingMethod for methods * @return obfuscation data (by type) for the supplied member + * or String for fields) */ public abstract ObfuscationData getObfEntry(MemberInfo targetMember); @@ -60,7 +64,9 @@ public interface IObfuscationDataProvider { * Resolves a field or method reference to an ObfuscationData set * * @param mapping member to search for + * @param the type of the obfuscation mapping (MappingMethod for methods * @return obfuscation data (by type) for the supplied member + * or String for fields) */ public abstract ObfuscationData getObfEntry(IMapping mapping); @@ -78,23 +84,31 @@ public interface IObfuscationDataProvider { /** * Get an obfuscation mapping for a method + * + * @param method method to fetch obfuscation mapping for */ public abstract ObfuscationData getObfMethod(MemberInfo method); /** * Get an obfuscation mapping for a method if an explicit mapping exists. * Where no direct mapping exists, remap the descriptor of the method only. + * + * @param method method to fetch obfuscation mapping for */ public abstract ObfuscationData getRemappedMethod(MemberInfo method); /** * Get an obfuscation mapping for a method + * + * @param method method to fetch obfuscation mapping for */ public abstract ObfuscationData getObfMethod(MappingMethod method); /** * Get an obfuscation mapping for a method if an explicit mapping exists. * Where no direct mapping exists, remap the descriptor of the method only. + * + * @param method method to fetch obfuscation mapping for */ public abstract ObfuscationData getRemappedMethod(MappingMethod method); @@ -112,21 +126,29 @@ public interface IObfuscationDataProvider { /** * Get an obfuscation mapping for a field + * + * @param field field to fetch obfuscation mapping for */ public abstract ObfuscationData getObfField(MemberInfo field); /** * Get an obfuscation mapping for a field + * + * @param field field to fetch obfuscation mapping for */ public abstract ObfuscationData getObfField(MappingField field); /** * Get an obfuscation mapping for a class + * + * @param type class type to fetch obfuscation mapping for */ public abstract ObfuscationData getObfClass(TypeHandle type); /** * Get an obfuscation mapping for a class + * + * @param className class name to fetch obfuscation mapping for */ public abstract ObfuscationData getObfClass(String className); diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/mapping/IMappingProvider.java b/src/ap/java/org/spongepowered/tools/obfuscation/mapping/IMappingProvider.java index dabc9a898..e23117c24 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/mapping/IMappingProvider.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/mapping/IMappingProvider.java @@ -54,8 +54,9 @@ public interface IMappingProvider { * Called multiple times by the environment. This method will be called for * each input file specified by the user. * - * @param input - * @throws IOException + * @param input input file to read + * @throws IOException if an error occurs reading the input file or the file + * does not exist or cannot be opened */ public abstract void read(File input) throws IOException; diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/mapping/IMappingWriter.java b/src/ap/java/org/spongepowered/tools/obfuscation/mapping/IMappingWriter.java index 6455dc487..fb9580ac6 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/mapping/IMappingWriter.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/mapping/IMappingWriter.java @@ -35,12 +35,13 @@ public interface IMappingWriter { /** - * Receives + * Instruct this writer to write the supplied collection of field and method + * mappings to the output resource * - * @param output - * @param type - * @param fields - * @param methods + * @param output path to output resource + * @param type obfuscation type to write + * @param fields field mappings + * @param methods method mappings */ public abstract void write(String output, ObfuscationType type, MappingSet fields, MappingSet methods); diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/mapping/common/MappingWriter.java b/src/ap/java/org/spongepowered/tools/obfuscation/mapping/common/MappingWriter.java index 5e6099a78..8691c6e5a 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/mapping/common/MappingWriter.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/mapping/common/MappingWriter.java @@ -52,6 +52,11 @@ public MappingWriter(Messager messager, Filer filer) { /** * Open a writer for an output file + * + * @param fileName output file name (resource path) + * @param description description of file being requested, for logging + * @return new PrintWriter for opened resource + * @throws IOException if the resource cannot be opened */ protected PrintWriter openFileWriter(String fileName, String description) throws IOException { if (fileName.matches("^.*[\\\\/:].*$")) { diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/mirror/AnnotationHandle.java b/src/ap/java/org/spongepowered/tools/obfuscation/mirror/AnnotationHandle.java index d1c463483..3742c1af8 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/mirror/AnnotationHandle.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/mirror/AnnotationHandle.java @@ -42,7 +42,7 @@ * A wrapper for {@link AnnotationMirror} which provides a more convenient way * to access annotation values. */ -public class AnnotationHandle { +public final class AnnotationHandle { /** * Annotation being wrapped @@ -92,6 +92,7 @@ public String toString() { * @param key key * @param defaultValue value to return if the key is not set or not present * @return value or default if not set + * @param duck type */ @SuppressWarnings({ "unchecked", "rawtypes" }) public T getValue(String key, T defaultValue) { @@ -114,6 +115,7 @@ public T getValue(String key, T defaultValue) { /** * Get the annotation value or return null if not present or not set * + * @param duck type * @return value or null if not present or not set */ public T getValue() { @@ -125,6 +127,7 @@ public T getValue() { * present or not set * * @param key key to fetch + * @param duck type * @return value or null if not present or not set */ public T getValue(String key) { @@ -146,8 +149,8 @@ public boolean getBoolean(String key, boolean defaultValue) { /** * Get an annotation value as an annotation handle * - * @param key - * @return + * @param key key to search for in the value map + * @return value or null if not set */ public AnnotationHandle getAnnotation(String key) { Object value = this.getValue(key); @@ -166,6 +169,7 @@ public AnnotationHandle getAnnotation(String key) { * Retrieve the annotation value as a list with values of the specified * type. Returns an empty list if the value is not present or not set. * + * @param list element duck type * @return list of values */ public List getList() { @@ -178,6 +182,7 @@ public List getList() { * present or not set. * * @param key key to fetch + * @param list element duck type * @return list of values */ public List getList(String key) { @@ -259,10 +264,25 @@ protected static AnnotationMirror getAnnotation(Element elem, Class annotationClass) { return new AnnotationHandle(AnnotationHandle.getAnnotation(elem, annotationClass)); } diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/mirror/MemberHandle.java b/src/ap/java/org/spongepowered/tools/obfuscation/mirror/MemberHandle.java index ce847aa4b..7d9fbebee 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/mirror/MemberHandle.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/mirror/MemberHandle.java @@ -57,5 +57,12 @@ public final String getDesc() { return this.desc; } + /** + * Return this handle as a mapping + * + * @param includeOwner include the owner in the generated mapping, false to + * only include name and desc + * @return this handle as a mapping of appropriate type + */ public abstract T asMapping(boolean includeOwner); } diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/mirror/TypeHandle.java b/src/ap/java/org/spongepowered/tools/obfuscation/mirror/TypeHandle.java index cee9b6ecc..b089796c6 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/mirror/TypeHandle.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/mirror/TypeHandle.java @@ -100,7 +100,7 @@ public TypeHandle(TypeElement element) { /** * Ctor for real elements, instanced via a type mirror * - * @param type + * @param type type */ public TypeHandle(DeclaredType type) { this((TypeElement)type.asElement()); @@ -142,6 +142,13 @@ protected TypeElement getTargetElement() { return this.element; } + /** + * Get an annotation handle for the specified annotation on this type + * + * @param annotationClass type of annotation to search for + * @return new annotation handle, call exists on the returned + * handle to determine whether the annotation is present + */ public AnnotationHandle getAnnotation(Class annotationClass) { return AnnotationHandle.of(this.getTargetElement(), annotationClass); } @@ -157,6 +164,7 @@ public final List getEnclosedElements() { * Returns enclosed elements (methods, fields, etc.) of a particular type * * @param kind types of element to return + * @param list element type */ public List getEnclosedElements(ElementKind... kind) { return TypeHandle.getEnclosedElements(this.getTargetElement(), kind); @@ -188,6 +196,9 @@ public TypeHandle getSuperclass() { return new TypeHandle((DeclaredType)superClass); } + /** + * Get interfaces directly implemented by this type + */ public List getInterfaces() { if (this.getTargetElement() == null) { return Collections.emptyList(); @@ -222,6 +233,9 @@ public boolean isSimulated() { return false; } + /** + * Get the TypeReference for this type, used for serialisation + */ public final TypeReference getReference() { if (this.reference == null) { this.reference = new TypeReference(this); @@ -236,12 +250,18 @@ public final TypeReference getReference() { * * @param name Method name * @param desc Method descriptor - * @return + * @return this handle as a mapping method */ public MappingMethod getMappingMethod(String name, String desc) { return new MappingMethod(this.getName(), name, desc); } + /** + * Find a descriptor for the supplied MemberInfo + * + * @param memberInfo MemberInfo to use as search term + * @return descriptor or null if no matching member could be located + */ public String findDescriptor(MemberInfo memberInfo) { String desc = memberInfo.desc; if (desc == null) { @@ -271,6 +291,7 @@ public final FieldHandle findField(VariableElement element) { * of the supplied element * * @param element Element to match + * @param caseSensitive True if case-sensitive comparison should be used * @return handle to the discovered field if matched or null if no match */ public final FieldHandle findField(VariableElement element, boolean caseSensitive) { @@ -295,6 +316,7 @@ public final FieldHandle findField(String name, String type) { * * @param name Field name to search for * @param type Field descriptor (java-style) + * @param caseSensitive True if case-sensitive comparison should be used * @return handle to the discovered field if matched or null if no match */ public FieldHandle findField(String name, String type, boolean caseSensitive) { @@ -327,6 +349,7 @@ public final MethodHandle findMethod(ExecutableElement element) { * type of the supplied element * * @param element Element to match + * @param caseSensitive True if case-sensitive comparison should be used * @return handle to the discovered method if matched or null if no match */ public final MethodHandle findMethod(ExecutableElement element, boolean caseSensitive) { @@ -351,6 +374,7 @@ public final MethodHandle findMethod(String name, String signature) { * * @param name Method name to search for * @param signature Method signature + * @param matchCase True if case-sensitive comparison should be used * @return handle to the discovered method if matched or null if no match */ public MethodHandle findMethod(String name, String signature, boolean matchCase) { diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/mirror/TypeUtils.java b/src/ap/java/org/spongepowered/tools/obfuscation/mirror/TypeUtils.java index ae40b9577..e35a5b29c 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/mirror/TypeUtils.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/mirror/TypeUtils.java @@ -53,6 +53,13 @@ public abstract class TypeUtils { // No instances for you private TypeUtils() {} + /** + * If the supplied type is a {@link DeclaredType}, return the package in + * which it is declared + * + * @param type type to find package for + * @return package for supplied type or null + */ public static PackageElement getPackage(TypeMirror type) { if (!(type instanceof DeclaredType)) { return null; @@ -60,6 +67,11 @@ public static PackageElement getPackage(TypeMirror type) { return TypeUtils.getPackage((TypeElement)((DeclaredType)type).asElement()); } + /** + * Return the package in which the specified type element is declared + * @param type type to find package for + * @return package for supplied type or null + */ public static PackageElement getPackage(TypeElement type) { Element parent = type.getEnclosingElement(); while (parent != null && !(parent instanceof PackageElement)) { @@ -68,40 +80,35 @@ public static PackageElement getPackage(TypeElement type) { return (PackageElement)parent; } - public static String getElementType(Element parent) { - if (parent instanceof TypeElement) { + /** + * Convenience method to convert element to string representation for error + * messages + * + * @param element Element to inspect + * @return string representation of element name + */ + public static String getElementType(Element element) { + if (element instanceof TypeElement) { return "TypeElement"; - } else if (parent instanceof ExecutableElement) { + } else if (element instanceof ExecutableElement) { return "ExecutableElement"; - } else if (parent instanceof VariableElement) { + } else if (element instanceof VariableElement) { return "VariableElement"; - } else if (parent instanceof PackageElement) { + } else if (element instanceof PackageElement) { return "PackageElement"; - } else if (parent instanceof TypeParameterElement) { + } else if (element instanceof TypeParameterElement) { return "TypeParameterElement"; } - return parent.getClass().getSimpleName(); - } - - public static String getJavaSignature(Element element) { - if (element instanceof ExecutableElement) { - ExecutableElement method = (ExecutableElement)element; - StringBuilder desc = new StringBuilder().append("("); - boolean extra = false; - for (VariableElement arg : method.getParameters()) { - if (extra) { - desc.append(','); - } - desc.append(TypeUtils.getTypeName(arg.asType())); - extra = true; - } - desc.append(')').append(TypeUtils.getTypeName(method.getReturnType())); - return desc.toString(); - } - return TypeUtils.getTypeName(element.asType()); + return element.getClass().getSimpleName(); } + /** + * Strip generic arguments from the supplied type descriptor + * + * @param type type descriptor + * @return type descriptor with generic args removed + */ public static String stripGenerics(String type) { StringBuilder sb = new StringBuilder(); for (int pos = 0, depth = 0; pos < type.length(); pos++) { @@ -118,16 +125,59 @@ public static String stripGenerics(String type) { return sb.toString(); } - public static String getDescriptor(Element elem) { - if (elem instanceof ExecutableElement) { - return TypeUtils.getDescriptor((ExecutableElement)elem); - } else if (elem instanceof VariableElement) { - return TypeUtils.getInternalName((VariableElement)elem); + /** + * Get the name of the specified field + * + * @param field field element + * @return field name + */ + public static String getName(VariableElement field) { + return field != null ? field.getSimpleName().toString() : null; + } + + /** + * Get the name of the specified method + * + * @param method method element + * @return method name + */ + public static String getName(ExecutableElement method) { + return method != null ? method.getSimpleName().toString() : null; + } + + /** + * Get a java-style signature for the specified element (return type follows + * args) eg: + * + *
(int,int)boolean
+ * + * @param element element to generate descriptor for + * @return descriptor + */ + public static String getJavaSignature(Element element) { + if (element instanceof ExecutableElement) { + ExecutableElement method = (ExecutableElement)element; + StringBuilder desc = new StringBuilder().append("("); + boolean extra = false; + for (VariableElement arg : method.getParameters()) { + if (extra) { + desc.append(','); + } + desc.append(TypeUtils.getTypeName(arg.asType())); + extra = true; + } + desc.append(')').append(TypeUtils.getTypeName(method.getReturnType())); + return desc.toString(); } - - return TypeUtils.getInternalName(elem.asType()); + return TypeUtils.getTypeName(element.asType()); } + /** + * Get the type name for the specified type + * + * @param type type mirror + * @return type name + */ public static String getTypeName(TypeMirror type) { switch (type.getKind()) { case ARRAY: return TypeUtils.getTypeName(((ArrayType)type).getComponentType()) + "[]"; @@ -138,25 +188,41 @@ public static String getTypeName(TypeMirror type) { } } + /** + * Get the type name for the specified type + * + * @param type type mirror + * @return type name + */ public static String getTypeName(DeclaredType type) { if (type == null) { return TypeUtils.OBJECT_SIG; } - return TypeUtils.getTypeName((TypeElement)type.asElement()); + return TypeUtils.getInternalName((TypeElement)type.asElement()).replace('/', '.'); } - private static String getTypeName(TypeElement elem) { - return TypeUtils.getInternalName(elem).replace('/', '.'); - } - - public static String getName(VariableElement field) { - return field != null ? field.getSimpleName().toString() : null; - } - - public static String getName(ExecutableElement method) { - return method != null ? method.getSimpleName().toString() : null; + /** + * Get a bytecode-style descriptor for the specified element + * + * @param element element to generate descriptor for + * @return descriptor + */ + public static String getDescriptor(Element element) { + if (element instanceof ExecutableElement) { + return TypeUtils.getDescriptor((ExecutableElement)element); + } else if (element instanceof VariableElement) { + return TypeUtils.getInternalName((VariableElement)element); + } + + return TypeUtils.getInternalName(element.asType()); } + /** + * Get a bytecode-style descriptor for the specified method + * + * @param method method to generate descriptor for + * @return descriptor + */ public static String getDescriptor(ExecutableElement method) { if (method == null) { return null; @@ -172,13 +238,25 @@ public static String getDescriptor(ExecutableElement method) { return String.format("(%s)%s", signature, returnType); } - public static String getInternalName(VariableElement var) { - if (var == null) { + /** + * Get a bytecode-style descriptor for the specified field + * + * @param field field to generate descriptor for + * @return descriptor + */ + public static String getInternalName(VariableElement field) { + if (field == null) { return null; } - return TypeUtils.getInternalName(var.asType()); + return TypeUtils.getInternalName(field.asType()); } + /** + * Get a bytecode-style descriptor for the specified type + * + * @param type type to generate descriptor for + * @return descriptor + */ public static String getInternalName(TypeMirror type) { switch (type.getKind()) { case ARRAY: return "[" + TypeUtils.getInternalName(((ArrayType)type).getComponentType()); @@ -200,6 +278,43 @@ public static String getInternalName(TypeMirror type) { throw new IllegalArgumentException("Unable to parse type symbol " + type + " with " + type.getKind() + " to equivalent bytecode type"); } + + /** + * Get a bytecode-style name for the specified type + * + * @param type type to get name for + * @return bytecode-style name + */ + public static String getInternalName(DeclaredType type) { + if (type == null) { + return TypeUtils.OBJECT_REF; + } + return TypeUtils.getInternalName((TypeElement)type.asElement()); + } + + /** + * Get a bytecode-style name for the specified type element + * + * @param element type element to get name for + * @return bytecode-style name + */ + public static String getInternalName(TypeElement element) { + if (element == null) { + return null; + } + StringBuilder reference = new StringBuilder(); + reference.append(element.getSimpleName()); + Element parent = element.getEnclosingElement(); + while (parent != null) { + if (parent instanceof TypeElement) { + reference.insert(0, "$").insert(0, parent.getSimpleName()); + } else if (parent instanceof PackageElement) { + reference.insert(0, "/").insert(0, ((PackageElement)parent).getQualifiedName().toString().replace('.', '/')); + } + parent = parent.getEnclosingElement(); + } + return reference.toString(); + } private static DeclaredType getUpperBound(TypeMirror type) { try { @@ -234,31 +349,14 @@ private static DeclaredType getUpperBound0(TypeMirror type, int depth) { return null; } - public static String getInternalName(DeclaredType type) { - if (type == null) { - return TypeUtils.OBJECT_REF; - } - return TypeUtils.getInternalName((TypeElement)type.asElement()); - } - - public static String getInternalName(TypeElement elem) { - if (elem == null) { - return null; - } - StringBuilder reference = new StringBuilder(); - reference.append(elem.getSimpleName()); - Element parent = elem.getEnclosingElement(); - while (parent != null) { - if (parent instanceof TypeElement) { - reference.insert(0, "$").insert(0, parent.getSimpleName()); - } else if (parent instanceof PackageElement) { - reference.insert(0, "/").insert(0, ((PackageElement)parent).getQualifiedName().toString().replace('.', '/')); - } - parent = parent.getEnclosingElement(); - } - return reference.toString(); - } - + /** + * Get whether the target type is assignable to the specified superclass + * + * @param processingEnv processing environment + * @param targetType target type to check + * @param superClass superclass type to check + * @return true if targetType is assignable to superClass + */ public static boolean isAssignable(ProcessingEnvironment processingEnv, TypeMirror targetType, TypeMirror superClass) { boolean assignable = processingEnv.getTypeUtils().isAssignable(targetType, superClass); if (!assignable && targetType instanceof DeclaredType && superClass instanceof DeclaredType) { diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/service/ObfuscationServices.java b/src/ap/java/org/spongepowered/tools/obfuscation/service/ObfuscationServices.java index d385a0b17..c1ac26da5 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/service/ObfuscationServices.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/service/ObfuscationServices.java @@ -38,7 +38,7 @@ /** * Obfuscation service manager */ -public class ObfuscationServices { +public final class ObfuscationServices { /** * Singleton @@ -74,6 +74,8 @@ public static ObfuscationServices getInstance() { /** * Initialise services + * + * @param ap annotation processor */ public void initProviders(IMixinAnnotationProcessor ap) { try { @@ -102,6 +104,9 @@ public void initProviders(IMixinAnnotationProcessor ap) { } } + /** + * Get the options supported by all available providers + */ public Set getSupportedOptions() { Set supportedOptions = new HashSet(); for (IObfuscationService provider : this.serviceLoader) { @@ -113,6 +118,12 @@ public Set getSupportedOptions() { return supportedOptions; } + /** + * Get the service instance for the specified class from the service loader + * + * @param serviceClass service class + * @return service instance or null if no matching services were loaded + */ public IObfuscationService getService(Class serviceClass) { for (IObfuscationService service : this.serviceLoader) { if (serviceClass.getName().equals(service.getClass().getName())) { diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/struct/InjectorRemap.java b/src/ap/java/org/spongepowered/tools/obfuscation/struct/InjectorRemap.java index 82c0291e8..4979adde4 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/struct/InjectorRemap.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/struct/InjectorRemap.java @@ -28,6 +28,7 @@ import javax.lang.model.element.Element; import javax.tools.Diagnostic; +import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.tools.obfuscation.mirror.AnnotationHandle; /** @@ -61,23 +62,48 @@ public InjectorRemap(boolean remap) { this.remap = remap; } + /** + * Get whether remap=true on the injector + */ public boolean shouldRemap() { return this.remap; } + /** + * Callback from the parser to notify this injector that it has been + * remapped + */ public void notifyRemapped() { this.remappedCount++; this.clearMessage(); } + /** + * Add an error message on ths injector, the message will be suppressed if + * a child {@link At} is remapped + * + * @param kind message kind + * @param msg message + * @param element annotated element + * @param annotation annotation + */ public void addMessage(Diagnostic.Kind kind, CharSequence msg, Element element, AnnotationHandle annotation) { this.message = new Message(kind, msg, element, annotation); } + /** + * Clear the current message (if any) + */ public void clearMessage() { this.message = null; } + /** + * Called after processing completes. Dispatches the queued message (if any) + * if no child At annotations were remapped. + * + * @param messager messager to push message into + */ public void dispatchPendingMessages(Messager messager) { if (this.remappedCount == 0 && this.message != null) { this.message.sendTo(messager); diff --git a/src/ap/java/org/spongepowered/tools/obfuscation/struct/Message.java b/src/ap/java/org/spongepowered/tools/obfuscation/struct/Message.java index 9bf0a52c9..987819272 100644 --- a/src/ap/java/org/spongepowered/tools/obfuscation/struct/Message.java +++ b/src/ap/java/org/spongepowered/tools/obfuscation/struct/Message.java @@ -72,6 +72,12 @@ public Message(Diagnostic.Kind kind, CharSequence msg, Element element, Annotati this.value = value; } + /** + * Send this message to the supplied message + * + * @param messager messager to send to + * @return fluent interface + */ public Message sendTo(Messager messager) { if (this.value != null) { messager.printMessage(this.kind, this.msg, this.element, this.annotation, this.value); @@ -85,40 +91,63 @@ public Message sendTo(Messager messager) { return this; } - + /** + * Get the message kind + */ public Diagnostic.Kind getKind() { return this.kind; } - + /** + * Set the message kind + * + * @param kind message kind + * @return fluent interface + */ public Message setKind(Diagnostic.Kind kind) { this.kind = kind; return this; } - + /** + * Get the message text + * + * @return fluent interface + */ public CharSequence getMsg() { return this.msg; } - + /** + * Set the message text + * + * @param msg message text + * @return fluent interface + */ public Message setMsg(CharSequence msg) { this.msg = msg; return this; } - + /** + * Get the target element + */ public Element getElement() { return this.element; } - + /** + * Get the target annotation + */ public AnnotationMirror getAnnotation() { return this.annotation; } - + /** + * Get the target annotation value + */ public AnnotationValue getValue() { return this.value; } + } diff --git a/src/bridge/java/org/spongepowered/asm/bridge/RemapperAdapter.java b/src/bridge/java/org/spongepowered/asm/bridge/RemapperAdapter.java index 11eae88f4..a3a39e877 100644 --- a/src/bridge/java/org/spongepowered/asm/bridge/RemapperAdapter.java +++ b/src/bridge/java/org/spongepowered/asm/bridge/RemapperAdapter.java @@ -26,7 +26,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.objectweb.asm.commons.Remapper; import org.spongepowered.asm.mixin.extensibility.IRemapper; import org.spongepowered.asm.util.ObfuscationUtil; import org.spongepowered.asm.util.ObfuscationUtil.IClassRemapper; @@ -37,9 +36,9 @@ public abstract class RemapperAdapter implements IRemapper, IClassRemapper { protected final Logger logger = LogManager.getLogger("mixin"); - protected final Remapper remapper; + protected final org.objectweb.asm.commons.Remapper remapper; - public RemapperAdapter(Remapper remapper) { + public RemapperAdapter(org.objectweb.asm.commons.Remapper remapper) { this.remapper = remapper; } diff --git a/src/bridge/java/org/spongepowered/asm/bridge/RemapperAdapterFML.java b/src/bridge/java/org/spongepowered/asm/bridge/RemapperAdapterFML.java index 97750e1a0..a0ed0b499 100644 --- a/src/bridge/java/org/spongepowered/asm/bridge/RemapperAdapterFML.java +++ b/src/bridge/java/org/spongepowered/asm/bridge/RemapperAdapterFML.java @@ -27,17 +27,16 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; -import org.objectweb.asm.commons.Remapper; import org.spongepowered.asm.mixin.extensibility.IRemapper; /** * Remapper adapter which remaps using FML's deobfuscating remapper */ -public class RemapperAdapterFML extends RemapperAdapter { +public final class RemapperAdapterFML extends RemapperAdapter { private final Method mdUnmap; - private RemapperAdapterFML(Remapper remapper, Method mdUnmap) { + private RemapperAdapterFML(org.objectweb.asm.commons.Remapper remapper, Method mdUnmap) { super(remapper); this.logger.info("Initialised Mixin FML Remapper Adapter with {}", remapper); this.mdUnmap = mdUnmap; @@ -52,12 +51,15 @@ public String unmap(String typeName) { } } + /** + * Factory method + */ public static IRemapper create() { try { Class clDeobfRemapper = RemapperAdapterFML.getFMLDeobfuscatingRemapper(); Field singletonField = clDeobfRemapper.getDeclaredField("INSTANCE"); Method mdUnmap = clDeobfRemapper.getDeclaredMethod("unmap", String.class); - Remapper remapper = (Remapper)singletonField.get(null); + org.objectweb.asm.commons.Remapper remapper = (org.objectweb.asm.commons.Remapper)singletonField.get(null); return new RemapperAdapterFML(remapper, mdUnmap); } catch (Exception ex) { ex.printStackTrace(); diff --git a/src/main/java/org/spongepowered/asm/launch/Blackboard.java b/src/main/java/org/spongepowered/asm/launch/Blackboard.java index bc6ea8370..de808f97f 100644 --- a/src/main/java/org/spongepowered/asm/launch/Blackboard.java +++ b/src/main/java/org/spongepowered/asm/launch/Blackboard.java @@ -55,21 +55,52 @@ private Keys() {} private Blackboard() {} + /** + * Get a value from the blackboard and duck-type it to the specified type + * + * @param key blackboard key + * @return value + * @param duck type + */ @SuppressWarnings("unchecked") public static T get(String key) { return (T)Launch.blackboard.get(key); } + /** + * Put the specified value onto the blackboard + * + * @param key blackboard key + * @param value new value + */ public static void put(String key, Object value) { Launch.blackboard.put(key, value); } + /** + * Get the value from the blackboard but return defaultValue if the + * specified key is not set. + * + * @param key blackboard key + * @param defaultValue value to return if the key is not set or is null + * @return value from blackboard or default value + * @param duck type + */ @SuppressWarnings("unchecked") public static T get(String key, T defaultValue) { Object value = Launch.blackboard.get(key); return value != null ? (T)value : defaultValue; } + /** + * Get a string from the blackboard, returns default value if not set or + * null. + * + * @param key blackboard key + * @param defaultValue default value to return if the specified key is not + * set or is null + * @return value from blackboard or default + */ public static String getString(String key, String defaultValue) { Object value = Launch.blackboard.get(key); return value != null ? value.toString() : defaultValue; diff --git a/src/main/java/org/spongepowered/asm/launch/platform/IMixinPlatformAgent.java b/src/main/java/org/spongepowered/asm/launch/platform/IMixinPlatformAgent.java index abdad43db..221f18e6d 100644 --- a/src/main/java/org/spongepowered/asm/launch/platform/IMixinPlatformAgent.java +++ b/src/main/java/org/spongepowered/asm/launch/platform/IMixinPlatformAgent.java @@ -59,7 +59,7 @@ public interface IMixinPlatformAgent { /** * Called from injectIntoClassLoader in the parent tweaker * - * @param classLoader + * @param classLoader classLoader to inject into */ public abstract void injectIntoClassLoader(LaunchClassLoader classLoader); diff --git a/src/main/java/org/spongepowered/asm/launch/platform/MainAttributes.java b/src/main/java/org/spongepowered/asm/launch/platform/MainAttributes.java index 574bd9f37..3e58cab6d 100644 --- a/src/main/java/org/spongepowered/asm/launch/platform/MainAttributes.java +++ b/src/main/java/org/spongepowered/asm/launch/platform/MainAttributes.java @@ -37,7 +37,7 @@ * "Main" attribute cache for a URI container, mainly to avoid constantly * opening jar files just to read odd values out of the manifest. */ -class MainAttributes { +final class MainAttributes { private static final Map instances = new HashMap(); diff --git a/src/main/java/org/spongepowered/asm/launch/platform/MixinContainer.java b/src/main/java/org/spongepowered/asm/launch/platform/MixinContainer.java index ef71f19cc..9d7c9a79e 100644 --- a/src/main/java/org/spongepowered/asm/launch/platform/MixinContainer.java +++ b/src/main/java/org/spongepowered/asm/launch/platform/MixinContainer.java @@ -34,6 +34,7 @@ import org.apache.logging.log4j.Logger; import org.spongepowered.asm.launch.Blackboard; +import net.minecraft.launchwrapper.ITweaker; import net.minecraft.launchwrapper.LaunchClassLoader; /** @@ -41,7 +42,7 @@ */ public class MixinContainer { - public static final List agentClasses = new ArrayList(); + private static final List agentClasses = new ArrayList(); static { Blackboard.put(Blackboard.Keys.AGENTS, MixinContainer.agentClasses); @@ -79,6 +80,9 @@ public URI getURI() { return this.uri; } + /** + * Get phase provider names from all agents in this container + */ public Collection getPhaseProviders() { List phaseProviders = new ArrayList(); for (IMixinPlatformAgent agent : this.agents) { @@ -91,7 +95,7 @@ public Collection getPhaseProviders() { } /** - * + * Prepare agents in this container */ public void prepare() { for (IMixinPlatformAgent agent : this.agents) { @@ -100,6 +104,10 @@ public void prepare() { } } + /** + * If this container is the primary container, initialise agents in this + * container as primary + */ public void initPrimaryContainer() { for (IMixinPlatformAgent agent : this.agents) { this.logger.debug("Processing launch tasks for {}", agent); @@ -108,7 +116,9 @@ public void initPrimaryContainer() { } /** - * @param classLoader + * Notify all agents to inject into classLoader + * + * @param classLoader classLoader to injec */ public void injectIntoClassLoader(LaunchClassLoader classLoader) { for (IMixinPlatformAgent agent : this.agents) { @@ -117,6 +127,13 @@ public void injectIntoClassLoader(LaunchClassLoader classLoader) { } } + /** + * Analogue of {@link ITweaker#getLaunchTarget}, queries all agents and + * returns first valid launch target. Returns null if no agents have launch + * target. + * + * @return launch target from agent or null + */ public String getLaunchTarget() { for (IMixinPlatformAgent agent : this.agents) { String launchTarget = agent.getLaunchTarget(); diff --git a/src/main/java/org/spongepowered/asm/launch/platform/MixinPlatformAgentAbstract.java b/src/main/java/org/spongepowered/asm/launch/platform/MixinPlatformAgentAbstract.java index c32924dd1..381d05da0 100644 --- a/src/main/java/org/spongepowered/asm/launch/platform/MixinPlatformAgentAbstract.java +++ b/src/main/java/org/spongepowered/asm/launch/platform/MixinPlatformAgentAbstract.java @@ -60,7 +60,8 @@ public abstract class MixinPlatformAgentAbstract implements IMixinPlatformAgent /** * Create a new platform agent for the specified URI * - * @param uri + * @param manager platform manager + * @param uri URI of the resource for this agent */ public MixinPlatformAgentAbstract(MixinPlatformManager manager, URI uri) { this.manager = manager; diff --git a/src/main/java/org/spongepowered/asm/launch/platform/MixinPlatformAgentDefault.java b/src/main/java/org/spongepowered/asm/launch/platform/MixinPlatformAgentDefault.java index fd6aae9b5..1f7ac52a2 100644 --- a/src/main/java/org/spongepowered/asm/launch/platform/MixinPlatformAgentDefault.java +++ b/src/main/java/org/spongepowered/asm/launch/platform/MixinPlatformAgentDefault.java @@ -36,6 +36,10 @@ */ public class MixinPlatformAgentDefault extends MixinPlatformAgentAbstract { + /** + * @param manager platform manager + * @param uri URI of the resource for this agent + */ public MixinPlatformAgentDefault(MixinPlatformManager manager, URI uri) { super(manager, uri); } diff --git a/src/main/java/org/spongepowered/asm/launch/platform/MixinPlatformAgentFML.java b/src/main/java/org/spongepowered/asm/launch/platform/MixinPlatformAgentFML.java index ecdc63d5c..fb2f4045b 100644 --- a/src/main/java/org/spongepowered/asm/launch/platform/MixinPlatformAgentFML.java +++ b/src/main/java/org/spongepowered/asm/launch/platform/MixinPlatformAgentFML.java @@ -88,7 +88,8 @@ public class MixinPlatformAgentFML extends MixinPlatformAgentAbstract { private Class clCoreModManager; /** - * @param uri + * @param manager platform manager + * @param uri URI of the resource for this agent */ public MixinPlatformAgentFML(MixinPlatformManager manager, URI uri) { super(manager, uri); diff --git a/src/main/java/org/spongepowered/asm/launch/platform/MixinPlatformManager.java b/src/main/java/org/spongepowered/asm/launch/platform/MixinPlatformManager.java index 1905d0dd5..02e1b8049 100644 --- a/src/main/java/org/spongepowered/asm/launch/platform/MixinPlatformManager.java +++ b/src/main/java/org/spongepowered/asm/launch/platform/MixinPlatformManager.java @@ -110,6 +110,9 @@ public MixinPlatformManager() { //Delegate delegate) { this.scanClasspath(); } + /** + * Get the phase provider classes from the primary container + */ public Collection getPhaseProviderClasses() { Collection phaseProviders = this.primaryContainer.getPhaseProviders(); if (phaseProviders != null) { @@ -119,6 +122,13 @@ public Collection getPhaseProviderClasses() { return Collections.emptyList(); } + /** + * Add a new URI to this platform and return the new container (or an + * existing container if the URI was previously registered) + * + * @param uri URI to add + * @return container for specified URI + */ public final MixinContainer addContainer(URI uri) { MixinContainer existingContainer = this.containers.get(uri); if (existingContainer != null) { @@ -135,6 +145,11 @@ public final MixinContainer addContainer(URI uri) { return container; } + /** + * Prepare all containers in this platform + * + * @param args command-line arguments from tweaker + */ public final void prepare(List args) { this.prepared = true; for (MixinContainer container : this.containers.values()) { @@ -165,6 +180,12 @@ private void parseArgs(List args) { } } + /** + * Initialise the primary container and dispatch injectIntoClassLoader to + * all containers + * + * @param classLoader classloader to inject into + */ public final void injectIntoClassLoader(LaunchClassLoader classLoader) { if (this.injected) { return; @@ -213,6 +234,10 @@ private void scanClasspath() { } } + /** + * Queries all containers for launch target, returns null if no containers + * specify a launch target + */ public String getLaunchTarget() { for (MixinContainer container : this.containers.values()) { String mainClass = container.getLaunchTarget(); diff --git a/src/main/java/org/spongepowered/asm/mixin/Interface.java b/src/main/java/org/spongepowered/asm/mixin/Interface.java index 3162bdd29..e68ed7067 100644 --- a/src/main/java/org/spongepowered/asm/mixin/Interface.java +++ b/src/main/java/org/spongepowered/asm/mixin/Interface.java @@ -79,6 +79,9 @@ private Remap(boolean forceRemap) { this.forceRemap = forceRemap; } + /** + * Returns whether this remap type should force remapping + */ public boolean forceRemap() { return this.forceRemap; } diff --git a/src/main/java/org/spongepowered/asm/mixin/MixinEnvironment.java b/src/main/java/org/spongepowered/asm/mixin/MixinEnvironment.java index 858c78766..732ce4ad1 100644 --- a/src/main/java/org/spongepowered/asm/mixin/MixinEnvironment.java +++ b/src/main/java/org/spongepowered/asm/mixin/MixinEnvironment.java @@ -75,7 +75,7 @@ public final class MixinEnvironment implements ITokenProvider { /** * Environment phase, deliberately not implemented as an enum */ - public static class Phase { + public static final class Phase { /** * Not initialised phase @@ -132,6 +132,13 @@ public String toString() { return this.name; } + /** + * Get a phase by name, returns null if no phases exist with + * the specified name + * + * @param name phase name to lookup + * @return phase object or null if non existent + */ public static Phase forName(String name) { for (Phase phase : Phase.phases) { if (phase.name.equals(name)) { @@ -527,8 +534,14 @@ > E getEnumValue(E defaultValue) { */ public static enum CompatibilityLevel { + /** + * Java 6 and above + */ JAVA_6(6, Opcodes.V1_6, false), + /** + * Java 7 and above + */ JAVA_7(7, Opcodes.V1_7, false) { @Override @@ -538,6 +551,9 @@ boolean isSupported() { }, + /** + * Java 8 and above + */ JAVA_8(8, Opcodes.V1_8, true) { @Override @@ -566,22 +582,46 @@ private void setMaxCompatibleLevel(CompatibilityLevel maxCompatibleLevel) { this.maxCompatibleLevel = maxCompatibleLevel; } + /** + * Get whether this compatibility level is supported in the current + * environment + */ boolean isSupported() { return true; } + /** + * Class version expected at this compatibility level + */ public int classVersion() { return this.classVersion; } + /** + * Get whether this environment supports non-abstract methods in + * interfaces, true in Java 1.8 and above + */ public boolean supportsMethodsInInterfaces() { return this.supportsMethodsInInterfaces; } + /** + * Get whether this level is the same or greater than the specified + * level + * + * @param level level to compare to + * @return true if this level is equal or higher the supplied level + */ public boolean isAtLeast(CompatibilityLevel level) { - return this.ver >= level.ver; + return level == null || this.ver >= level.ver; } + /** + * Get whether this level can be elevated to the specified level + * + * @param level desired level + * @return true if this level supports elevation + */ public boolean canElevateTo(CompatibilityLevel level) { if (level == null || this.maxCompatibleLevel == null) { return true; @@ -589,6 +629,12 @@ public boolean canElevateTo(CompatibilityLevel level) { return level.ver <= this.maxCompatibleLevel.ver; } + /** + * True if this level can support the specified level + * + * @param level desired level + * @return true if the other level can be elevated to this level + */ public boolean canSupport(CompatibilityLevel level) { if (level == null) { return true; @@ -925,7 +971,7 @@ public MixinEnvironment registerTokenProviderClass(String providerName) { try { @SuppressWarnings("unchecked") Class providerClass = - (Class)Class.forName(providerName, true, Launch.classLoader); + (Class)Class.forName(providerName, true, Launch.classLoader); IEnvironmentTokenProvider provider = providerClass.newInstance(); this.registerTokenProvider(provider); } catch (Throwable th) { @@ -1079,7 +1125,7 @@ public String getOptionValue(Option option) { /** * Set the obfuscation context * - * @param context + * @param context new context */ public void setObfuscationContext(String context) { this.obfuscationContext = context; @@ -1305,7 +1351,7 @@ public static void setCompatibilityLevel(CompatibilityLevel level) throws Illega /** * Internal callback * - * @param phase + * @param phase phase to go to */ static void gotoPhase(Phase phase) { if (phase == null || phase.ordinal < 0) { diff --git a/src/main/java/org/spongepowered/asm/mixin/Mixins.java b/src/main/java/org/spongepowered/asm/mixin/Mixins.java index 279a860c6..52e03082a 100644 --- a/src/main/java/org/spongepowered/asm/mixin/Mixins.java +++ b/src/main/java/org/spongepowered/asm/mixin/Mixins.java @@ -59,6 +59,11 @@ public final class Mixins { private Mixins() {} + /** + * Add multiple configurations + * + * @param configFiles config resources to add + */ public static void addConfigurations(String... configFiles) { MixinEnvironment fallback = MixinEnvironment.getDefaultEnvironment(); for (String configFile : configFiles) { diff --git a/src/main/java/org/spongepowered/asm/mixin/extensibility/IMixinErrorHandler.java b/src/main/java/org/spongepowered/asm/mixin/extensibility/IMixinErrorHandler.java index 551b7a7bf..2b52b1f3a 100644 --- a/src/main/java/org/spongepowered/asm/mixin/extensibility/IMixinErrorHandler.java +++ b/src/main/java/org/spongepowered/asm/mixin/extensibility/IMixinErrorHandler.java @@ -57,6 +57,9 @@ public static enum ErrorAction { */ ERROR(Level.FATAL); + /** + * Logging level for the specified error action + */ public final Level logLevel; private ErrorAction(Level logLevel) { diff --git a/src/main/java/org/spongepowered/asm/mixin/gen/AccessorInfo.java b/src/main/java/org/spongepowered/asm/mixin/gen/AccessorInfo.java index 32ea34eae..4af81e808 100644 --- a/src/main/java/org/spongepowered/asm/mixin/gen/AccessorInfo.java +++ b/src/main/java/org/spongepowered/asm/mixin/gen/AccessorInfo.java @@ -93,10 +93,24 @@ private AccessorType(Set expectedPrefixes) { this.expectedPrefixes = expectedPrefixes; } + /** + * Returns true if the supplied prefix string is an allowed prefix for + * this accessor type + * + * @param prefix prefix to check + * @return true if the expected prefix set contains the supplied value + */ public boolean isExpectedPrefix(String prefix) { return this.expectedPrefixes.contains(prefix); } + /** + * Returns all the expected prefixes for this accessor type as a string + * for debugging/error message purposes + * + * @return string representation of expected prefixes for this accessor + * type + */ public String getExpectedPrefixes() { return this.expectedPrefixes.toString(); } @@ -203,11 +217,34 @@ protected String getTargetName() { return MemberInfo.parse(name, this.mixin).name; } + /** + * Uses the name of this accessor method and the calculated accessor type to + * try and inflect the name of the target field or method. This allows a + * method named getFoo to be inflected to a target named + * foo for example. + */ protected String inflectTarget() { return AccessorInfo.inflectTarget(this.method.name, this.type, this.toString(), this.mixin, this.mixin.getEnvironment().getOption(Option.DEBUG_VERBOSE)); } + /** + * Uses the name of an accessor method and the accessor type to try and + * inflect the name of the target field or method. This allows a method + * named getFoo to be inflected to a target named foo for + * example. + * + * @param accessorName Name of the accessor method + * @param accessorType Type of accessor being processed, this is calculated + * from the method signature (void methods being setters, + * methods with return types being getters) + * @param accessorDescription description of the accessor to include in + * error messages + * @param context Mixin context + * @param verbose Emit warnings when accessor prefix doesn't match type + * @return inflected target member name or null if name cannot be + * inflected + */ public static String inflectTarget(String accessorName, AccessorType accessorType, String accessorDescription, IMixinContext context, boolean verbose) { Matcher nameMatcher = AccessorInfo.PATTERN_ACCESSOR.matcher(accessorName); @@ -303,6 +340,7 @@ private FieldNode findTargetField() { * fields and methods. * * @param nodes Node list to search (method/field list) + * @param node type * @return best match */ protected TNode findTarget(List nodes) { diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/At.java b/src/main/java/org/spongepowered/asm/mixin/injection/At.java index 4e168ea2a..d703e6852 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/At.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/At.java @@ -43,14 +43,32 @@ */ @Retention(RetentionPolicy.RUNTIME) public @interface At { + /** * Shift is used to shift resulting opcodes */ public enum Shift { + + /** + * Do not shift the returned opcodes + */ NONE, + + /** + * Shift the returned opcodes back one instruction + */ BEFORE, + + /** + * Shift the returned opcodes forward one instruction + */ AFTER, + + /** + * Shift the returned opcodes by the amount specified in {@link At#by} + */ BY + } /** @@ -110,7 +128,7 @@ public enum Shift { /** *

The named arguments list is used to expand the scope of the * annotation beyond the fixed values below in order to accommodate the - * needs of custom injection point classes. + * needs of custom injection point classes.

* * @return Named arguments for the injection point */ diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/InjectionNodes.java b/src/main/java/org/spongepowered/asm/mixin/injection/InjectionNodes.java index 5f4486dc7..c97abcf43 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/InjectionNodes.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/InjectionNodes.java @@ -143,6 +143,7 @@ public boolean isRemoved() { * * @param key meta key * @param value meta value + * @param value type */ public InjectionNode decorate(String key, V value) { if (this.decorations == null) { @@ -158,7 +159,7 @@ public InjectionNode decorate(String key, V value) { * @param key meta key * @return true if the specified decoration exists */ - public boolean hasDecoration(K key) { + public boolean hasDecoration(String key) { return this.decorations != null && this.decorations.get(key) != null; } @@ -167,6 +168,7 @@ public boolean hasDecoration(K key) { * * @param key meta key * @return decoration value or null if absent + * @param value type */ @SuppressWarnings("unchecked") public V getDecoration(String key) { @@ -186,7 +188,7 @@ public int compareTo(InjectionNode other) { */ @Override public String toString() { - return String.format("InjectionNode[%s]", ASMHelper.getNodeDescriptionForDebug(this.currentTarget).replaceAll("\\s+", " ")); + return String.format("InjectionNode[%s]", ASMHelper.describeNode(this.currentTarget).replaceAll("\\s+", " ")); } } diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/InjectionPoint.java b/src/main/java/org/spongepowered/asm/mixin/injection/InjectionPoint.java index 35b2e387d..af6de2e86 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/InjectionPoint.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/InjectionPoint.java @@ -600,6 +600,12 @@ private static InjectionPoint shift(InjectionPoint point, At.Shift shift, int by return point; } + /** + * Register an injection point class. The supplied class must be decorated + * with an {@link AtCode} annotation for registration purposes. + * + * @param type injection point type to register + */ public static void register(Class type) { AtCode code = type.getAnnotation(AtCode.class); if (code == null) { diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/callback/CallbackInfo.java b/src/main/java/org/spongepowered/asm/mixin/injection/callback/CallbackInfo.java index e05cee7e9..729814922 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/callback/CallbackInfo.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/callback/CallbackInfo.java @@ -110,6 +110,14 @@ static String getCallInfoClassName() { return CallbackInfo.class.getName(); } + /** + * Gets the {@link CallbackInfo} class name to use for the specified return + * type. Currently returns {@link CallbackInfo} for void types and + * {@link CallbackInfoReturnable} for non-void types. + * + * @param returnType return type of the target method + * @return CallbackInfo class name to use + */ public static String getCallInfoClassName(Type returnType) { return (returnType.equals(Type.VOID_TYPE) ? CallbackInfo.class.getName() : CallbackInfoReturnable.class.getName()).replace('.', '/'); } diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/code/ISliceContext.java b/src/main/java/org/spongepowered/asm/mixin/injection/code/ISliceContext.java index 67a7c9f06..fdc1326df 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/code/ISliceContext.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/code/ISliceContext.java @@ -31,6 +31,14 @@ */ public interface ISliceContext extends IInjectionPointContext { + /** + * Fetch slice with the specified id from this context, the slice id may be + * transformed internally by the context according to restrictions on the + * injector itself + * + * @param id slice id to fetch + * @return method slice matching query + */ public abstract MethodSlice getSlice(String id); } diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/code/Injector.java b/src/main/java/org/spongepowered/asm/mixin/injection/code/Injector.java index b74c95d53..d5a73ae98 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/code/Injector.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/code/Injector.java @@ -159,6 +159,12 @@ protected void addTargetNode(Target target, List myNodes, Abstrac myNodes.add(target.injectionNodes.add(node)); } + /** + * Performs the injection on the specified target + * + * @param target target to inject into + * @param nodes selected nodes + */ public final void inject(Target target, List nodes) { for (InjectionNode node : nodes) { if (node.isRemoved()) { @@ -270,10 +276,26 @@ protected static String printArgs(Type[] args) { return "(" + Joiner.on("").join(args) + ")"; } + /** + * Returns whether the from type can be coerced to the to + * type. + * + * @param from type to coerce from + * @param to type to coerce to + * @return true if from can be coerced to to + */ public static boolean canCoerce(Type from, Type to) { return Injector.canCoerce(from.getDescriptor(), to.getDescriptor()); } + /** + * Returns whether the from type can be coerced to the to + * type. + * + * @param from type to coerce from + * @param to type to coerce to + * @return true if from can be coerced to to + */ public static boolean canCoerce(String from, String to) { if (from.length() > 1 || to.length() > 1) { return false; @@ -282,6 +304,14 @@ public static boolean canCoerce(String from, String to) { return Injector.canCoerce(from.charAt(0), to.charAt(0)); } + /** + * Returns whether the from type can be coerced to the to + * type. + * + * @param from type to coerce from + * @param to type to coerce to + * @return true if from can be coerced to to + */ public static boolean canCoerce(char from, char to) { return to == 'I' && "IBSCZ".indexOf(from) > -1; } diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/code/InjectorTarget.java b/src/main/java/org/spongepowered/asm/mixin/injection/code/InjectorTarget.java index 29ec0675c..a9ca082bb 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/code/InjectorTarget.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/code/InjectorTarget.java @@ -101,15 +101,18 @@ public InsnList getSlice(String id) { } /** - * Get the slice instructions for the specified + * Get the slice instructions for the specified injection point * - * @param injectionPoint + * @param injectionPoint injection point to fetch slice for * @return slice */ public InsnList getSlice(InjectionPoint injectionPoint) { return this.getSlice(injectionPoint.getSlice()); } + /** + * Dispose all cached instruction lists + */ public void dispose() { for (ReadOnlyInsnList insns : this.cache.values()) { insns.dispose(); diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/code/MethodSlice.java b/src/main/java/org/spongepowered/asm/mixin/injection/code/MethodSlice.java index a2a219e6a..369a0e0d0 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/code/MethodSlice.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/code/MethodSlice.java @@ -46,7 +46,7 @@ /** * Stores information about a defined method slice for a particular injector. */ -public class MethodSlice { +public final class MethodSlice { /** * A read-only wrapper for an {@link InsnList} which only allows the segment diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/code/MethodSlices.java b/src/main/java/org/spongepowered/asm/mixin/injection/code/MethodSlices.java index 3f7c5666d..d0178f849 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/code/MethodSlices.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/code/MethodSlices.java @@ -39,7 +39,7 @@ * be different to declared slice ids because they are mapped by the underlying * injector. Some injectors only support a single slice. */ -public class MethodSlices { +public final class MethodSlices { /** * Injector which owns this collection of slices @@ -63,7 +63,7 @@ private MethodSlices(InjectionInfo info) { /** * Add a slice to this collection * - * @param slice + * @param slice slice to add */ private void add(MethodSlice slice) { String id = this.info.getSliceId(slice.getId()); diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/invoke/RedirectInjector.java b/src/main/java/org/spongepowered/asm/mixin/injection/invoke/RedirectInjector.java index 554d9b5fb..a06316daf 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/invoke/RedirectInjector.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/invoke/RedirectInjector.java @@ -266,7 +266,7 @@ protected void postInject(Target target, InjectionNode node) { ConstructorRedirectData meta = node.getDecoration(ConstructorRedirectData.KEY); boolean wildcard = node.getDecoration(RedirectInjector.KEY_WILD).booleanValue(); if (wildcard && meta.injected == 0) { - throw new InvalidInjectionException(this.info, this.annotationType + " ctor invocation was not found in " + target); + throw new InvalidInjectionException(this.info, this.annotationType + " ctor invocation was not found in " + target); } } } @@ -317,7 +317,6 @@ protected void injectAtInvoke(Target target, InjectionNode node) { private void injectAtFieldAccess(Target target, InjectionNode node) { final FieldInsnNode fieldNode = (FieldInsnNode)node.getCurrentTarget(); final int opCode = fieldNode.getOpcode(); - final boolean staticField = opCode == Opcodes.GETSTATIC || opCode == Opcodes.PUTSTATIC; final Type ownerType = Type.getType("L" + fieldNode.owner + ";"); final Type fieldType = Type.getType(fieldNode.desc); @@ -330,7 +329,7 @@ private void injectAtFieldAccess(Target target, InjectionNode node) { int fuzz = node.getDecoration(RedirectInjector.KEY_FUZZ).intValue(); this.injectAtArrayField(target, fieldNode, opCode, ownerType, fieldType, fuzz); } else { - this.injectAtScalarField(target, fieldNode, opCode, staticField, ownerType, fieldType); + this.injectAtScalarField(target, fieldNode, opCode, ownerType, fieldType); } } @@ -373,6 +372,12 @@ private void injectAtSetArray(Target target, FieldInsnNode fieldNode, AbstractIn * regardless of whether it's a read or write because it just depends on the * actual handler signature, the correct arguments are already on the stack * thanks to the nature of xALOAD and xASTORE. + * + * @param target target method + * @param fieldNode field node + * @param varNode array access node + * @param withArgs true if the descriptor includes captured arguments from + * the target method signature */ public void injectArrayRedirect(Target target, FieldInsnNode fieldNode, AbstractInsnNode varNode, boolean withArgs) { if (!this.isStatic) { @@ -390,14 +395,20 @@ public void injectArrayRedirect(Target target, FieldInsnNode fieldNode, Abstract /** * Redirect a field get or set + * + * @param target target method + * @param fieldNode field access node + * @param opCode field access type + * @param ownerType type of the field owner + * @param fieldType field type */ - public void injectAtScalarField(Target target, final FieldInsnNode fieldNode, int opCode, boolean staticField, Type ownerType, Type fieldType) { + public void injectAtScalarField(Target target, final FieldInsnNode fieldNode, int opCode, Type ownerType, Type fieldType) { AbstractInsnNode invoke = null; InsnList insns = new InsnList(); if (opCode == Opcodes.GETSTATIC || opCode == Opcodes.GETFIELD) { - invoke = this.injectAtGetField(insns, target, fieldNode, staticField, ownerType, fieldType); + invoke = this.injectAtGetField(insns, target, fieldNode, opCode == Opcodes.GETSTATIC, ownerType, fieldType); } else if (opCode == Opcodes.PUTSTATIC || opCode == Opcodes.PUTFIELD) { - invoke = this.injectAtPutField(insns, target, fieldNode, staticField, ownerType, fieldType); + invoke = this.injectAtPutField(insns, target, fieldNode, opCode == Opcodes.PUTSTATIC, ownerType, fieldType); } else { throw new InvalidInjectionException(this.info, "Unspported opcode " + ASMHelper.getOpcodeName(opCode) + " for " + this.info); } @@ -466,6 +477,12 @@ private AbstractInsnNode injectAtPutField(InsnList insns, Target target, FieldIn /** * Check that the handler descriptor matches the calculated descriptor for * the access being redirected. + * + * @param desc computed descriptor + * @param target target method + * @param type redirector type in human-readable text, for error messages + * @return true if the descriptor was found and includes target method args, + * false if the descriptor was found and does not capture target args */ protected boolean checkDescriptor(String desc, Target target, String type) { if (this.methodNode.desc.equals(desc)) { diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/modify/BeforeLoadLocal.java b/src/main/java/org/spongepowered/asm/mixin/injection/modify/BeforeLoadLocal.java index b8dd70051..20715bca8 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/modify/BeforeLoadLocal.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/modify/BeforeLoadLocal.java @@ -176,8 +176,8 @@ protected BeforeLoadLocal(InjectionPointData data) { protected BeforeLoadLocal(InjectionPointData data, int opcode, boolean opcodeAfter) { - super(data.getMixin()); - this.returnType = data.getReturnType(); + super(data.getContext()); + this.returnType = data.getMethodReturnType(); this.discriminator = data.getLocalVariableDiscriminator(); this.opcode = data.getOpcode(this.returnType.getOpcode(opcode)); this.ordinal = data.getOrdinal(); diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/modify/LocalVariableDiscriminator.java b/src/main/java/org/spongepowered/asm/mixin/injection/modify/LocalVariableDiscriminator.java index 6691ca919..5445a9f29 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/modify/LocalVariableDiscriminator.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/modify/LocalVariableDiscriminator.java @@ -210,7 +210,7 @@ public void print(PrettyPrinter printer) { private final Set names; /** - * @param argsOnly + * @param argsOnly true to only search within the method arguments * @param ordinal target variable ordinal * @param index target variable index * @param names target variable names @@ -271,6 +271,15 @@ protected boolean isImplicit(final Context context) { return this.ordinal < 0 && this.index < context.baseArgIndex && this.names.isEmpty(); } + /** + * Find a matching local variable in the specified target + * + * @param returnType variable tyoe + * @param argsOnly only match in the method args + * @param target target method + * @param node current instruction + * @return index of local or -1 if not matched + */ public int findLocal(Type returnType, boolean argsOnly, Target target, AbstractInsnNode node) { try { return this.findLocal(new Context(returnType, argsOnly, target, node)); @@ -279,6 +288,12 @@ public int findLocal(Type returnType, boolean argsOnly, Target target, AbstractI } } + /** + * Find a local variable for the specified context + * + * @param context search context + * @return index of local or -1 if not found + */ public int findLocal(Context context) { if (this.isImplicit(context)) { return this.findImplicitLocal(context); @@ -286,6 +301,14 @@ public int findLocal(Context context) { return this.findExplicitLocal(context); } + /** + * Find an implicit local, this means that we expect exactly 1 variable with + * the specified type in scope, if more than one is found then we throw an + * {@link InvalidImplicitDiscriminatorException} + * + * @param context search context + * @return local variable index + */ private int findImplicitLocal(final Context context) { int found = 0; int count = 0; @@ -305,6 +328,13 @@ private int findImplicitLocal(final Context context) { throw new InvalidImplicitDiscriminatorException("Found " + count + " candidate variables but exactly 1 is required."); } + /** + * Find an explicit local variable in the local variable table. Returns -1 + * if no variables match the discriminator + * + * @param context search context + * @return variable index or -1 if not found + */ private int findExplicitLocal(final Context context) { for (int index = context.baseArgIndex; index < context.locals.length; index++) { Local local = context.locals[index]; @@ -331,6 +361,12 @@ private int findExplicitLocal(final Context context) { return -1; } + /** + * Parse a local variable discriminator from the supplied annotation + * + * @param annotation annotation to parse + * @return discriminator configured using values from the annoation + */ public static LocalVariableDiscriminator parse(AnnotationNode annotation) { boolean argsOnly = ASMHelper.getAnnotationValue(annotation, "argsOnly", Boolean.FALSE).booleanValue(); int ordinal = ASMHelper.getAnnotationValue(annotation, "ordinal", -1); diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/modify/ModifyVariableInjector.java b/src/main/java/org/spongepowered/asm/mixin/injection/modify/ModifyVariableInjector.java index c0bf0c54a..57095cac5 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/modify/ModifyVariableInjector.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/modify/ModifyVariableInjector.java @@ -73,15 +73,15 @@ public Context(Type returnType, boolean argsOnly, Target target, AbstractInsnNod */ abstract static class ContextualInjectionPoint extends InjectionPoint { - protected final IMixinContext mixin; + protected final IMixinContext context; - ContextualInjectionPoint(IMixinContext mixin) { - this.mixin = mixin; + ContextualInjectionPoint(IMixinContext context) { + this.context = context; } @Override public boolean find(String desc, InsnList insns, Collection nodes) { - throw new InvalidInjectionException(this.mixin, "STORE injection point must be used in conjunction with @ModifyVariable"); + throw new InvalidInjectionException(this.context, "STORE injection point must be used in conjunction with @ModifyVariable"); } abstract boolean find(Target target, Collection nodes); @@ -100,7 +100,8 @@ public boolean find(String desc, InsnList insns, Collection no /** * @param info Injection info - * @param print + * @param print True to print this injector's discovered LVT + * @param discriminator discriminator */ public ModifyVariableInjector(InjectionInfo info, boolean print, LocalVariableDiscriminator discriminator) { super(info); diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/points/BeforeFieldAccess.java b/src/main/java/org/spongepowered/asm/mixin/injection/points/BeforeFieldAccess.java index 7c82e70df..d14821600 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/points/BeforeFieldAccess.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/points/BeforeFieldAccess.java @@ -65,7 +65,7 @@ * * * - *

Matching array access:

+ *

Matching array access:

*

For array fields, it is possible to match field accesses followed by a * corresponding array element get or set operation. To enable * this behaviour specify the array named-argument with the desired @@ -86,6 +86,9 @@ @AtCode("FIELD") public class BeforeFieldAccess extends BeforeInvoke { + /** + * Default fuzz factor for searching for array access opcodes + */ public static final int ARRAY_SEARCH_FUZZ_DEFAULT = 8; /** @@ -153,6 +156,20 @@ protected boolean addInsn(InsnList insns, Collection nodes, Ab return super.addInsn(insns, nodes, insn); } + /** + * Searches for an array access instruction in the supplied instruction list + * which is within searchRange instructions of the supplied field + * instruction. Searching halts if the search range is exhausted, if an + * {@link Opcodes#ARRAYLENGTH} opcode is encountered immediately after the + * specified access, if a matching field access is found, or if the end of + * the method is reached. + * + * @param insns Instruction list to search + * @param fieldNode Field instruction to search from + * @param opcode array access opcode to search for + * @param searchRange search range + * @return matching opcode or null if not matched + */ public static AbstractInsnNode findArrayNode(InsnList insns, FieldInsnNode fieldNode, int opcode, int searchRange) { int pos = 0; for (Iterator iter = insns.iterator(insns.indexOf(fieldNode) + 1); iter.hasNext();) { diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/points/BeforeFinalReturn.java b/src/main/java/org/spongepowered/asm/mixin/injection/points/BeforeFinalReturn.java index b14b2eee4..961641908 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/points/BeforeFinalReturn.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/points/BeforeFinalReturn.java @@ -58,12 +58,12 @@ @AtCode("TAIL") public class BeforeFinalReturn extends InjectionPoint { - private final IMixinContext mixin; + private final IMixinContext context; public BeforeFinalReturn(InjectionPointData data) { super(data); - this.mixin = data.getMixin(); + this.context = data.getContext(); } @Override @@ -83,7 +83,7 @@ public boolean find(String desc, InsnList insns, Collection no // WAT? if (ret == null) { - throw new InvalidInjectionException(this.mixin, "TAIL could not locate a valid RETURN in the target method!"); + throw new InvalidInjectionException(this.context, "TAIL could not locate a valid RETURN in the target method!"); } nodes.add(ret); diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/points/BeforeInvoke.java b/src/main/java/org/spongepowered/asm/mixin/injection/points/BeforeInvoke.java index a4be0f555..5cbf77dbd 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/points/BeforeInvoke.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/points/BeforeInvoke.java @@ -102,6 +102,12 @@ private String getClassName() { return String.format("@At(%s)", atCode != null ? atCode.value() : this.getClass().getSimpleName().toUpperCase()); } + /** + * Set the logging state for this injector + * + * @param logging logging state + * @return fluent interface + */ public BeforeInvoke setLogging(boolean logging) { this.log = logging; return this; diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/points/BeforeNew.java b/src/main/java/org/spongepowered/asm/mixin/injection/points/BeforeNew.java index 2d440f18b..db0a8cc8a 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/points/BeforeNew.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/points/BeforeNew.java @@ -108,11 +108,14 @@ public BeforeNew(InjectionPointData data) { this.ordinal = data.getOrdinal(); String target = Strings.emptyToNull(data.get("class", data.get("target", "")).replace('.', '/')); - MemberInfo member = MemberInfo.parseAndValidate(target, data.getMixin()); + MemberInfo member = MemberInfo.parseAndValidate(target, data.getContext()); this.target = member.toCtorType(); this.desc = member.toCtorDesc(); } + /** + * Returns whether this injection point has a constructor descriptor defined + */ public boolean hasDescriptor() { return this.desc != null; } diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/struct/InjectionInfo.java b/src/main/java/org/spongepowered/asm/mixin/injection/struct/InjectionInfo.java index 7a3889e8f..22d677fef 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/struct/InjectionInfo.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/struct/InjectionInfo.java @@ -261,6 +261,12 @@ public void postInject() { } } + /** + * Callback from injector which notifies us that a callback was injected. No + * longer used. + * + * @param target target into which the injector injected + */ public void notifyInjected(Target target) { // this.targets.remove(target.method); } @@ -297,7 +303,7 @@ public MethodSlice getSlice(String id) { * support use of a single slice will always return the default id (an empty * string) * - * @param id + * @param id slice id * @return mapped id */ public String getSliceId(String id) { @@ -386,6 +392,15 @@ private void checkTarget(MethodNode target) { } } + /** + * Parse an injector from the specified method (if an injector annotation is + * present). If no injector annotation is present then null is + * returned. + * + * @param mixin context + * @param method mixin method + * @return parsed InjectionInfo or null + */ public static InjectionInfo parse(MixinTargetContext mixin, MethodNode method) { AnnotationNode annotation = InjectionInfo.getInjectorAnnotation(mixin.getMixin(), method); @@ -408,6 +423,15 @@ public static InjectionInfo parse(MixinTargetContext mixin, MethodNode method) { return null; } + /** + * Returns any injector annotation found on the specified method. If + * multiple matching annotations are found then an exception is thrown. If + * no annotations are present then null is returned. + * + * @param mixin context + * @param method mixin method + * @return annotation or null + */ @SuppressWarnings("unchecked") public static AnnotationNode getInjectorAnnotation(IMixinInfo mixin, MethodNode method) { AnnotationNode annotation = null; @@ -426,6 +450,12 @@ public static AnnotationNode getInjectorAnnotation(IMixinInfo mixin, MethodNode return annotation; } + /** + * Get the conform prefix for an injector handler by type + * + * @param annotation Annotation to inspect + * @return conform prefix + */ public static String getInjectorPrefix(AnnotationNode annotation) { if (annotation != null) { if (annotation.desc.endsWith(ModifyArg.class.getSimpleName() + ";")) { diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/struct/InjectionPointData.java b/src/main/java/org/spongepowered/asm/mixin/injection/struct/InjectionPointData.java index 01033993a..97fef302b 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/struct/InjectionPointData.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/struct/InjectionPointData.java @@ -34,6 +34,7 @@ import org.spongepowered.asm.lib.tree.AnnotationNode; import org.spongepowered.asm.lib.tree.MethodNode; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.InjectionPoint.Selector; import org.spongepowered.asm.mixin.injection.modify.LocalVariableDiscriminator; import org.spongepowered.asm.mixin.injection.throwables.InvalidInjectionPointException; @@ -61,7 +62,7 @@ public class InjectionPointData { /** * Mixin */ - private final IMixinContext mixin; + private final IMixinContext context; /** * Injector callback @@ -108,9 +109,9 @@ public class InjectionPointData { */ private final int opcode; - public InjectionPointData(IMixinContext mixin, MethodNode method, AnnotationNode parent, String at, List args, String target, + public InjectionPointData(IMixinContext context, MethodNode method, AnnotationNode parent, String at, List args, String target, String slice, int ordinal, int opcode) { - this.mixin = mixin; + this.context = context; this.method = method; this.parent = parent; this.at = at; @@ -146,101 +147,165 @@ private void parseArgs(List args) { } } + /** + * Get the at value on the injector + */ public String getAt() { return this.at; } + /** + * Get the parsed constructor type for this injector + */ public String getType() { return this.type; } + /** + * Get the selector value parsed from the injector + */ public Selector getSelector() { return this.selector; } - public IMixinContext getMixin() { - return this.mixin; + /** + * Get the context + */ + public IMixinContext getContext() { + return this.context; } + /** + * Get the annotated method + */ public MethodNode getMethod() { return this.method; } + /** + * Get the return type of the annotated method + */ + public Type getMethodReturnType() { + return Type.getReturnType(this.method.desc); + } + + /** + * Get the root annotation (eg. {@link Inject}) + */ public AnnotationNode getParent() { return this.parent; } + /** + * Get the slice id specified on the injector + */ public String getSlice() { return this.slice; } - public Type getReturnType() { - return Type.getReturnType(this.method.desc); - } - public LocalVariableDiscriminator getLocalVariableDiscriminator() { return LocalVariableDiscriminator.parse(this.parent); } + /** + * Get the supplied value from the named args, return defaultValue if the + * arg is not set + * + * @param key argument name + * @param defaultValue value to return if the arg is not set + * @return argument value or default if not set + */ public String get(String key, String defaultValue) { String value = this.args.get(key); return value != null ? value : defaultValue; } + /** + * Get the supplied value from the named args, return defaultValue if the + * arg is not set + * + * @param key argument name + * @param defaultValue value to return if the arg is not set + * @return argument value or default if not set + */ public int get(String key, int defaultValue) { - return this.parseInt(this.get(key, String.valueOf(defaultValue)), defaultValue); + return InjectionPointData.parseInt(this.get(key, String.valueOf(defaultValue)), defaultValue); } + /** + * Get the supplied value from the named args, return defaultValue if the + * arg is not set + * + * @param key argument name + * @param defaultValue value to return if the arg is not set + * @return argument value or default if not set + */ public boolean get(String key, boolean defaultValue) { - return this.parseBoolean(this.get(key, String.valueOf(defaultValue)), defaultValue); + return InjectionPointData.parseBoolean(this.get(key, String.valueOf(defaultValue)), defaultValue); } + /** + * Get the supplied value from the named args as a {@link MemberInfo}, + * throws an exception if the argument cannot be parsed as a MemberInfo. + * + * @param key argument name + * @return argument value as a MemberInfo + */ public MemberInfo get(String key) { try { - return MemberInfo.parseAndValidate(this.get(key, ""), this.mixin); + return MemberInfo.parseAndValidate(this.get(key, ""), this.context); } catch (InvalidMemberDescriptorException ex) { - throw new InvalidInjectionPointException(this.mixin, "Failed parsing @At(\"%s\").%s descriptor \"%s\" on %s", - this.at, key, this.target, InjectionInfo.describeInjector(this.mixin, this.parent, this.method)); - } - } - - private int parseInt(String string, int defaultValue) { - try { - return Integer.parseInt(string); - } catch (Exception ex) { - return defaultValue; - } - } - - private boolean parseBoolean(String string, boolean defaultValue) { - try { - return Boolean.parseBoolean(string); - } catch (Exception ex) { - return defaultValue; + throw new InvalidInjectionPointException(this.context, "Failed parsing @At(\"%s\").%s descriptor \"%s\" on %s", + this.at, key, this.target, InjectionInfo.describeInjector(this.context, this.parent, this.method)); } } + /** + * Get the target value specified on the injector + */ public MemberInfo getTarget() { try { - return MemberInfo.parseAndValidate(this.target, this.mixin); + return MemberInfo.parseAndValidate(this.target, this.context); } catch (InvalidMemberDescriptorException ex) { - throw new InvalidInjectionPointException(this.mixin, "Failed parsing @At(\"%s\") descriptor \"%s\" on %s", - this.at, this.target, InjectionInfo.describeInjector(this.mixin, this.parent, this.method)); + throw new InvalidInjectionPointException(this.context, "Failed parsing @At(\"%s\") descriptor \"%s\" on %s", + this.at, this.target, InjectionInfo.describeInjector(this.context, this.parent, this.method)); } } + /** + * Get the ordinal specified on the injection point + */ public int getOrdinal() { return this.ordinal; } + /** + * Get the opcode specified on the injection point + */ public int getOpcode() { return this.opcode; } + /** + * Get the opcode specified on the injection point or return the default if + * no opcode was specified + * + * @param defaultOpcode opcode to return if none specified + * @return opcode or default + */ public int getOpcode(int defaultOpcode) { return this.opcode > 0 ? this.opcode : defaultOpcode; } + /** + * Get the opcode specified on the injection point or return the default if + * no opcode was specified or if the specified opcode does not appear in the + * supplied list of valid opcodes + * + * @param defaultOpcode opcode to return if none specified + * @param validOpcodes valid opcodes + * @return opcode or default + */ public int getOpcode(int defaultOpcode, int... validOpcodes) { for (int validOpcode : validOpcodes) { if (this.opcode == validOpcode) { @@ -259,6 +324,17 @@ private static Pattern createPattern() { return Pattern.compile(String.format("^([^:]+):?(%s)?$", Joiner.on('|').join(Selector.values()))); } + /** + * Parse a constructor type from the supplied at string + * + * @param at at to parse + * @return parsed constructor type + */ + public static String parseType(String at) { + Matcher matcher = InjectionPointData.AT_PATTERN.matcher(at); + return InjectionPointData.parseType(matcher, at); + } + private static String parseType(Matcher matcher, String at) { return matcher.matches() ? matcher.group(1) : at; } @@ -266,10 +342,21 @@ private static String parseType(Matcher matcher, String at) { private static Selector parseSelector(Matcher matcher) { return matcher.matches() && matcher.group(2) != null ? Selector.valueOf(matcher.group(2)) : Selector.DEFAULT; } - - public static String parseType(String at) { - Matcher matcher = InjectionPointData.AT_PATTERN.matcher(at); - return InjectionPointData.parseType(matcher, at); + + private static int parseInt(String string, int defaultValue) { + try { + return Integer.parseInt(string); + } catch (Exception ex) { + return defaultValue; + } } + private static boolean parseBoolean(String string, boolean defaultValue) { + try { + return Boolean.parseBoolean(string); + } catch (Exception ex) { + return defaultValue; + } + } + } diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/struct/MemberInfo.java b/src/main/java/org/spongepowered/asm/mixin/injection/struct/MemberInfo.java index ccb26b8e6..415322e54 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/struct/MemberInfo.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/struct/MemberInfo.java @@ -282,6 +282,9 @@ public String toSrg() { return this.owner + "/" + this.name; } + /** + * Returns this MemberInfo as a java-style descriptor + */ public String toDescriptor() { if (this.desc == null) { return ""; @@ -290,6 +293,9 @@ public String toDescriptor() { return new SignaturePrinter(this).setFullyQualified(true).toDescriptor(); } + /** + * Returns the constructor type represented by this MemberInfo + */ public String toCtorType() { if (this.unparsed == null) { return null; @@ -311,6 +317,10 @@ public String toCtorType() { return this.desc != null ? this.desc : this.unparsed; } + /** + * Returns the constructor descriptor represented by this + * MemberInfo, returns null if no descriptor is present. + */ public String toCtorDesc() { if (this.desc != null && this.desc.startsWith("(") && this.desc.indexOf(')') > -1) { return this.desc.substring(0, this.desc.indexOf(')') + 1) + "V"; @@ -319,6 +329,11 @@ public String toCtorDesc() { return null; } + /** + * Get the return type for this MemberInfo, if the decriptor is present, + * returns null if the descriptor is absent or if this MemberInfo represents + * a field + */ public String getReturnType() { if (this.desc == null || this.desc.indexOf(')') == -1 || this.desc.indexOf('(') != 0 ) { return null; @@ -331,10 +346,17 @@ public String getReturnType() { return returnType; } + /** + * Returns this MemberInfo as a {@link MappingField} or + * {@link MappingMethod} + */ public IMapping asMapping() { return this.isField() ? this.asFieldMapping() : this.asMethodMapping(); } + /** + * Returns this MemberInfo as a mapping method + */ public MappingMethod asMethodMapping() { if (!this.isFullyQualified()) { throw new MixinException("Cannot convert unqualified reference " + this + " to MethodMapping"); @@ -347,6 +369,9 @@ public MappingMethod asMethodMapping() { return new MappingMethod(this.owner, this.name, this.desc); } + /** + * Returns this MemberInfo as a mapping field + */ public MappingField asFieldMapping() { if (!this.isField()) { throw new MixinException("Cannot convert non-field reference " + this + " to FieldMapping"); @@ -620,12 +645,14 @@ private static MemberInfo parse(String input, ReferenceMapper refMapper, String return new MemberInfo(name, owner, desc, matchAll, input); } + /** + * Return the supplied mapping parsed as a MemberInfo + * + * @param mapping mapping to parse + * @return new MemberInfo + */ public static MemberInfo fromMapping(IMapping mapping) { return new MemberInfo(mapping); } - - public static void main(String[] args) { - MemberInfo m = MemberInfo.parseAndValidate(null); //"(Lfoo;III)Lfoo/bar/qcv;"); - System.err.printf(">> [%s] [%s]\n", m.toCtorType(), m.toCtorDesc()); - } + } diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/struct/ModifyConstantInjectionInfo.java b/src/main/java/org/spongepowered/asm/mixin/injection/struct/ModifyConstantInjectionInfo.java index 36e52a5df..aa9b42efc 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/struct/ModifyConstantInjectionInfo.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/struct/ModifyConstantInjectionInfo.java @@ -104,7 +104,7 @@ public boolean find(String desc, InsnList insns, Collection no if (this.log) { BeforeConstant.logger.info("BeforeConstant is searching for an constants in method with descriptor {}", desc); - } + } ListIterator iter = insns.iterator(); for (int ordinal = 0; iter.hasNext();) { @@ -118,7 +118,7 @@ public boolean find(String desc, InsnList insns, Collection no } if (this.ordinal == -1 || this.ordinal == ordinal) { if (this.log) { - BeforeConstant.logger.info(" BeforeConstant found {}", ASMHelper.getNodeDescriptionForDebug(insn).trim()); + BeforeConstant.logger.info(" BeforeConstant found {}", ASMHelper.describeNode(insn).trim()); } nodes.add(insn); found = true; diff --git a/src/main/java/org/spongepowered/asm/mixin/injection/struct/Target.java b/src/main/java/org/spongepowered/asm/mixin/injection/struct/Target.java index d895ee2cb..645671394 100644 --- a/src/main/java/org/spongepowered/asm/mixin/injection/struct/Target.java +++ b/src/main/java/org/spongepowered/asm/mixin/injection/struct/Target.java @@ -41,6 +41,9 @@ */ public class Target implements Comparable, Iterable { + /** + * Target class node + */ public final ClassNode classNode; /** @@ -177,8 +180,7 @@ public int allocateLocals(int locals) { } /** - * Allocate a number of new stack variables for this method, returns the - * first stack index of the allocated range + * Allocate a number of new local variables for this method * * @param locals number of locals to allocate */ @@ -186,16 +188,33 @@ public void addToLocals(int locals) { this.setMaxLocals(this.maxLocals + locals); } + /** + * Set the maxlocals for this target to the specified value, the specfied + * value must be higher than the original max locals + * + * @param maxLocals max locals value to set + */ public void setMaxLocals(int maxLocals) { if (maxLocals > this.method.maxLocals) { this.method.maxLocals = maxLocals; } } + /** + * Allocate a number of new stack variables for this method + * + * @param stack number of stack entries to allocate + */ public void addToStack(int stack) { this.setMaxStack(this.maxStack + stack); } + /** + * Set the max stack size for this target to the specified value, the + * specfied value must be higher than the original max stack + * + * @param maxStack max stack value to set + */ public void setMaxStack(int maxStack) { if (maxStack > this.method.maxStack) { this.method.maxStack = maxStack; @@ -290,14 +309,29 @@ public int compareTo(Target o) { return this.toString().compareTo(o.toString()); } + /** + * Return the index of the specified instruction in this instruction list + * + * @param insn instruction to locate, must exist in the target + * @return opcode index + */ public int indexOf(AbstractInsnNode insn) { return this.insns.indexOf(insn); } + /** + * Return the instruction at the specified index + * + * @param index opcode index + * @return requested instruction + */ public AbstractInsnNode get(int index) { return this.insns.get(index); } + /* (non-Javadoc) + * @see java.lang.Iterable#iterator() + */ @Override public Iterator iterator() { return this.insns.iterator(); @@ -337,6 +371,7 @@ public void replaceNode(AbstractInsnNode location, AbstractInsnNode champion, In * @param location Instruction to replace * @param champion Instruction which notionally replaces the original insn * @param before Instructions to actually insert (must contain champion) + * @param after Instructions to insert after the specified location */ public void wrapNode(AbstractInsnNode location, AbstractInsnNode champion, InsnList before, InsnList after) { this.insns.insertBefore(location, before); diff --git a/src/main/java/org/spongepowered/asm/mixin/refmap/IMixinContext.java b/src/main/java/org/spongepowered/asm/mixin/refmap/IMixinContext.java index 0021372d5..2ac9d58d4 100644 --- a/src/main/java/org/spongepowered/asm/mixin/refmap/IMixinContext.java +++ b/src/main/java/org/spongepowered/asm/mixin/refmap/IMixinContext.java @@ -53,10 +53,28 @@ public interface IMixinContext { */ public abstract ReferenceMapper getReferenceMapper(); + /** + * Retrieve the value of the specified option from the environment + * this mixin belongs to. + * + * @param option option to check + * @return option value + */ public abstract boolean getOption(Option option); + /** + * Get the priority of the mixin + */ public abstract int getPriority(); - public abstract Target getTargetMethod(MethodNode into); + /** + * Obtain a {@link Target} method handle for a method in the target, this is + * used by consumers to manipulate the bytecode in a target method in a + * controlled manner. + * + * @param method method node to wrap + * @return target method + */ + public abstract Target getTargetMethod(MethodNode method); } diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/ClassInfo.java b/src/main/java/org/spongepowered/asm/mixin/transformer/ClassInfo.java index 92a642491..22e48188f 100644 --- a/src/main/java/org/spongepowered/asm/mixin/transformer/ClassInfo.java +++ b/src/main/java/org/spongepowered/asm/mixin/transformer/ClassInfo.java @@ -63,7 +63,7 @@ * information needed to support more complex mixin behaviour such as detached * superclass and mixin inheritance. */ -public class ClassInfo extends TreeInfo { +public final class ClassInfo extends TreeInfo { public static final int INCLUDE_PRIVATE = Opcodes.ACC_PRIVATE; public static final int INCLUDE_STATIC = Opcodes.ACC_STATIC; @@ -137,10 +137,16 @@ private Traversal(Traversal next, boolean traverse, SearchType searchType) { this.searchType = searchType; } + /** + * Return the next traversal type for this traversal type + */ public Traversal next() { return this.next; } + /** + * Return whether this traversal type allows traversal + */ public boolean canTraverse() { return this.traverse; } @@ -158,10 +164,19 @@ public static class FrameData { private static final String[] FRAMETYPES = { "NEW", "FULL", "APPEND", "CHOP", "SAME", "SAME1" }; + /** + * Frame index + */ public final int index; + /** + * Frame type + */ public final int type; + /** + * Frame local count + */ public final int locals; FrameData(int index, int type, int locals) { @@ -338,7 +353,7 @@ public int getAccess() { } /** - * @param name + * @param name new name * @return the passed-in argument, for fluency */ public String renameTo(String name) { @@ -964,7 +979,7 @@ private ClassInfo addMethodsRecursive(Set methods, boolean includeMixins * * @param superClass Name of the superclass to search for in the hierarchy * @return true if the specified class appears in the class's hierarchy - * anywhere + * anywhere */ public boolean hasSuperClass(String superClass) { return this.hasSuperClass(superClass, Traversal.NONE); @@ -976,7 +991,7 @@ public boolean hasSuperClass(String superClass) { * @param superClass Name of the superclass to search for in the hierarchy * @param traversal Traversal type to allow during this lookup * @return true if the specified class appears in the class's hierarchy - * anywhere + * anywhere */ public boolean hasSuperClass(String superClass, Traversal traversal) { if (ClassInfo.JAVA_LANG_OBJECT.equals(superClass)) { @@ -991,7 +1006,7 @@ public boolean hasSuperClass(String superClass, Traversal traversal) { * * @param superClass Superclass to search for in the hierarchy * @return true if the specified class appears in the class's hierarchy - * anywhere + * anywhere */ public boolean hasSuperClass(ClassInfo superClass) { return this.hasSuperClass(superClass, Traversal.NONE); @@ -1003,7 +1018,7 @@ public boolean hasSuperClass(ClassInfo superClass) { * @param superClass Superclass to search for in the hierarchy * @param traversal Traversal type to allow during this lookup * @return true if the specified class appears in the class's hierarchy - * anywhere + * anywhere */ public boolean hasSuperClass(ClassInfo superClass, Traversal traversal) { if (ClassInfo.OBJECT == superClass) { diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/InterfaceInfo.java b/src/main/java/org/spongepowered/asm/mixin/transformer/InterfaceInfo.java index 62e4746b8..b53a8e813 100644 --- a/src/main/java/org/spongepowered/asm/mixin/transformer/InterfaceInfo.java +++ b/src/main/java/org/spongepowered/asm/mixin/transformer/InterfaceInfo.java @@ -42,7 +42,7 @@ * Information about an interface being runtime-patched onto a mixin target * class, see {@link org.spongepowered.asm.mixin.Implements Implements} */ -public class InterfaceInfo extends TreeInfo { +public final class InterfaceInfo extends TreeInfo { /** * Parent mixin diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/MemberRef.java b/src/main/java/org/spongepowered/asm/mixin/transformer/MemberRef.java index 111a0f769..79475c4c6 100644 --- a/src/main/java/org/spongepowered/asm/mixin/transformer/MemberRef.java +++ b/src/main/java/org/spongepowered/asm/mixin/transformer/MemberRef.java @@ -31,11 +31,10 @@ import org.spongepowered.asm.util.ASMHelper; /** - * Reference to a field or method that also includes invocation - * instructions. + * Reference to a field or method that also includes invocation instructions. * - * To instances are defined to be equal if they both refer to the same method - * and have the same invocation instructions. + *

To instances are defined to be equal if they both refer to the same method + * and have the same invocation instructions.

*/ public abstract class MemberRef { diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/MethodMapper.java b/src/main/java/org/spongepowered/asm/mixin/transformer/MethodMapper.java index d77290344..da119d6dd 100644 --- a/src/main/java/org/spongepowered/asm/mixin/transformer/MethodMapper.java +++ b/src/main/java/org/spongepowered/asm/mixin/transformer/MethodMapper.java @@ -74,6 +74,13 @@ public ClassInfo getClassInfo() { return this.info; } + /** + * Conforms an injector handler method + * + * @param mixin owner mixin + * @param handler annotated injector handler method + * @param method method in target + */ public void remapHandlerMethod(MixinInfo mixin, MethodNode handler, Method method) { if (!(handler instanceof MixinMethodNode) || !((MixinMethodNode)handler).isInjector()) { return; @@ -92,6 +99,12 @@ public void remapHandlerMethod(MixinInfo mixin, MethodNode handler, Method metho handler.name = method.renameTo(handlerName); } + /** + * Get the name for a handler method provided a source mixin method + * + * @param method mixin method + * @return conformed handler name + */ public String getHandlerName(MixinMethodNode method) { String prefix = InjectionInfo.getInjectorPrefix(method.getInjectorAnnotation()); String classUID = MethodMapper.getClassUID(method.getOwner().getClassRef()); diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/MixinApplicatorStandard.java b/src/main/java/org/spongepowered/asm/mixin/transformer/MixinApplicatorStandard.java index 16ea3e3ce..84a7b5886 100644 --- a/src/main/java/org/spongepowered/asm/mixin/transformer/MixinApplicatorStandard.java +++ b/src/main/java/org/spongepowered/asm/mixin/transformer/MixinApplicatorStandard.java @@ -310,7 +310,7 @@ protected void applySignature(MixinTargetContext mixin) { /** * Mixin interfaces implemented by the mixin class onto the target class * - * @param mixin + * @param mixin mixin target context */ protected void applyInterfaces(MixinTargetContext mixin) { for (String interfaceName : mixin.getInterfaces()) { @@ -324,7 +324,7 @@ protected void applyInterfaces(MixinTargetContext mixin) { /** * Mixin misc attributes from mixin class onto the target class * - * @param mixin + * @param mixin mixin target context */ protected void applyAttributes(MixinTargetContext mixin) { if (mixin.shouldSetSourceFile()) { @@ -336,7 +336,7 @@ protected void applyAttributes(MixinTargetContext mixin) { /** * Mixin class-level annotations on the mixin into the target class * - * @param mixin + * @param mixin mixin target context */ protected void applyAnnotations(MixinTargetContext mixin) { ClassNode sourceClass = mixin.getClassNode(); @@ -349,7 +349,7 @@ protected void applyAnnotations(MixinTargetContext mixin) { * fields so that transformMethod can rename field references in the method * body. * - * @param mixin + * @param mixin mixin target context */ protected void applyFields(MixinTargetContext mixin) { this.mergeShadowFields(mixin); @@ -384,7 +384,7 @@ protected void mergeNewFields(MixinTargetContext mixin) { /** * Mixin methods from the mixin class into the target class * - * @param mixin + * @param mixin mixin target context */ protected void applyMethods(MixinTargetContext mixin) { for (MethodNode shadow : mixin.getShadowMethods()) { @@ -413,7 +413,7 @@ protected void applyNormalMethod(MixinTargetContext mixin, MethodNode mixinMetho this.mergeMethod(mixin, mixinMethod); } else if (Constants.CLINIT.equals(mixinMethod.name)) { // Class initialiser insns get appended - this.appendInsns(mixinMethod); + this.appendInsns(mixin, mixinMethod); } } @@ -576,9 +576,10 @@ protected void displaceIntrinsic(MixinTargetContext mixin, MethodNode method, Me * Handles appending instructions from the source method to the target * method. Both methods must return void * - * @param method + * @param mixin mixin target context + * @param method source method */ - protected final void appendInsns(MethodNode method) { + protected final void appendInsns(MixinTargetContext mixin, MethodNode method) { if (Type.getReturnType(method.desc) != Type.VOID_TYPE) { throw new IllegalArgumentException("Attempted to merge insns from a method which does not return void"); } @@ -611,7 +612,7 @@ protected final void appendInsns(MethodNode method) { * (Attempts to) find and patch field initialisers from the mixin into the * target class * - * @param mixin + * @param mixin mixin target context */ protected void applyInitialisers(MixinTargetContext mixin) { // Try to find a suitable constructor, we need a constructor with line numbers in order to extract the initialiser @@ -662,7 +663,7 @@ protected MethodNode getConstructor(MixinTargetContext mixin) { * Identifies line numbers in the supplied ctor which correspond to the * start and end of the method body. * - * @param ctor + * @param ctor constructor to scan * @return range indicating the line numbers of the specified constructor * and the position of the superclass ctor invocation */ @@ -706,14 +707,16 @@ private Range getConstructorRange(MethodNode ctor) { * Get insns corresponding to the instance initialiser (hopefully) from the * supplied constructor. * - * TODO Potentially rewrite this to be less horrible. - * - * @param mixin - * @param ctor + * @param mixin mixin target context + * @param ctor constructor to inspect * @return initialiser bytecode extracted from the supplied constructor, or * null if the constructor range could not be parsed */ protected final Deque getInitialiser(MixinTargetContext mixin, MethodNode ctor) { + // + // TODO Potentially rewrite this to be less horrible. + // + // Find the range of line numbers which corresponds to the constructor body Range init = this.getConstructorRange(ctor); if (!init.isValid()) { @@ -781,8 +784,9 @@ protected final Deque getInitialiser(MixinTargetContext mixin, /** * Inject initialiser code into the target constructor * - * @param ctor - * @param initialiser + * @param mixin mixin target context + * @param ctor target constructor + * @param initialiser initialiser instructions */ protected final void injectInitialiser(MixinTargetContext mixin, MethodNode ctor, Deque initialiser) { Map labels = ASMHelper.cloneLabels(ctor.instructions); @@ -901,8 +905,8 @@ protected void applyAccessors(MixinTargetContext mixin) { /** * Check visibility before merging a mixin method * - * @param mixin - * @param mixinMethod + * @param mixin mixin target context + * @param mixinMethod method to check */ protected void checkMethodVisibility(MixinTargetContext mixin, MethodNode mixinMethod) { if (ASMHelper.hasFlag(mixinMethod, Opcodes.ACC_STATIC) diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/MixinConfig.java b/src/main/java/org/spongepowered/asm/mixin/transformer/MixinConfig.java index dff633424..901d63a06 100644 --- a/src/main/java/org/spongepowered/asm/mixin/transformer/MixinConfig.java +++ b/src/main/java/org/spongepowered/asm/mixin/transformer/MixinConfig.java @@ -62,7 +62,7 @@ /** * Mixin configuration bundle */ -class MixinConfig implements Comparable, IMixinConfig { +final class MixinConfig implements Comparable, IMixinConfig { /** * Wrapper for injection options @@ -738,7 +738,7 @@ public boolean packageMatch(String className) { * Check whether this configuration bundle has a mixin for the specified * class * - * @param targetClass + * @param targetClass target class * @return true if this bundle contains any mixins for the specified target */ public boolean hasMixinsFor(String targetClass) { @@ -748,7 +748,7 @@ public boolean hasMixinsFor(String targetClass) { /** * Get mixins for the specified target class * - * @param targetClass + * @param targetClass target class * @return mixins for the specified target */ public List getMixinsFor(String targetClass) { @@ -805,7 +805,7 @@ public int compareTo(MixinConfig other) { * Factory method, creates a new mixin configuration bundle from the * specified configFile, which must be accessible on the classpath * - * @param configFile + * @param configFile configuration file to load * @param outer fallback environment * @return new Config */ diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/MixinInfo.java b/src/main/java/org/spongepowered/asm/mixin/transformer/MixinInfo.java index b0f1aa0cb..87d687fc2 100644 --- a/src/main/java/org/spongepowered/asm/mixin/transformer/MixinInfo.java +++ b/src/main/java/org/spongepowered/asm/mixin/transformer/MixinInfo.java @@ -479,7 +479,8 @@ boolean isDetachedSuper() { /** * True if this mixin class can actually be classloaded * - * @return + * @return whether this subtype is directly classloadable (supports + * classloader pinholing) */ boolean isLoadable() { return false; @@ -488,8 +489,8 @@ boolean isLoadable() { /** * Validate a single target before adding * - * @param targetName - * @param targetInfo + * @param targetName target class name + * @param targetInfo information about the target class */ void validateTarget(String targetName, ClassInfo targetInfo) { boolean targetIsInterface = targetInfo.isInterface(); @@ -740,11 +741,13 @@ static SubType getTypeFor(MixinInfo mixin) { /** * Internal ctor, called by {@link MixinConfig} * - * @param parent - * @param mixinName - * @param runTransformers - * @param plugin - * @param suppressPlugin + * @param parent configuration which owns this mixin, the parent + * @param mixinName name of this mixin (class name stub) + * @param runTransformers true if this mixin should run transformers on its + * bytecode when loading + * @param plugin mixin config companion plugin, may be null + * @param suppressPlugin true to suppress the plugin from filtering targets + * of this mixin */ MixinInfo(MixinConfig parent, String mixinName, boolean runTransformers, IMixinConfigPlugin plugin, boolean suppressPlugin) { this.parent = parent; @@ -805,8 +808,8 @@ void validate() { /** * Read the target class names from the {@link Mixin} annotation * - * @param classNode - * @param suppressPlugin + * @param classNode mixin classnode + * @param suppressPlugin true to suppress plugin filtering targets * @return target class list read from classNode */ protected List readTargetClasses(MixinClassNode classNode, boolean suppressPlugin) { @@ -896,7 +899,7 @@ private void handleTargetError(String message) { /** * Read the priority from the {@link Mixin} annotation * - * @param classNode + * @param classNode mixin classnode * @return priority read from classNode */ protected int readPriority(ClassNode classNode) { @@ -1092,7 +1095,7 @@ Set getInterfaces() { /** * Get a new mixin target context object for the specified target * - * @param target + * @param target target class context * @return new context */ MixinTargetContext createContextFor(TargetClassContext target) { @@ -1101,10 +1104,12 @@ MixinTargetContext createContextFor(TargetClassContext target) { } /** - * @param mixinClassName - * @param runTransformers - * @return - * @throws ClassNotFoundException + * Load the mixin class bytes + * + * @param mixinClassName mixin class name + * @param runTransformers true to run transformers on the loaded bytecode + * @return mixin bytecode + * @throws ClassNotFoundException if the mixin bytes could not be found */ private byte[] loadMixinClass(String mixinClassName, boolean runTransformers) throws ClassNotFoundException { byte[] mixinBytes = null; diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/MixinPreProcessorStandard.java b/src/main/java/org/spongepowered/asm/mixin/transformer/MixinPreProcessorStandard.java index 6c5335be7..d0aa05a51 100644 --- a/src/main/java/org/spongepowered/asm/mixin/transformer/MixinPreProcessorStandard.java +++ b/src/main/java/org/spongepowered/asm/mixin/transformer/MixinPreProcessorStandard.java @@ -188,7 +188,7 @@ MixinTargetContext createContextFor(TargetClassContext target) { /** * Run the second pass, attach to the specified context * - * @param context + * @param context mixin target context */ MixinPreProcessorStandard attach(MixinTargetContext context) { if (this.attached) { @@ -474,8 +474,8 @@ protected void attachFields(MixinTargetContext context) { boolean isFinal = field.isDecoratedFinal(); if (this.verboseLogging && ASMHelper.hasFlag(target, Opcodes.ACC_FINAL) != isFinal) { String message = isFinal - ? "@Shadow field {}::{} is decorated with @Final but target is not final" - : "@Shadow target {}::{} is final but shadow is not decorated with @Final"; + ? "@Shadow field {}::{} is decorated with @Final but target is not final" + : "@Shadow target {}::{} is final but shadow is not decorated with @Final"; MixinPreProcessorStandard.logger.warn(message, this.mixin, mixinField.name); } diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/MixinTargetContext.java b/src/main/java/org/spongepowered/asm/mixin/transformer/MixinTargetContext.java index 32bf23029..b7e514fd8 100644 --- a/src/main/java/org/spongepowered/asm/mixin/transformer/MixinTargetContext.java +++ b/src/main/java/org/spongepowered/asm/mixin/transformer/MixinTargetContext.java @@ -180,21 +180,29 @@ public class MixinTargetContext implements IMixinContext { } /** - * @param method + * Add a shadow method to this mixin context, called by the preprocessor + * + * @param method shadow method to add */ void addShadowMethod(MethodNode method) { this.shadowMethods.add(method); } /** - * @param fieldNode + * Add a shadow field to this mixin context, called by the preprocessor + * + * @param fieldNode field node + * @param fieldInfo field info */ void addShadowField(FieldNode fieldNode, Field fieldInfo) { this.shadowFields.put(fieldNode, fieldInfo); } /** - * @param method + * Add an accessor method to this mixin context, called by the preprocessor + * + * @param method method to add + * @param type annotation type */ void addAccessorMethod(MethodNode method, Class type) { this.accessors.add(AccessorInfo.of(this, method, type)); @@ -203,7 +211,7 @@ void addAccessorMethod(MethodNode method, Class type) { /** * Callback from the applicator which notifies us that a method was merged * - * @param method + * @param method merged method */ void addMergedMethod(MethodNode method) { this.mergedMethods.add(method); @@ -1032,10 +1040,26 @@ public void postApply(String transformedName, ClassNode targetClass) { this.mixin.postApply(transformedName, targetClass); } + /** + * Obtain a unique name for the specified method from the target class + * context + * + * @param method method to obtain a name for + * @param preservePrefix true to preserve the method prefix (decorate as + * postfix) otherwise decorates as infix + * @return unique method name + */ public String getUniqueName(MethodNode method, boolean preservePrefix) { return this.targetClass.getUniqueName(method, preservePrefix); } + /** + * Obtain a unique name for the specified field from the target class + * context + * + * @param field field to obtain a name for + * @return unique field name + */ public String getUniqueName(FieldNode field) { return this.targetClass.getUniqueName(field); } @@ -1077,6 +1101,10 @@ public void applyInjections() { this.injectors.clear(); } + /** + * Expand accessor methods mixed into the target class by populating the + * method bodies + */ public List generateAccessors() { for (AccessorInfo accessor : this.accessors) { accessor.locate(); diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/MixinTransformer.java b/src/main/java/org/spongepowered/asm/mixin/transformer/MixinTransformer.java index 18929e302..bcca2d131 100644 --- a/src/main/java/org/spongepowered/asm/mixin/transformer/MixinTransformer.java +++ b/src/main/java/org/spongepowered/asm/mixin/transformer/MixinTransformer.java @@ -333,8 +333,7 @@ private IDecompiler initDecompiler(File outputPath) { MixinTransformer.logger.info("Attempting to load Fernflower decompiler{}", as ? " (Threaded mode)" : ""); String className = "org.spongepowered.asm.mixin.transformer.debug.RuntimeDecompiler" + (as ? "Async" : ""); @SuppressWarnings("unchecked") - Class clazz = - (Class)Class.forName(className); + Class clazz = (Class)Class.forName(className); Constructor ctor = clazz.getDeclaredConstructor(File.class); IDecompiler decompiler = ctor.newInstance(outputPath); MixinTransformer.logger.info("Fernflower decompiler was successfully initialised, exported classes will be decompiled{}", @@ -779,7 +778,7 @@ public void onInit(MixinInfo mixin) { * Apply mixins for specified target class to the class described by the * supplied byte array. * - * @param context + * @param context target class context * @return class bytecode after application of mixins */ private byte[] applyMixins(TargetClassContext context) { diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/TargetClassContext.java b/src/main/java/org/spongepowered/asm/mixin/transformer/TargetClassContext.java index ea11fb0eb..294aa732b 100644 --- a/src/main/java/org/spongepowered/asm/mixin/transformer/TargetClassContext.java +++ b/src/main/java/org/spongepowered/asm/mixin/transformer/TargetClassContext.java @@ -218,8 +218,8 @@ MethodNode findAliasedMethod(Deque aliases, String desc) { /** * Finds a field in the target class * - * @param aliases - * @param desc + * @param aliases aliases for the field + * @param desc field descriptor * @return Target field or null if not found */ FieldNode findAliasedField(Deque aliases, String desc) { diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/TreeInfo.java b/src/main/java/org/spongepowered/asm/mixin/transformer/TreeInfo.java index 91a8b032f..0cc92f716 100644 --- a/src/main/java/org/spongepowered/asm/mixin/transformer/TreeInfo.java +++ b/src/main/java/org/spongepowered/asm/mixin/transformer/TreeInfo.java @@ -104,7 +104,7 @@ protected static byte[] loadClass(String className, boolean runTransformers) thr * @param name Original class name * @param transformedName Name of the class to load * @return raw class bytecode - * @throws IOException + * @throws IOException if an error occurs reading the class bytes */ private static byte[] getClassBytes(String name, String transformedName) throws IOException { byte[] classBytes = Launch.classLoader.getClassBytes(name); @@ -130,9 +130,9 @@ private static byte[] getClassBytes(String name, String transformedName) throws * Since we obtain the class bytes with getClassBytes(), we need to apply * the transformers ourself * - * @param name - * @param transformedName - * @param basicClass + * @param name class name + * @param transformedName transformed class name + * @param basicClass input class bytes * @return class bytecode after processing by all registered transformers * except the excluded transformers */ diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/debug/IHotSwap.java b/src/main/java/org/spongepowered/asm/mixin/transformer/debug/IHotSwap.java index cca77c9af..ecfbe0dd7 100644 --- a/src/main/java/org/spongepowered/asm/mixin/transformer/debug/IHotSwap.java +++ b/src/main/java/org/spongepowered/asm/mixin/transformer/debug/IHotSwap.java @@ -32,7 +32,7 @@ public interface IHotSwap { /** * Registers a mixin class with the agent. * - * This is needed as the mixin needs to be loaded to be redefined. + *

This is needed as the mixin needs to be loaded to be redefined.

* * @param name Fully qualified name of the mixin class */ @@ -41,8 +41,8 @@ public interface IHotSwap { /** * Registers a class targeted by at least one mixin. * - * This is used to rollback the target class to a state before the mixin's - * where applied. + *

This is used to rollback the target class to a state before the + * mixin's were applied.

* * @param name Name of the class * @param bytecode Bytecode of the class before mixin's have been applied diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/meta/SourceMap.java b/src/main/java/org/spongepowered/asm/mixin/transformer/meta/SourceMap.java index f3b0e8a4b..2dc4ee2b4 100644 --- a/src/main/java/org/spongepowered/asm/mixin/transformer/meta/SourceMap.java +++ b/src/main/java/org/spongepowered/asm/mixin/transformer/meta/SourceMap.java @@ -135,6 +135,11 @@ void appendFile(StringBuilder sb) { } } + /** + * Append lines representing this File to the supplied StringBuilder + * + * @param sb StringBuilder to append to + */ public void appendLines(StringBuilder sb) { sb.append("1#").append(this.id) // Map line number 1 (onwards) in file number .append(",").append(this.size) // repeated times (eg. lines 1 to ) @@ -217,18 +222,48 @@ public String getPseudoGeneratedSourceFile() { return this.sourceFile.replace(".java", "$mixin.java"); } + /** + * Add a file to this SourceMap in the default stratum + * + * @param classNode class node to read details from + * @return new File + */ public File addFile(ClassNode classNode) { return this.addFile(this.defaultStratum, classNode); } + /** + * Add a file to this SourceMap in the specified stratum + * + * @param stratumName name of the stratum to add to + * @param classNode class node to read file details from + * @return new File + */ public File addFile(String stratumName, ClassNode classNode) { return this.addFile(stratumName, classNode.sourceFile, classNode.name + ".java", ASMHelper.getMaxLineNumber(classNode, 500, 50)); } - public File addFile( String sourceFileName, String sourceFilePath, int size) { + /** + * Add a file to this SourceMap in the default stratum + * + * @param sourceFileName source filename + * @param sourceFilePath path to source file + * @param size number of lines to allocate + * @return new File + */ + public File addFile(String sourceFileName, String sourceFilePath, int size) { return this.addFile(this.defaultStratum, sourceFileName, sourceFilePath, size); } + /** + * Add a file to this SourceMap in the specified stratum + * + * @param stratumName name of the stratum to add to + * @param sourceFileName source filename + * @param sourceFilePath path to source file + * @param size number of lines to allocate + * @return new File + */ public File addFile(String stratumName, String sourceFileName, String sourceFilePath, int size) { Stratum stratum = this.strata.get(stratumName); if (stratum == null) { diff --git a/src/main/java/org/spongepowered/asm/obfuscation/RemapperChain.java b/src/main/java/org/spongepowered/asm/obfuscation/RemapperChain.java index 926c0358e..c6822240e 100644 --- a/src/main/java/org/spongepowered/asm/obfuscation/RemapperChain.java +++ b/src/main/java/org/spongepowered/asm/obfuscation/RemapperChain.java @@ -42,6 +42,12 @@ public String toString() { return String.format("RemapperChain[%d]", this.remappers.size()); } + /** + * Add a new remapper to this chain + * + * @param remapper remapper to add + * @return fluent interface + */ public RemapperChain add(IRemapper remapper) { this.remappers.add(remapper); return this; diff --git a/src/main/java/org/spongepowered/asm/obfuscation/mapping/common/MappingMethod.java b/src/main/java/org/spongepowered/asm/obfuscation/mapping/common/MappingMethod.java index 75e8c9df3..3b2597dc7 100644 --- a/src/main/java/org/spongepowered/asm/obfuscation/mapping/common/MappingMethod.java +++ b/src/main/java/org/spongepowered/asm/obfuscation/mapping/common/MappingMethod.java @@ -95,6 +95,13 @@ public MappingMethod copy() { return new MappingMethod(this.getOwner(), this.getSimpleName(), this.getDesc()); } + /** + * Return a clone of this mapping with the supplied prefix added. Returns + * this object if the prefix matches the existing name. + * + * @param prefix prefix to prepend + * @return cloned mapping + */ public MappingMethod addPrefix(String prefix) { String simpleName = this.getSimpleName(); if (simpleName == null || simpleName.startsWith(prefix)) { diff --git a/src/main/java/org/spongepowered/asm/util/ASMHelper.java b/src/main/java/org/spongepowered/asm/util/ASMHelper.java index 484ef163f..6aa3643ff 100644 --- a/src/main/java/org/spongepowered/asm/util/ASMHelper.java +++ b/src/main/java/org/spongepowered/asm/util/ASMHelper.java @@ -50,24 +50,39 @@ /** * Utility methods for working with ASM */ -public class ASMHelper { +public final class ASMHelper { + /** + * Integer constant opcodes + */ public static final int[] CONSTANTS_INT = { Opcodes.ICONST_M1, Opcodes.ICONST_0, Opcodes.ICONST_1, Opcodes.ICONST_2, Opcodes.ICONST_3, Opcodes.ICONST_4, Opcodes.ICONST_5 }; + /** + * Float constant opcodes + */ public static final int[] CONSTANTS_FLOAT = { Opcodes.FCONST_0, Opcodes.FCONST_1, Opcodes.FCONST_2 }; + /** + * Double constant opcodes + */ public static final int[] CONSTANTS_DOUBLE = { Opcodes.DCONST_0, Opcodes.DCONST_1 }; + /** + * Long constant opcodes + */ public static final int[] CONSTANTS_LONG = { Opcodes.LCONST_0, Opcodes.LCONST_1 }; + /** + * All constant opcodes + */ public static final int[] CONSTANTS_ALL = { Opcodes.ACONST_NULL, Opcodes.ICONST_M1, @@ -90,15 +105,19 @@ public class ASMHelper { }; private static final String[] CONSTANTS_TYPES = { - null, - "I", - "I", "I", "I", "I", "I", "I", - "J", "J", - "F", "F", "F", - "D", "D", - "I", //"B", - "I", //"S" + null, + "I", + "I", "I", "I", "I", "I", "I", + "J", "J", + "F", "F", "F", + "D", "D", + "I", //"B", + "I", //"S" }; + + private ASMHelper() { + // utility class + } /** * Finds a method given the method descriptor @@ -173,7 +192,7 @@ public static void printMethodWithOpcodeIndices(MethodNode method) { System.err.printf("%s%s\n", method.name, method.desc); int i = 0; for (Iterator iter = method.instructions.iterator(); iter.hasNext();) { - System.err.printf("[%4d] %s\n", i++, ASMHelper.getNodeDescriptionForDebug(iter.next())); + System.err.printf("[%4d] %s\n", i++, ASMHelper.describeNode(iter.next())); } } @@ -196,10 +215,20 @@ public static void printMethod(MethodNode method) { * @param node Node to print */ public static void printNode(AbstractInsnNode node) { - System.err.printf("%s\n", ASMHelper.getNodeDescriptionForDebug(node)); + System.err.printf("%s\n", ASMHelper.describeNode(node)); } - public static String getNodeDescriptionForDebug(AbstractInsnNode node) { + /** + * Gets a description of the supplied node for debugging purposes + * + * @param node node to describe + * @return human-readable description of node + */ + public static String describeNode(AbstractInsnNode node) { + if (node == null) { + return String.format(" %-14s ", "null"); + } + if (node instanceof LabelNode) { return String.format("[%s]", ((LabelNode)node).getLabel()); } @@ -645,10 +674,22 @@ public static > T getAnnotationValue(AnnotationNode annotation return Enum.valueOf(enumClass, value[1]); } + /** + * Returns true if the supplied method node is static + * + * @param method method node + * @return true if the method has the {@link Opcodes#ACC_STATIC} flag + */ public static boolean methodIsStatic(MethodNode method) { return (method.access & Opcodes.ACC_STATIC) == Opcodes.ACC_STATIC; } + /** + * Returns true if the supplied field node is static + * + * @param field field node + * @return true if the field has the {@link Opcodes#ACC_STATIC} flag + */ public static boolean fieldIsStatic(FieldNode field) { return (field.access & Opcodes.ACC_STATIC) == Opcodes.ACC_STATIC; } @@ -733,6 +774,14 @@ public static void loadArgs(Type[] args, InsnList insns, int start, int end) { } } + /** + * Clones all of the labels in the source instruction list and returns the + * clones in a map of old label -> new label. This is used to facilitate + * the use of {@link AbstractInsnNode#clone}. + * + * @param source instruction list + * @return map of existing labels to their cloned counterparts + */ public static Map cloneLabels(InsnList source) { Map labels = new HashMap(); @@ -747,8 +796,13 @@ public static Map cloneLabels(InsnList source) { } /** - * @param returnType - * @param args + * Generate a bytecode descriptor from the supplied tokens. Each token can + * be a {@link Type}, a {@link Class} or otherwise is converted in-place by + * calling {@link Object#toString toString}. + * + * @param returnType object representing the method return type, can be + * null for void + * @param args objects representing argument types */ public static String generateDescriptor(Object returnType, Object... args) { StringBuilder sb = new StringBuilder().append('('); @@ -761,7 +815,10 @@ public static String generateDescriptor(Object returnType, Object... args) { } /** - * @param arg + * Converts the supplied object to a descriptor component, used by + * {@link #generateDescriptor}. + * + * @param arg object to convert */ private static String toDescriptor(Object arg) { if (arg instanceof String) { @@ -774,18 +831,46 @@ private static String toDescriptor(Object arg) { return arg == null ? "" : arg.toString(); } + /** + * Returns the simple name of an annotation, mainly used for printing + * annotation names in error messages/user-facing strings + * + * @param annotationType annotation + * @return annotation's simple name + */ public static String getSimpleName(Class annotationType) { return annotationType.getSimpleName(); } + /** + * Returns the simple name of an annotation, mainly used for printing + * annotation names in error messages/user-facing strings + * + * @param annotation annotation node + * @return annotation's simple name + */ public static String getSimpleName(AnnotationNode annotation) { return ASMHelper.getSimpleName(annotation.desc); } + /** + * Returns the simple name from an object type descriptor (in L...; format) + * + * @param desc type descriptor + * @return "simple" name + */ public static String getSimpleName(String desc) { - return desc.substring(desc.lastIndexOf('/') + 1).replace(";", ""); + int pos = Math.max(desc.lastIndexOf('/'), 0); + return desc.substring(pos + 1).replace(";", ""); } + /** + * Gets whether the supplied instruction is a constant instruction (eg. + * ICONST_1) + * + * @param insn instruction to check + * @return true if the supplied instruction is a constant + */ public static boolean isConstant(AbstractInsnNode insn) { if (insn == null) { return false; @@ -793,6 +878,14 @@ public static boolean isConstant(AbstractInsnNode insn) { return Ints.contains(ASMHelper.CONSTANTS_ALL, insn.getOpcode()); } + /** + * If the supplied instruction is a constant, returns the constant value + * from the instruction + * + * @param insn constant instruction to process + * @return the constant value or null if the value cannot be parsed + * (or is null) + */ public static Object getConstant(AbstractInsnNode insn) { if (insn == null) { return null; @@ -810,6 +903,13 @@ public static Object getConstant(AbstractInsnNode insn) { return index < 0 ? null : ASMHelper.CONSTANTS_VALUES[index]; } + /** + * Returns the {@link Type} of a particular constant instruction's payload + * + * @param insn constant instruction + * @return type of constant or null if it cannot be parsed (or is + * null) + */ public static Type getConstantType(AbstractInsnNode insn) { if (insn == null) { return null; @@ -838,8 +938,8 @@ public static Type getConstantType(AbstractInsnNode insn) { /** * Check whether the specified flag is set on the specified class * - * @param classNode - * @param flag + * @param classNode class node + * @param flag flag to check * @return True if the specified flag is set in this method's access flags */ public static boolean hasFlag(ClassNode classNode, int flag) { @@ -849,8 +949,8 @@ public static boolean hasFlag(ClassNode classNode, int flag) { /** * Check whether the specified flag is set on the specified method * - * @param method - * @param flag + * @param method method node + * @param flag flag to check * @return True if the specified flag is set in this method's access flags */ public static boolean hasFlag(MethodNode method, int flag) { @@ -860,8 +960,8 @@ public static boolean hasFlag(MethodNode method, int flag) { /** * Check whether the specified flag is set on the specified field * - * @param field - * @param flag + * @param field field node + * @param flag flag to check * @return True if the specified flag is set in this field's access flags */ public static boolean hasFlag(FieldNode field, int flag) { diff --git a/src/main/java/org/spongepowered/asm/util/ClassSignature.java b/src/main/java/org/spongepowered/asm/util/ClassSignature.java index 8abf5a3bd..8afdc819e 100644 --- a/src/main/java/org/spongepowered/asm/util/ClassSignature.java +++ b/src/main/java/org/spongepowered/asm/util/ClassSignature.java @@ -1265,7 +1265,7 @@ public SignatureVisitor getRemapper() { @Override public String toString() { while (this.rawInterfaces.size() > 0) { - this.addRawInterface(this.rawInterfaces.remove()); + this.addRawInterface(this.rawInterfaces.remove()); } StringBuilder sb = new StringBuilder(); diff --git a/src/main/java/org/spongepowered/asm/util/ConstraintParser.java b/src/main/java/org/spongepowered/asm/util/ConstraintParser.java index 4ef7af17d..92363fcc3 100644 --- a/src/main/java/org/spongepowered/asm/util/ConstraintParser.java +++ b/src/main/java/org/spongepowered/asm/util/ConstraintParser.java @@ -72,9 +72,9 @@ public final class ConstraintParser { *
Greater than or equal to 1234 (equivalent to 1234 * >)
*
(1234-1300)
- *
Value must be between
1234 and 1300 (inclusive) + *
Value must be between 1234 and 1300 (inclusive)
*
(1234+10)
- *
Value must be between
1234 and 1234+10 (1234-1244 + *
Value must be between 1234 and 1234+10 (1234-1244 * inclusive)
* * @@ -220,6 +220,13 @@ public int getMax() { return this.max; } + /** + * Checks the current token against the environment and throws a + * {@link ConstraintViolationException} if the constraint is invalid + * + * @param environment environment to fetch constraints + * @throws ConstraintViolationException if constraint is not valid + */ public void check(ITokenProvider environment) throws ConstraintViolationException { if (this != Constraint.NONE) { Integer value = environment.getToken(this.token); @@ -240,6 +247,10 @@ public void check(ITokenProvider environment) throws ConstraintViolationExceptio } } + /** + * Gets a human-readable description of the range expressed by this + * constraint + */ public String getRangeHumanReadable() { if (this.min == Integer.MIN_VALUE && this.max == Integer.MAX_VALUE) { return "ANY VALUE"; @@ -262,6 +273,14 @@ public String toString() { private ConstraintParser() { } + /** + * Parse the supplied expression as a constraint and returns a new + * Constraint. Returns {@link Constraint#NONE} if the constraint could not + * be parsed or is empty. + * + * @param expr constraint expression to parse + * @return parsed constraint + */ public static Constraint parse(String expr) { if (expr == null || expr.length() == 0) { return Constraint.NONE; @@ -281,6 +300,15 @@ public static Constraint parse(String expr) { return head != null ? head : Constraint.NONE; } + /** + * Parse a constraint expression on the supplied annotation as a constraint + * and returns a new Constraint. Returns {@link Constraint#NONE} if the + * constraint could not be parsed or is empty. + * + * @param annotation annotation containing the constraint expression to + * parse + * @return parsed constraint + */ public static Constraint parse(AnnotationNode annotation) { String constraints = ASMHelper.getAnnotationValue(annotation, "constraints", ""); return ConstraintParser.parse(constraints); diff --git a/src/main/java/org/spongepowered/asm/util/JavaVersion.java b/src/main/java/org/spongepowered/asm/util/JavaVersion.java index 342d6dfcc..731e996b5 100644 --- a/src/main/java/org/spongepowered/asm/util/JavaVersion.java +++ b/src/main/java/org/spongepowered/asm/util/JavaVersion.java @@ -36,6 +36,9 @@ public abstract class JavaVersion { private JavaVersion() {} + /** + * Get the current java version, calculates if necessary + */ public static double current() { if (JavaVersion.current == 0.0) { JavaVersion.current = JavaVersion.resolveCurrentVersion(); diff --git a/src/main/java/org/spongepowered/asm/util/Locals.java b/src/main/java/org/spongepowered/asm/util/Locals.java index 81603529c..1fb81cea4 100644 --- a/src/main/java/org/spongepowered/asm/util/Locals.java +++ b/src/main/java/org/spongepowered/asm/util/Locals.java @@ -54,13 +54,17 @@ /** * Utility methods for working with local variables using ASM */ -public class Locals { +public final class Locals { /** * Cached local variable lists, to avoid having to recalculate them * (expensive) if multiple injectors are working with the same method */ private static final Map> calculatedLocalVariables = new HashMap>(); + + private Locals() { + // utility class + } /** * Injects appropriate LOAD opcodes into the supplied InsnList for each @@ -70,6 +74,7 @@ public class Locals { * RETURN values in locals) * @param insns Instruction List to inject into * @param pos Start position + * @param limit maximum number of locals to consume */ public static void loadLocals(Type[] locals, InsnList insns, int pos, int limit) { for (; pos < locals.length && limit > 0; pos++) { diff --git a/src/main/java/org/spongepowered/asm/util/ObfuscationUtil.java b/src/main/java/org/spongepowered/asm/util/ObfuscationUtil.java index 5dc696562..02160f6af 100644 --- a/src/main/java/org/spongepowered/asm/util/ObfuscationUtil.java +++ b/src/main/java/org/spongepowered/asm/util/ObfuscationUtil.java @@ -54,10 +54,24 @@ public interface IClassRemapper { private ObfuscationUtil() {} + /** + * Map a descriptor using the supplied rempper + * + * @param desc descriptor to remap + * @param remapper remapper to use + * @return mapped descriptor + */ public static String mapDescriptor(String desc, IClassRemapper remapper) { return ObfuscationUtil.remapDescriptor(desc, remapper, false); } + /** + * Unmap (inverse of map) a descriptor using the supplied rempper + * + * @param desc descriptor to unmap + * @param remapper remapper to use + * @return unmapped descriptor + */ public static String unmapDescriptor(String desc, IClassRemapper remapper) { return ObfuscationUtil.remapDescriptor(desc, remapper, true); } diff --git a/src/main/java/org/spongepowered/asm/util/PrettyPrinter.java b/src/main/java/org/spongepowered/asm/util/PrettyPrinter.java index a18a08d27..6f95d5447 100644 --- a/src/main/java/org/spongepowered/asm/util/PrettyPrinter.java +++ b/src/main/java/org/spongepowered/asm/util/PrettyPrinter.java @@ -486,7 +486,7 @@ public PrettyPrinter table(String... titles) { * printer.table("Column 1", 30, "Column 2", 20, Alignment.RIGHT); * * - * @param format + * @param format format string, see description * @return fluent interface */ public PrettyPrinter table(Object... format) { diff --git a/src/main/java/org/spongepowered/asm/util/SignaturePrinter.java b/src/main/java/org/spongepowered/asm/util/SignaturePrinter.java index f7c02f193..e417d78d1 100644 --- a/src/main/java/org/spongepowered/asm/util/SignaturePrinter.java +++ b/src/main/java/org/spongepowered/asm/util/SignaturePrinter.java @@ -123,14 +123,25 @@ public SignaturePrinter(String name, Type returnType, Type[] argTypes, String[] } } + /** + * Return only the arguments portion of this signature as a Java-style block + */ public String getFormattedArgs() { return this.appendArgs(new StringBuilder(), true).toString(); } + /** + * Get string representation of this signature's return type + */ public String getReturnType() { return SignaturePrinter.getTypeName(this.returnType, false, this.fullyQualified); } + /** + * Set modifiers on this signature using the supplied method node + * + * @param method method node to read modifiers from + */ public void setModifiers(MethodNode method) { String returnType = SignaturePrinter.getTypeName(Type.getReturnType(method.desc), false, this.fullyQualified); if ((method.access & Opcodes.ACC_PUBLIC) != 0) { @@ -144,25 +155,50 @@ public void setModifiers(MethodNode method) { } } + /** + * Set modifiers on this signature explicitly. Use the special token + * ${returnType} to insert the return type into the modifier + * string. + * + * @param modifiers modifiers to prepend + * @return fluent interface + */ public SignaturePrinter setModifiers(String modifiers) { this.modifiers = modifiers.replace("${returnType}", this.getReturnType()); return this; } + /** + * Set whether this signature generates fully-qualified class output, mainly + * used when generating signatures for Mirror + * + * @param fullyQualified new value for fully-qualified + * @return fluent interface + */ public SignaturePrinter setFullyQualified(boolean fullyQualified) { this.fullyQualified = fullyQualified; return this; } + /** + * Get whether this printer will fully-qualify class names in generated + * signatures + */ public boolean isFullyQualified() { return this.fullyQualified; } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ @Override public String toString() { return this.appendArgs(new StringBuilder().append(this.modifiers).append(" ").append(this.name), false).toString(); } + /** + * Return this signature in descriptor format (return type after args) + */ public String toDescriptor() { StringBuilder args = this.appendArgs(new StringBuilder(), true); return args.append(SignaturePrinter.getTypeName(this.returnType, false, this.fullyQualified)).toString(); diff --git a/src/main/java/org/spongepowered/asm/util/VersionNumber.java b/src/main/java/org/spongepowered/asm/util/VersionNumber.java index 50625e936..fa4c37c72 100644 --- a/src/main/java/org/spongepowered/asm/util/VersionNumber.java +++ b/src/main/java/org/spongepowered/asm/util/VersionNumber.java @@ -33,7 +33,7 @@ * format as a sequence of four shorts packed into a long. This is to * facilitate meaningful comparison between version numbers. */ -public class VersionNumber implements Comparable, Serializable { +public final class VersionNumber implements Comparable, Serializable { private static final long serialVersionUID = 1L; @@ -46,7 +46,7 @@ public class VersionNumber implements Comparable, Serializable { /** * Regex for matching a version number specified as a string */ - private static final Pattern versionNumberPattern = + private static final Pattern PATTERN = Pattern.compile("^(\\d{1,5})(?:\\.(\\d{1,5})(?:\\.(\\d{1,5})(?:\\.(\\d{1,5}))?)?)?(-[a-zA-Z0-9_\\-]+)?$"); /** @@ -190,7 +190,7 @@ private static VersionNumber parse(String version, VersionNumber defaultVersion) return defaultVersion; } - Matcher versionNumberPatternMatcher = VersionNumber.versionNumberPattern.matcher(version); + Matcher versionNumberPatternMatcher = VersionNumber.PATTERN.matcher(version); if (!versionNumberPatternMatcher.matches()) { return defaultVersion; } diff --git a/src/main/java/org/spongepowered/asm/util/launchwrapper/LaunchClassLoaderUtil.java b/src/main/java/org/spongepowered/asm/util/launchwrapper/LaunchClassLoaderUtil.java index 8e916132a..50d845f07 100644 --- a/src/main/java/org/spongepowered/asm/util/launchwrapper/LaunchClassLoaderUtil.java +++ b/src/main/java/org/spongepowered/asm/util/launchwrapper/LaunchClassLoaderUtil.java @@ -153,6 +153,9 @@ public void registerInvalidClass(String name) { } } + /** + * Get the classloader exclusions from the target classloader + */ public Set getClassLoaderExceptions() { if (this.classLoaderExceptions != null) { return this.classLoaderExceptions; @@ -160,6 +163,9 @@ public Set getClassLoaderExceptions() { return Collections.emptySet(); } + /** + * Get the transformer exclusions from the target classloader + */ public Set getTransformerExceptions() { if (this.transformerExceptions != null) { return this.transformerExceptions; diff --git a/src/main/java/org/spongepowered/asm/util/throwables/LVTGeneratorException.java b/src/main/java/org/spongepowered/asm/util/throwables/LVTGeneratorException.java index 012bac110..066464492 100644 --- a/src/main/java/org/spongepowered/asm/util/throwables/LVTGeneratorException.java +++ b/src/main/java/org/spongepowered/asm/util/throwables/LVTGeneratorException.java @@ -27,8 +27,8 @@ import org.spongepowered.asm.mixin.throwables.MixinException; /** - * Exception thrown when something goes horribly wrong whilst summoning the - * antichrist generating the LVT for a target method. + * Exception thrown when something goes horribly wrong whilst summoning the + * antichrist generating the LVT for a target method. */ public class LVTGeneratorException extends MixinException {