Package org.stianloader.sll.transform

# Interface CodeTransformer

All Known Implementing Classes:
  `SLLCTMixinTransformer`

@Experimental @AvailableSince("4.0.0-a20241012") public interface CodeTransformer
An experimental extension to the current ASM `ClassNode` transformation API of SLL. That is, this interface is implemented alongside `ASMTransformer`, which results in `transformClass(ClassNode, URI)` to be called instead of `ASMTransformer.accept(ClassNode)`.

As of now, this API is currently mainly intended for internal use within the micromixin variant of SLL and may require more throughout vetting for other usecases, which is why usage of it is not recommended even if it is intended to replace the current bytecode transformation API in SLL which has existed in it's current state since SLL 2.1.0. As such, ABI (Application binary interface) breaks for this interface may occur in future versions even though breaks are atypical for SLL.

Since:
  4.0.0-a20241012

- ## Method Summary

  Modifier and Type
  Method
  Description
  `default boolean`
  `isValidTarget(@NotNull String internalName, @Nullable URI codeSourceURI)`
  Obtains whether this `CodeTransformer` instance is interested in transforming the given class.
  `boolean`
  `transformClass(@NotNull org.objectweb.asm.tree.ClassNode node, @Nullable URI codeSourceURI)`
  Optionally transforms a class, returning `true` if the input `node` was modified, `false` otherwise.

- ## Method Details

  - ### isValidTarget

    @Experimental @AvailableSince("4.0.0-a20250819") default boolean isValidTarget(@NotNull @NotNull String internalName, @Nullable @Nullable URI codeSourceURI)
    Obtains whether this `CodeTransformer` instance is interested in transforming the given class. Returns `true` if the class with the given internal name is of interest to this transformer, `false` otherwise.

    The caller of this method must not call `transformClass(ClassNode, URI)` for classes with the same name as the one used in a call to this method if that call returned `false`. This is a performance-saving measure and is very much akin to `ASMTransformer.isValidTarget(String)`, except that is also exposes the codeSourceURI of the class.

    If no transformers mark a class as a valid target, then the bytecode of the class does not need to be transformed into a ClassNode, saving some CPU cycles (meaning faster startup times).

    The code source property ought not be confused with the `ClassNode.sourceFile` property of a class. Instead it corresponds to `CodeSource.getLocation()`, hinting at the location of the compiled bytecode.

    Parameters:
      `internalName` - The internal name of the class, as per `Type.getInternalName()`.
      `codeSourceURI` - A URI representing the location of the class source code. This URI will correspond to the JAR in which the class is located in, or the "base" directory of the class as per the classpath. This argument may be `null` if the caller does not know (or rather - cannot determine) the location of the class bytecode.
    Returns:
      True if the target is to be transformed, false otherwise.
    Since:
      4.0.0-a20250819
    See Also:
      - `CodeSource`
    Implementation Specification:
      By default, if the class implementing this interface also extends `ASMTransformer`, then `ASMTransformer.isValidTarget(String)` will be called, otherwise `true` will be returned.

  - ### transformClass

    @Experimental @AvailableSince("4.0.0-a20241012") boolean transformClass(@NotNull @NotNull org.objectweb.asm.tree.ClassNode node, @Nullable @Nullable URI codeSourceURI)
    Optionally transforms a class, returning `true` if the input `node` was modified, `false` otherwise.

    If the node was transformed while this method returned `false`, the applied transformations may get discarded, or may also not get discarded. The exact behaviour will likely depend on the behaviour of other classes. Please be aware that debugging such edge case behaviour is extremely difficult as the cause and effects will likely seem to be completely disconnected to the average programmer, and will further not be reproducible in every environment. The return flag mainly exists for performance reasons as converting `ClassNode` into `byte[]` isn't exactly free.

    The transformation occurs in-situ, meaning that the input `ClassNode` is transformed as-is without any cloning. Thus the input node is also the output node in some sense.

    Parameters:
      `node` - The input and output `ClassNode` to transform.
      `codeSourceURI` - The `URI` where this class is located in, following the paradigms of `CodeSource.getLocation()`. For classes located inside JARs, the URI of the jar will be used. For classes within directories, the URI of the directory is used (i.e. `file://bin/` for `file://bin/com/example/Main.class`). If the location of the class file is unknown or cannot be represented as an `URI`, `null` should be used.
    Returns:
      `true` if the input node was transformed, `false` otherwise.
    Since:
      4.0.0-a20241012