Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CtElement.clone() breaks local variable references #749

Closed
fedorov-s-n opened this issue Jul 13, 2016 · 1 comment
Closed

CtElement.clone() breaks local variable references #749

fedorov-s-n opened this issue Jul 13, 2016 · 1 comment

Comments

@fedorov-s-n
Copy link
Contributor

Suppose you want to clone CtMethod m1 to get CtMethod m2. clone() does it well, but all local variable references from m2 refer to variable declarations from m1. Is it convenient to fix that in clone() method implementation?

Code that sets reference declarations to correct variables:

public <T extends CtElement> T repairLocals(T element) {
    class Scope {

        private final Scope parent;
        private ArrayList<CtVariable> variables;

        public Scope(Scope parent) {
            this.parent = parent;
        }

        public void add(CtVariable var) {
            if (variables == null) {
                variables = new ArrayList<>(1);
            }
            variables.add(var);
        }

        public CtVariable get(String name) {
            if (variables != null) {
                for (CtVariable var : variables) {
                    if (name.equals(var.getSimpleName())) {
                        return var;
                    }
                }
            }
            return parent == null ? null : parent.get(name);
        }
    }
    CtScanner scanner = new CtScanner() {

        private final Stack<Scope> scopes;

        {
            scopes = new Stack<>();
            scopes.add(new Scope(null));
        }

        @Override
        protected void enter(CtElement e) {
            scopes.push(new Scope(scopes.peek()));
        }

        @Override
        protected void exit(CtElement e) {
            scopes.pop();
        }

        @Override
        public <T> void visitCtCatchVariable(CtCatchVariable<T> catchVariable) {
            super.visitCtCatchVariable(catchVariable);
            scopes.peek().add(catchVariable);
        }

        @Override
        public <T> void visitCtCatchVariableReference(CtCatchVariableReference<T> reference) {
            super.visitCtCatchVariableReference(reference);
            CtVariable var = scopes.peek().get(reference.getSimpleName());
            if (var != null) {
                reference.setDeclaration((CtCatchVariable<T>) var);
            }
        }

        @Override
        public <T> void visitCtLocalVariable(CtLocalVariable<T> localVariable) {
            super.visitCtLocalVariable(localVariable);
            scopes.peek().add(localVariable);
        }

        @Override
        public <T> void visitCtLocalVariableReference(CtLocalVariableReference<T> reference) {
            super.visitCtLocalVariableReference(reference);
            CtVariable var = scopes.peek().get(reference.getSimpleName());
            if (var != null) {
                reference.setDeclaration((CtLocalVariable<T>) var);
            }
        }
    };
    element.accept(scanner);
    return element;
}
@GerardPaligot
Copy link
Contributor

GerardPaligot commented Jul 25, 2016

I close this issue and add a reference for the second issue (#756).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants