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

Duplicate cursor while working with Java visitors #3641

Closed
BoykoAlex opened this issue Oct 23, 2023 · 5 comments · Fixed by #3642
Closed

Duplicate cursor while working with Java visitors #3641

BoykoAlex opened this issue Oct 23, 2023 · 5 comments · Fixed by #3642
Assignees
Labels
bug Something isn't working

Comments

@BoykoAlex
Copy link
Contributor

The change in TreeVisitor:

            setCursor(cursor.getParent());

            if (topLevel) {
                sample.stop(Timer.builder("rewrite.visitor.visit").tag("visitor.class", getClass().getName()).register(Metrics.globalRegistry));
                visitCountSummary.record(visitCount);

                if (t != null && afterVisit != null) {
                    for (TreeVisitor<?, P> v : afterVisit) {
                        if (v != null) {
                             v.setCursor(new Cursor(cursor, tree)); // <---- This change
                            //noinspection unchecked
                            t = (T) v.visit(t, p);
                        }
                    }
                }

                sample.stop(Timer.builder("rewrite.visitor.visit.cumulative").tag("visitor.class", getClass().getName()).register(Metrics.globalRegistry));
                afterVisit = null;
                visitCount = 0;
            }

seems problematic and may lead to the creation of two cursors (child and parent) pointing to the same AST node.
The following call t = (T) v.visit(t, p); would create another cursor with the same tree element it seems:

    @Nullable
    public T visit(@Nullable Tree tree, P p) {
        if (tree == null) {
            return defaultValue(null, p);
        }

        Timer.Sample sample = null;
        boolean topLevel = false;
        if (visitCount == 0) {
            topLevel = true;
            sample = Timer.start();
        }

        visitCount++;
        setCursor(new Cursor(cursor, tree));

Having a duplicate cursor leads to problems with indents in the auto formatting visitor.

@BoykoAlex BoykoAlex added the bug Something isn't working label Oct 23, 2023
@BoykoAlex
Copy link
Contributor Author

BoykoAlex commented Oct 23, 2023

I propose to switch the cursor creation call:

from

v.setCursor(new Cursor(cursor, tree));

to

v.setCursor(cursor == null ? null : cursor.fork());

@knutwannheden
Copy link
Contributor

@BoykoAlex Thanks for reporting. This seems to be about commit 3086e52. It indeed looks like the after visitor's cursor will end up with a parent with the same value.

@sambsnyd If I understand your commit correctly, you made a change to fix TreeVisitorTest#scheduleAfterOnVisitWithCursor(). But I think that what that test is doing is somewhat dangerous: Its visitor overrides visit(Tree, P). This is of course possible, but that method (in TreeVisitor) is the one which contains all the "important" bits about setting up the cursor etc. So I think a visitor doing that can't expect the cursor to point to the element being visited. In that way I think this test is wrong. What are your thoughts on this?

@knutwannheden
Copy link
Contributor

@BoykoAlex Rather than calling Cursor#fork() I would like to propose to switch back to using the original cursor, as we had it before. I will update your PR accordingly.

@knutwannheden
Copy link
Contributor

knutwannheden commented Oct 27, 2023

Using Cursor#fork(), as you propose, could also make sense in a second step to avoid any "pollution" between visitors.

@knutwannheden knutwannheden linked a pull request Oct 27, 2023 that will close this issue
@timtebeek timtebeek moved this to In Progress in OpenRewrite Oct 27, 2023
@timtebeek timtebeek moved this from In Progress to Ready to Review in OpenRewrite Oct 27, 2023
@BoykoAlex
Copy link
Contributor Author

@knutwannheden reverting the commit or switching to fork() either should fix the issue for me. thanks very much for looking into this!-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

2 participants