All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jfxcore.compiler.transform.TransformContext Maven / Gradle / Ivy

// Copyright (c) 2021, JFXcore. All rights reserved.
// Use of this source code is governed by the BSD-3-Clause license that can be found in the LICENSE file.

package org.jfxcore.compiler.transform;

import javassist.ClassPool;
import javassist.CtClass;
import org.jetbrains.annotations.Nullable;
import org.jfxcore.compiler.ast.DocumentNode;
import org.jfxcore.compiler.ast.Node;
import org.jfxcore.compiler.ast.TemplateContentNode;
import org.jfxcore.compiler.ast.Visitor;
import org.jfxcore.compiler.util.ArrayStack;
import org.jfxcore.compiler.util.CompilationContext;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.ListIterator;
import java.util.function.Predicate;

public class TransformContext {

    private final ArrayStack parents = new ArrayStack<>();
    private final List ids = new ArrayList<>();
    private final CtClass markupClass;
    private final CtClass bindingContextClass;

    public TransformContext(
            List imports,
            ClassPool classPool,
            @Nullable CtClass codeBehindClass,
            @Nullable CtClass markupClass) {
        CompilationContext context = CompilationContext.getCurrent();
        context.setClassPool(classPool);
        context.setImports(imports);

        if (codeBehindClass != null && markupClass != null) {
            this.markupClass = markupClass;
            this.bindingContextClass = codeBehindClass;
        } else if (markupClass != null) {
            this.markupClass = this.bindingContextClass = markupClass;
        } else {
            this.markupClass = null;
            this.bindingContextClass = null;
        }
    }

    public List getIds() {
        return ids;
    }

    public CtClass getMarkupClass() {
        return markupClass;
    }

    public @Nullable CtClass getBindingContextClass() {
        ListIterator it = parents.listIterator(parents.size());

        while (it.hasPrevious()) {
            Node node = it.previous();

            if (node instanceof TemplateContentNode templateContentNode) {
                return templateContentNode.getBindingContextClass().jvmType();
            }
        }

        return bindingContextClass;
    }

    public boolean isTemplate() {
        ListIterator it = parents.listIterator(parents.size());

        while (it.hasPrevious()) {
            Node node = it.previous();

            if (node instanceof TemplateContentNode) {
                return true;
            }
        }

        return false;
    }

    public void push(Node node) {
        parents.push(node);
    }

    public void pop() {
        parents.pop();
    }

    public List getParents() {
        return parents;
    }

    public Node getParent() {
        return parents.peek();
    }

    public Node getParent(int index) {
        if (index >= parents.size()) {
            return null;
        }

        return parents.get(parents.size() - index - 1);
    }

    public Node getParent(Node node) {
        if (parents.isEmpty()) {
            throw new RuntimeException("Specified node has no parent.");
        }

        Node root = parents.get(0);
        Node[] parent = new Node[1];

        Visitor.visit(root, new Visitor() {
            final Deque stack = new ArrayDeque<>();

            @Override
            public Node onVisited(Node n) {
                if (node == n) {
                    parent[0] = stack.peek();
                    return Visitor.STOP;
                }

                return n;
            }

            @Override
            public void push(Node node) {
                stack.push(node);
            }

            @Override
            public void pop() {
                stack.pop();
            }
        });

        return parent[0];
    }

    @SuppressWarnings("unchecked")
    public  T getParent(Class nodeClass) {
        Node parent = getParent();
        if (nodeClass.isInstance(parent)) {
            return (T)parent;
        }

        return null;
    }

    public DocumentNode getDocument() {
        return findParent(DocumentNode.class);
    }

    public  T findParent(Class type) {
        T parent = tryFindParent(type);
        if (parent == null) {
            throw new RuntimeException("Parent not found: " + type.getName());
        }

        return parent;
    }

    public  T tryFindParent(Class type) {
        return tryFindParent(type, null);
    }

    @SuppressWarnings("unchecked")
    public  T tryFindParent(Class type, @Nullable Predicate predicate) {
        for (int i = parents.size() - 1; i >= 0; --i) {
            if (type.isInstance(parents.get(i))
                    && (predicate == null || predicate.test((T)parents.get(i)))) {
                return (T)parents.get(i);
            }
        }

        return null;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy