Repository: openrewrite/rewrite (Java)

Issue:
Duplicate cursor while working with Java visitors
The change in `TreeVisitor`:

```java
            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:

```java
    @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.


Discussion: I propose to switch the cursor creation call:

from

```java
v.setCursor(new Cursor(cursor, tree));
```

to

```java
v.setCursor(cursor == null ? null : cursor.fork());
```




Fix (patch):
diff --git a/rewrite-core/src/main/java/org/openrewrite/TreeVisitor.java b/rewrite-core/src/main/java/org/openrewrite/TreeVisitor.java
index a3b441ab0a..73d6d853a4 100644
--- a/rewrite-core/src/main/java/org/openrewrite/TreeVisitor.java
+++ b/rewrite-core/src/main/java/org/openrewrite/TreeVisitor.java
@@ -309,7 +309,7 @@ public T visit(@Nullable Tree tree, P p) {
                 if (t != null && afterVisit != null) {
                     for (TreeVisitor<?, P> v : afterVisit) {
                         if (v != null) {
-                             v.setCursor(new Cursor(cursor, tree));
+                             v.setCursor(getCursor());
                             //noinspection unchecked
                             t = (T) v.visit(t, p);
                         }
diff --git a/rewrite-java/src/main/java/org/openrewrite/java/ChangeType.java b/rewrite-java/src/main/java/org/openrewrite/java/ChangeType.java
index 5524872971..d9f068c5eb 100644
--- a/rewrite-java/src/main/java/org/openrewrite/java/ChangeType.java
+++ b/rewrite-java/src/main/java/org/openrewrite/java/ChangeType.java
@@ -181,9 +181,9 @@ private void addImport(JavaType.FullyQualified owningClass) {
                         if (maybeType instanceof JavaType.FullyQualified) {
                             JavaType.FullyQualified type = (JavaType.FullyQualified) maybeType;
                             if (originalType.getFullyQualifiedName().equals(type.getFullyQualifiedName())) {
-                                sf = (JavaSourceFile) new RemoveImport<ExecutionContext>(originalType.getFullyQualifiedName()).visit(sf, ctx, getCursor());
+                                sf = (JavaSourceFile) new RemoveImport<ExecutionContext>(originalType.getFullyQualifiedName()).visit(sf, ctx, getCursor().getParentOrThrow());
                             } else if (originalType.getOwningClass() != null && originalType.getOwningClass().getFullyQualifiedName().equals(type.getFullyQualifiedName())) {
-                                sf = (JavaSourceFile) new RemoveImport<ExecutionContext>(originalType.getOwningClass().getFullyQualifiedName()).visit(sf, ctx, getCursor());
+                                sf = (JavaSourceFile) new RemoveImport<ExecutionContext>(originalType.getOwningClass().getFullyQualifiedName()).visit(sf, ctx, getCursor().getParentOrThrow());
                             }
                         }
                     }