Как конвертировать ClassVisitor в ClassNode в ASM Java - PullRequest
1 голос
/ 22 октября 2019

Я хочу работать с ASM Core и Tree API одновременно. В настоящее время система использует определенное количество ClassVisitor, связанных вместе для анализа файла класса. Теперь в конце этой цепочки я хочу добавить еще один Transformer, который работает на ClassNode. Можно ли преобразовать ClassVisitor в ClassNode.

...
_cv = new FirstCV(_cv);
_cv = new SecondCV(_cv);
...
_cv = new ClassNodeTransformer((ClassNode) _cv); // Not sure how to achieve this step.

1 Ответ

0 голосов
/ 23 октября 2019

A ClassVisitor представляет этап обработки, тогда как ClassNode представляет конкретное состояние класса. Чтобы интегрировать операцию, работающую с ClassNode, вам нужен посетитель, который создает дерево при посещении класса и начинает посещать обработанный результат в конце.

public abstract class IntegrateNodeTransformer extends ClassVisitor {
    ClassVisitor target;

    public IntegrateNodeTransformer(int api, ClassVisitor target) {
        super(api, null);
        this.target = target;
    }

    /**
     * Initiate the building of a tree when the visit of a class starts.
     */
    @Override
    public void visit(int version, int access, String name, String signature,
                      String superName, String[] interfaces) {
        super.cv = new ClassNode();
        super.visit(version, access, name, signature, superName, interfaces);
    }

    /**
     * On completion of visiting the source class, process the tree and initiate
     * visiting of the result by the target visitor, if there is one.
     */
    @Override
    public void visitEnd() {
        super.visitEnd();
        ClassNode source = (ClassNode)super.cv;
        ClassNode result = process(source);
        if(target != null) result.accept(target);
    }

    /**
     * Do the actual work with the Tree API.
     * May manipulate {@code source} directly and return it or return an entirely new tree.
     */
    protected abstract ClassNode process(ClassNode source);
}

Если у вас есть только один шаг обработкииспользуя Tree API, вы можете рассмотреть возможность его непосредственного выполнения без преобразования в ClassVisitor:

ClassReader cr = new ClassReader(…);
// steps before using the tree API

// mind that composed visitor process in the opposite order of their construction
ClassNode cn = new ClassNode();
ClassVisitor cv = new SomeClassVisitor(cn); // 3rd step
cv = new AnotherClassVisitor(cv);           // 2nd step
cv = new YetAnotherClassVisitor(cv);        // 1st step

cr.accept(cv, 0); // perform steps 1 to 3 and build result tree

cn = process(cn); // the Tree API based operation (4th step)

// steps after using the tree API
ClassWriter cw = new ClassWriter(cr, 0);    // last generate class
cv = new YourLastClassVisitor(cw);          // 7th step
cv = new InCaseYouHaveMoreClassVisitor(cv); // 6th step
cv = new YouKnowWhatIMean(cv);              // 5th step

cn.accept(cv); // perform steps 5 to 7 on tree input and generate class
final byte[] code = cw.toByteArray();
...