-
Notifications
You must be signed in to change notification settings - Fork 14
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
Index all assigned variables #620
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,9 @@ use crate::treesitter::NodeTypeExt; | |
|
||
#[derive(Clone, Debug)] | ||
pub enum IndexEntryData { | ||
Variable { | ||
name: String, | ||
}, | ||
Function { | ||
name: String, | ||
arguments: Vec<String>, | ||
|
@@ -117,7 +120,13 @@ fn insert(path: &Path, entry: IndexEntry) -> anyhow::Result<()> { | |
let path = str_from_path(path)?; | ||
|
||
let index = index.entry(path.to_string()).or_default(); | ||
index.insert(entry.key.clone(), entry); | ||
|
||
// Retain the first occurrence in the index. In the future we'll track every occurrences and | ||
// their scopes but for now we only track the first definition of an object (in a way, its | ||
// declaration). | ||
if !index.contains_key(&entry.key) { | ||
index.insert(entry.key.clone(), entry); | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
@@ -205,6 +214,11 @@ fn index_node(path: &Path, contents: &Rope, node: &Node) -> anyhow::Result<Optio | |
return Ok(Some(entry)); | ||
} | ||
|
||
// Should be after function indexing as this is a more general case | ||
if let Ok(Some(entry)) = index_variable(path, contents, node) { | ||
return Ok(Some(entry)); | ||
} | ||
|
||
if let Ok(Some(entry)) = index_comment(path, contents, node) { | ||
return Ok(Some(entry)); | ||
} | ||
|
@@ -262,6 +276,40 @@ fn index_function( | |
})) | ||
} | ||
|
||
fn index_variable( | ||
_path: &Path, | ||
contents: &Rope, | ||
node: &Node, | ||
) -> anyhow::Result<Option<IndexEntry>> { | ||
if !matches!( | ||
node.node_type(), | ||
NodeType::BinaryOperator(BinaryOperatorType::LeftAssignment) | | ||
NodeType::BinaryOperator(BinaryOperatorType::EqualsAssignment) | ||
) { | ||
return Ok(None); | ||
} | ||
|
||
let Some(lhs) = node.child_by_field_name("lhs") else { | ||
return Ok(None); | ||
}; | ||
|
||
let lhs_text = contents.node_slice(&lhs)?.to_string(); | ||
|
||
// Super hacky but let's wait until the typed API to do better | ||
if !lhs_text.starts_with("method(") && !lhs.is_identifier_or_string() { | ||
return Ok(None); | ||
} | ||
|
||
let start = convert_point_to_position(contents, lhs.start_position()); | ||
let end = convert_point_to_position(contents, lhs.end_position()); | ||
|
||
Ok(Some(IndexEntry { | ||
key: lhs_text.clone(), | ||
range: Range { start, end }, | ||
data: IndexEntryData::Variable { name: lhs_text }, | ||
})) | ||
Comment on lines
+298
to
+310
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems pretty reasonable even with the hackiness for method( |
||
} | ||
|
||
fn index_comment(_path: &Path, contents: &Rope, node: &Node) -> anyhow::Result<Option<IndexEntry>> { | ||
// check for comment | ||
node.is_comment().into_result()?; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -95,6 +95,19 @@ pub fn symbols(params: &WorkspaceSymbolParams) -> anyhow::Result<Vec<SymbolInfor | |
container_name: None, | ||
}); | ||
}, | ||
IndexEntryData::Variable { name } => { | ||
info.push(SymbolInformation { | ||
name: name.clone(), | ||
kind: SymbolKind::VARIABLE, | ||
location: Location { | ||
uri: Url::from_file_path(path).unwrap(), | ||
range: entry.range, | ||
}, | ||
tags: None, | ||
deprecated: None, | ||
container_name: None, | ||
}); | ||
}, | ||
Comment on lines
+98
to
+110
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So I guess workspace symbols are enough to power jump to definition, neat |
||
}; | ||
}); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's somewhat interesting to note that for document symbols, i.e. with It even already worked with So it was just the following two places where we weren't indexing variables but we do now:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh I hadn't caught up on that, good catch |
||
|
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.
So this ensures that for the workspace we now add variables to the completion list even if they don't exist yet in the R session. For example in a fresh restart of clock we now get these global constants:
I think that's probably fine, even though sending that to the console will result in an error. I guess its still useful when writing in the editor without loading the package?
However, note that after you load the package, the completion shows up with a different symbol:
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.
I think this will all get cleaned up once we build a stronger model of object scopes.