TransformationManager

The transformation manager allows registering of different transformer types for class processing operations.

Example Transformer

public class MyTransformer implements JvmClassTransformer {
    /** Optional, can delete if you do not need any one-time setup logic */
    @Override
    public void setup(@Nonnull JvmTransformerContext context, @Nonnull Workspace workspace) {
        // Transformation setup here
        //  - Pulling values from the context
        //  - Checking contents of the workspace
        //  - Etc.
    }

    /** Used to transform the classes */
    @Override
    public void transform(@Nonnull JvmTransformerContext context, @Nonnull Workspace workspace,
                          @Nonnull WorkspaceResource resource, @Nonnull JvmClassBundle bundle,
                          @Nonnull JvmClassInfo classInfo) throws TransformationException {
        if (exampleOfRawEdit) {
            // IMPORTANT: Use this method to get the bytecode, and DO NOT use the direct 'classInfo.getBytecode()'!
            // The context will store updated bytecode across multiple transformations, so if you use the direct
            // bytecode from the 'ClassInfo' you risk losing all previous transform operations.
            byte[] modifiedBytecode = context.getBytecode(bundle, classInfo);
            
            // TODO: Make changes to 'modifiedBytecode'
            
            // Save modified bytecode into the context
            context.setBytecode(bundle, classInfo, modifiedBytecode);
        } else if (exampleOfAsmTreeEdit) {
            // IMPORTANT: The same note as above applies here, but with ASM's ClassNode.
            ClassNode node = context.getNode(bundle, classInfo);
            
            // TODO: Make changes to 'node'
            
             // Save modified class-node (and its respective bytecode) into the context
            context.setNode(bundle, classInfo, node);
        }
    }

    /** Unique name of this transformer */
    @Nonnull
    @Override
    public String name() {
        return "My cool transformer";
    }

    /** Any dependencies this transformer relies on. Some transformers are used for analysis and store data
     *  that can be accessed later, and depending on those transformers ensures the data is accessible when
     *  this transformer is invoked. */
    @Nonnull
    @Override
    public Set<Class<? extends JvmClassTransformer>> dependencies() {
        // Optional method, you can delete this if you have no dependencies.
        // But if you do use dependencies, you can get instances of them via 'context.getJvmTransformer(OtherTransformer.class)'
        // in the 'setup' and 'transform' methods above.
        return Collections.emptySet();
    }
}

Registering transformers

// Registering and unregistering
processingService.registerJvmClassTransformer(MyTransformer.class, () -> new MyTransformer());
processingService.unregisterJvmClassTransformer(MyTransformer.class);