Skip to content

Recurse into special constructs to find document symbols #892

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

Merged
merged 4 commits into from
Aug 22, 2025

Conversation

lionel-
Copy link
Contributor

@lionel- lionel- commented Aug 8, 2025

Addresses posit-dev/positron#8881

We now consistently recurse inside these constructs to collect nested document symbols such as comment sections:

  • if-else branches
  • loops

The behaviour regarding nested assignments implemented in #859 has been adapted so that { blocks in if-else branches and loops still counts as top-level. This way these assignments are all treated as consistently part of the outline:

x <- 1

if (TRUE) {
  x <- 2
} else {
  x <- 3
}

for (i in xs) {
  x <- 4
}

In addition we also now collect comment sections in parameter lists of function definitions:

x <- function(
  # section ----
  arg
) {
  ...
}

QA Notes

Comment sections and other kinds of document symbols in if-else branches and loops are now part of the outline:

# top ----

if (TRUE) {
  # if ----
  foo <- function() {}
} else {
  # else ----
  foo <- function() {}
}

for (i in xs) {
  # loop ----
  bar <- function() {}
}

Comment sections in parameter lists of function definitions are now included as well. We don't recurse through default arguments though.

x <- function(
  # section ----
  arg = function() {
    # not a section ----
  }
) {
  ...
}
Screenshot 2025-08-08 at 13 54 15

@lionel- lionel- requested a review from DavisVaughan August 8, 2025 17:56
Copy link
Contributor

@DavisVaughan DavisVaughan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few questions requesting clarifying behavior and a few more tests but I think this looks fairly straightforward?

Comment on lines 197 to 198
NodeType::BracedExpression => {
let old = ctx.top_level;
ctx.top_level = false;
collect_list_sections(ctx, node, contents, current_level, symbols)?;
ctx.top_level = old;
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this change the behavior of general braced expressions? i.e.

# a section ----

{
  # another one ----
}

And do we have tests for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! We tested the brace-in-call and brace-in-function cases, but not the brace-in-program case.

I've tweaked a snapshot to include these (as well as the brace-in-brace case) and regenerated before all changes in this PR, then reran the tests with all the changes (including removed current_level), and there were no snapshot changes.

Comment on lines 564 to 549
// Only collect sections
return Ok(());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what this comment means. Does it mean no recursion? Can you provide more details?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep no recursion, the comment is now clearer about that

ctx,
&node,
contents,
0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmmmmm 0? Are you sure you shouldn't pass the current_level through to here? You do for the function body. Add a test either way about this behavior?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or at least a comment here about why its 0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant 0 here, but I think you're right to be confused. With the changes made over time, we no longer propagate the current level across syntax constructs. So I've just removed this argument.

@lionel- lionel- force-pushed the bugfix/outline-cflow branch from 5d654e0 to ce3fb52 Compare August 22, 2025 09:01
@lionel- lionel- merged commit 04b6bd2 into main Aug 22, 2025
6 checks passed
@lionel- lionel- deleted the bugfix/outline-cflow branch August 22, 2025 09:09
@github-actions github-actions bot locked and limited conversation to collaborators Aug 22, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants