Classpath features

    Features are used for building representations based on JcClasspath bytecode. One should pass the features when creating a classpath.

    JcClasspath cp = db.asyncClasspath(files,
        Arrays.asList(new AppendMainMethodToAllClasses())
    ).get();

    JcClasspathFeature

    This class is a base class for all the features. It has two methods:

    • on(event) lets one receive events from the other features;
    • event(result, input) produces events for the other features.

    The basic scenario is caching: when an extension gets information on a code structure, this information can be cached for further usage.

    JcClasspathExtFeature

    Can be used for mocking or caching:

    • tryFindClass(classpath, name): Optional<JcClassOrInterface>?
    • tryFindType(classpath, name): Optional<JcType>?

    Returned values should conform to this logic:

    • not empty Optional for the found class or type;
    • empty Optional for a class or type that does not exist in the classpath;
    • null when we do not know if a class or type exists or not.

    JcClassExtFeature

    Can be used for patching classes with new fields or methods:

    • fieldsOf(clazz) returns a list of additional fields for a particular class; null by default.
    • methodsOf(clazz) returns a list of additional methods for a particular class. null by default.
    • extensionValuesOf(clazz) returns a map of additional information for a particular class.

    extensionValuesOf can expose specific information about the classes, for example, from Kotlin or Scala compilers.

    JcInstExtFeature

    • transformRawInstList(method: JcMethod, list) transforms a raw instruction list.
    • transformInstList(method, list) transforms an instruction list — raw instructions remain the same.

    UnknownClass

    Can be used to gracefully handle situation that some classes are nor preserved in classpath. i.e.

    class Bar {
    
        int x = 0;
    
        public void run() {
           System.out.println("Hello world");
        }
    }
    
    class Foo extends Bar {
    
        Bar f = new Bar();
    
        public void call() {
           System.out.println(f.x);
           run();
        }
    }

    Let's assume that we have classpath that contains class Foo and doesn't contain Bar. Default behavior for classpath is to fail on trying to access class that doesn't exist. i.e parsing method instructions will fail, reading class hierarchy will fail, resolving method will fail.

    UnknownClasses feature fix this behaviour. All references pointing to nowhere will be resolved as special implementation of JcClassOrInterface instance. Such instance will have empty JcClassOrInterface.declaredFields and JcClassOrInterface.declaredMethods but all resolutions done through JcClassOrInterface.lookup interface will return mocked instances.

    [//] # (## JcMethodExtFeature)