Detailed changes
@@ -7342,8 +7342,8 @@ dependencies = [
[[package]]
name = "tree-sitter-elixir"
-version = "0.19.0"
-source = "git+https://github.com/elixir-lang/tree-sitter-elixir?rev=05e3631c6a0701c1fa518b0fee7be95a2ceef5e2#05e3631c6a0701c1fa518b0fee7be95a2ceef5e2"
+version = "0.1.0"
+source = "git+https://github.com/elixir-lang/tree-sitter-elixir?rev=4ba9dab6e2602960d95b2b625f3386c27e08084e#4ba9dab6e2602960d95b2b625f3386c27e08084e"
dependencies = [
"cc",
"tree-sitter",
@@ -2253,7 +2253,7 @@ impl BufferSnapshot {
}
pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
- self.outline_items_containing(0..self.len(), theme)
+ self.outline_items_containing(0..self.len(), true, theme)
.map(Outline::new)
}
@@ -2265,6 +2265,7 @@ impl BufferSnapshot {
let position = position.to_offset(self);
let mut items = self.outline_items_containing(
position.saturating_sub(1)..self.len().min(position + 1),
+ false,
theme,
)?;
let mut prev_depth = None;
@@ -2279,6 +2280,7 @@ impl BufferSnapshot {
fn outline_items_containing(
&self,
range: Range<usize>,
+ include_extra_context: bool,
theme: Option<&SyntaxTheme>,
) -> Option<Vec<OutlineItem<Anchor>>> {
let mut matches = self.syntax.matches(range.clone(), &self.text, |grammar| {
@@ -2313,7 +2315,10 @@ impl BufferSnapshot {
let node_is_name;
if capture.index == config.name_capture_ix {
node_is_name = true;
- } else if Some(capture.index) == config.context_capture_ix {
+ } else if Some(capture.index) == config.context_capture_ix
+ || (Some(capture.index) == config.extra_context_capture_ix
+ && include_extra_context)
+ {
node_is_name = false;
} else {
continue;
@@ -2340,10 +2345,12 @@ impl BufferSnapshot {
buffer_ranges.first().unwrap().0.start..buffer_ranges.last().unwrap().0.end,
true,
);
+ let mut last_buffer_range_end = 0;
for (buffer_range, is_name) in buffer_ranges {
- if !text.is_empty() {
+ if !text.is_empty() && buffer_range.start > last_buffer_range_end {
text.push(' ');
}
+ last_buffer_range_end = buffer_range.end;
if is_name {
let mut start = text.len();
let end = start + buffer_range.len();
@@ -592,6 +592,52 @@ async fn test_outline_nodes_with_newlines(cx: &mut gpui::TestAppContext) {
);
}
+#[gpui::test]
+async fn test_outline_with_extra_context(cx: &mut gpui::TestAppContext) {
+ let language = javascript_lang()
+ .with_outline_query(
+ r#"
+ (function_declaration
+ "function" @context
+ name: (_) @name
+ parameters: (formal_parameters
+ "(" @context.extra
+ ")" @context.extra)) @item
+ "#,
+ )
+ .unwrap();
+
+ let text = r#"
+ function a() {}
+ function b(c) {}
+ "#
+ .unindent();
+
+ let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(Arc::new(language), cx));
+ let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
+
+ // extra context nodes are included in the outline.
+ let outline = snapshot.outline(None).unwrap();
+ assert_eq!(
+ outline
+ .items
+ .iter()
+ .map(|item| (item.text.as_str(), item.depth))
+ .collect::<Vec<_>>(),
+ &[("function a()", 0), ("function b( )", 0),]
+ );
+
+ // extra context nodes do not appear in breadcrumbs.
+ let symbols = snapshot.symbols_containing(3, None).unwrap();
+ assert_eq!(
+ symbols
+ .iter()
+ .map(|item| (item.text.as_str(), item.depth))
+ .collect::<Vec<_>>(),
+ &[("function a", 0)]
+ );
+}
+
#[gpui::test]
async fn test_symbols_containing(cx: &mut gpui::TestAppContext) {
let text = r#"
@@ -455,6 +455,7 @@ struct OutlineConfig {
item_capture_ix: u32,
name_capture_ix: u32,
context_capture_ix: Option<u32>,
+ extra_context_capture_ix: Option<u32>,
}
struct InjectionConfig {
@@ -771,6 +772,7 @@ impl LanguageRegistry {
}
}
Err(err) => {
+ log::error!("failed to load language {name} - {err}");
let mut state = this.state.write();
state.mark_language_loaded(id);
if let Some(mut txs) = state.loading_languages.remove(&id) {
@@ -1059,34 +1061,22 @@ impl Language {
pub fn with_queries(mut self, queries: LanguageQueries) -> Result<Self> {
if let Some(query) = queries.highlights {
- self = self
- .with_highlights_query(query.as_ref())
- .expect("failed to evaluate highlights query");
+ self = self.with_highlights_query(query.as_ref())?;
}
if let Some(query) = queries.brackets {
- self = self
- .with_brackets_query(query.as_ref())
- .expect("failed to load brackets query");
+ self = self.with_brackets_query(query.as_ref())?;
}
if let Some(query) = queries.indents {
- self = self
- .with_indents_query(query.as_ref())
- .expect("failed to load indents query");
+ self = self.with_indents_query(query.as_ref())?;
}
if let Some(query) = queries.outline {
- self = self
- .with_outline_query(query.as_ref())
- .expect("failed to load outline query");
+ self = self.with_outline_query(query.as_ref())?;
}
if let Some(query) = queries.injections {
- self = self
- .with_injection_query(query.as_ref())
- .expect("failed to load injection query");
+ self = self.with_injection_query(query.as_ref())?;
}
if let Some(query) = queries.overrides {
- self = self
- .with_override_query(query.as_ref())
- .expect("failed to load override query");
+ self = self.with_override_query(query.as_ref())?;
}
Ok(self)
}
@@ -1102,12 +1092,14 @@ impl Language {
let mut item_capture_ix = None;
let mut name_capture_ix = None;
let mut context_capture_ix = None;
+ let mut extra_context_capture_ix = None;
get_capture_indices(
&query,
&mut [
("item", &mut item_capture_ix),
("name", &mut name_capture_ix),
("context", &mut context_capture_ix),
+ ("context.extra", &mut extra_context_capture_ix),
],
);
if let Some((item_capture_ix, name_capture_ix)) = item_capture_ix.zip(name_capture_ix) {
@@ -1116,6 +1108,7 @@ impl Language {
item_capture_ix,
name_capture_ix,
context_capture_ix,
+ extra_context_capture_ix,
});
}
Ok(self)
@@ -106,7 +106,7 @@ tree-sitter = "0.20"
tree-sitter-c = "0.20.1"
tree-sitter-cpp = "0.20.0"
tree-sitter-css = { git = "https://github.com/tree-sitter/tree-sitter-css", rev = "769203d0f9abe1a9a691ac2b9fe4bb4397a73c51" }
-tree-sitter-elixir = { git = "https://github.com/elixir-lang/tree-sitter-elixir", rev = "05e3631c6a0701c1fa518b0fee7be95a2ceef5e2" }
+tree-sitter-elixir = { git = "https://github.com/elixir-lang/tree-sitter-elixir", rev = "4ba9dab6e2602960d95b2b625f3386c27e08084e" }
tree-sitter-embedded-template = "0.20.0"
tree-sitter-go = { git = "https://github.com/tree-sitter/tree-sitter-go", rev = "aeb2f33b366fd78d5789ff104956ce23508b85db" }
tree-sitter-json = { git = "https://github.com/tree-sitter/tree-sitter-json", rev = "40a81c01a40ac48744e0c8ccabbaba1920441199" }
@@ -1,20 +1,5 @@
["when" "and" "or" "not" "in" "not in" "fn" "do" "end" "catch" "rescue" "after" "else"] @keyword
-(unary_operator
- operator: "@" @comment.doc
- operand: (call
- target: (identifier) @comment.doc.__attribute__
- (arguments
- [
- (string) @comment.doc
- (charlist) @comment.doc
- (sigil
- quoted_start: _ @comment.doc
- quoted_end: _ @comment.doc) @comment.doc
- (boolean) @comment.doc
- ]))
- (#match? @comment.doc.__attribute__ "^(moduledoc|typedoc|doc)$"))
-
(unary_operator
operator: "&"
operand: (integer) @operator)
@@ -84,6 +69,11 @@
quoted_start: _ @string.special
quoted_end: _ @string.special) @string.special
+(
+ (identifier) @comment.unused
+ (#match? @comment.unused "^_")
+)
+
(call
target: [
(identifier) @function
@@ -99,17 +89,12 @@
(binary_operator
left: (identifier) @function
operator: "when")
+ (binary_operator
+ operator: "|>"
+ right: (identifier))
])
(#match? @keyword "^(def|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp|defp)$"))
-(call
- target: (identifier) @keyword
- (arguments
- (binary_operator
- operator: "|>"
- right: (identifier)))
- (#match? @keyword "^(def|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp|defp)$"))
-
(binary_operator
operator: "|>"
right: (identifier) @function)
@@ -127,10 +112,18 @@
(#match? @constant.builtin "^(__MODULE__|__DIR__|__ENV__|__CALLER__|__STACKTRACE__)$")
)
-(
- (identifier) @comment.unused
- (#match? @comment.unused "^_")
-)
+(unary_operator
+ operator: "@" @comment.doc
+ operand: (call
+ target: (identifier) @__attribute__ @comment.doc
+ (arguments
+ [
+ (string)
+ (charlist)
+ (sigil)
+ (boolean)
+ ] @comment.doc))
+ (#match? @__attribute__ "^(moduledoc|typedoc|doc)$"))
(comment) @comment
@@ -1,6 +1,4 @@
-[
- (call)
-] @indent
+(call) @indent
(_ "[" "]" @end) @indent
(_ "{" "}" @end) @indent
@@ -8,9 +8,19 @@
(arguments
[
(identifier) @name
- (call target: (identifier) @name)
+ (call
+ target: (identifier) @name
+ (arguments
+ "(" @context.extra
+ _* @context.extra
+ ")" @context.extra))
(binary_operator
- left: (call target: (identifier) @name)
+ left: (call
+ target: (identifier) @name
+ (arguments
+ "(" @context.extra
+ _* @context.extra
+ ")" @context.extra))
operator: "when")
])
(#match? @context "^(def|defp|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp)$")) @item
@@ -327,10 +327,10 @@ mod tests {
.map(|item| (item.text.as_str(), item.depth))
.collect::<Vec<_>>(),
&[
- ("function a ( )", 0),
- ("async function a2 ( )", 1),
+ ("function a()", 0),
+ ("async function a2()", 1),
("let b", 0),
- ("function getB ( )", 0),
+ ("function getB()", 0),
("const d", 0),
]
);