-
Notifications
You must be signed in to change notification settings - Fork 17
Emit R6Class methods as workspace symbols #861
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
base: main
Are you sure you want to change the base?
Conversation
@@ -267,6 +267,7 @@ fn completions_from_workspace_arguments( | |||
return Ok(None); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#
prefix in command palette
One of the best settings I've tweaked is
"search.quickOpen.includeSymbols": true
So that a simple Cmd + P
brings up a search bar that merges both file names and workspace symbols
@@ -267,6 +267,7 @@ fn completions_from_workspace_arguments( | |||
return Ok(None); | |||
}, | |||
indexer::IndexEntryData::Variable { .. } => return Ok(None), | |||
indexer::IndexEntryData::Method { .. } => return Ok(None), | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be worth trying to give these a unique name? Like, trying to sniff out the R6 class name to include as well?
Imagine if I implemented two of three of these similar interfaces in the same file, then I'd have no way of telling them apart
What does Rust do for something like this?
https://github.com/DavisVaughan/almanac/blob/main/R/cache-rrule.R
https://github.com/DavisVaughan/almanac/blob/main/R/cache-radjusted.R

for m in self.cursor.matches(&self.query, node, contents) { | ||
for cap in m.captures.iter() { | ||
let cap_name = &self.query.capture_names()[cap.index as usize]; | ||
if *cap_name == capture_name { | ||
result.push(cap.node); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want cursor.matches()
or the flat cursor.captures()
?
If I remember right, captures()
is a flat list, but matches()
has some structure that it doesn't look like you use
if crate::treesitter::node_is_call(&rhs, "R6Class", contents) || | ||
crate::treesitter::node_is_namespaced_call(&rhs, "R6", "R6Class", contents) | ||
{ | ||
index_r6_class(path, contents, &rhs, entries)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should probably early return after this right? If not, maybe a comment about why fallthrough is good?
let start = convert_point_to_position(contents, lhs.start_position()); | ||
let end = convert_point_to_position(contents, lhs.end_position()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just checking, do you use lhs.start_position()
or node.start_position()
?
Same question below in the // Otherwise, emit variable
path
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh i see this in the test, maybe a comment here too?
// Note that unlike document symbols whose ranges cover the whole entity
// they represent, the range of workspace symbols only cover the identifers
// Tree-sitter query to match individual methods in R6Class public/private lists | ||
let query_str = r#" | ||
(argument | ||
name: (identifier) @access | ||
value: (call | ||
function: (identifier) @_list_fn | ||
arguments: (arguments | ||
(argument | ||
name: (identifier) @method_name | ||
value: (function_definition) @method_fn | ||
) | ||
) | ||
) | ||
(#match? @access "public|private") | ||
(#eq? @_list_fn "list") | ||
) | ||
"#; | ||
let mut ts_query = crate::treesitter::TSQuery::new(query_str)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing I will note is that tree-sitter recommends that you "compile" your static Query
objects exactly once ahead of time, because they do take a non zero amount of overhead to parse and compile.
Would it be possible to rearrange things to end up with a Lazy<Query>
that is initialized once and then fed to your TSQuery
helper?
// We'll switch from Rope to String in the near future so let's not | ||
// worry about this conversion now | ||
let contents_str = contents.to_string(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, should be nicer all around
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you wanted to be super fancy I believe you could implement TextProvider
for Rope
It's probably not worth it but i think the idea is that you can somehow provide some iterator when you don't have a complete contiguous buffer available
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually it might be easier than that? It looks like they already provide an implementation of TextProvider
for FnMut(Node) -> <iterator over bytes>
So you could probably provide something like
mut |node: Node| {
iter::once(contents.node_slice(&node).unwrap().to_string().as_bytes())
}
which would materialize a node
worth of text in to_string()
but not the whole document
It's not allowed to fail so I guess you have to unwrap()
May or may not be worth it, just a thought
private = list( | ||
private_method = function() { | ||
1 | ||
} | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also include a private variable to ensure it isn't indexed?
Addresses posit-dev/positron#6549
Add a bunch of tests for the workspace indexers which were not tested before.
Add a new indexed type
Method
. This is used to include R6Class methods in workspace symbols but exclusing them from completions.Indexers now push symbols onto a list instead of returning a single symbol to their callers. This allows a single indexer to handle multiple symbols.
The assignment handler now pushes R6Class method symbols in addition to the assigned object.
QA Notes
Add the following to a file:
These symbols should now be available as Workspace symbols (
#
prefix in command palette):initialize()
,foo()
,bar()
and you should be able to jump straight to the definition of these methods from any file.The symbols starting with
not_indexed
should not be available.All this is tested on the backend side.