add embedding treesitter queries for elixir
This commit is contained in:
parent
f0bf60fded
commit
e630ff38c4
4 changed files with 222 additions and 1 deletions
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -7982,6 +7982,16 @@ dependencies = [
|
||||||
"tree-sitter",
|
"tree-sitter",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tree-sitter-elixir"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a9916f3e1c80b3c8aab8582604e97e8720cb9b893489b347cf999f80f9d469e"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"tree-sitter",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tree-sitter-elixir"
|
name = "tree-sitter-elixir"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -8519,6 +8529,7 @@ dependencies = [
|
||||||
"tiktoken-rs 0.5.0",
|
"tiktoken-rs 0.5.0",
|
||||||
"tree-sitter",
|
"tree-sitter",
|
||||||
"tree-sitter-cpp",
|
"tree-sitter-cpp",
|
||||||
|
"tree-sitter-elixir 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tree-sitter-rust",
|
"tree-sitter-rust",
|
||||||
"tree-sitter-toml 0.20.0",
|
"tree-sitter-toml 0.20.0",
|
||||||
"tree-sitter-typescript 0.20.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tree-sitter-typescript 0.20.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -9558,7 +9569,7 @@ dependencies = [
|
||||||
"tree-sitter-c",
|
"tree-sitter-c",
|
||||||
"tree-sitter-cpp",
|
"tree-sitter-cpp",
|
||||||
"tree-sitter-css",
|
"tree-sitter-css",
|
||||||
"tree-sitter-elixir",
|
"tree-sitter-elixir 0.1.0 (git+https://github.com/elixir-lang/tree-sitter-elixir?rev=4ba9dab6e2602960d95b2b625f3386c27e08084e)",
|
||||||
"tree-sitter-embedded-template",
|
"tree-sitter-embedded-template",
|
||||||
"tree-sitter-go",
|
"tree-sitter-go",
|
||||||
"tree-sitter-heex",
|
"tree-sitter-heex",
|
||||||
|
|
|
@ -55,3 +55,4 @@ tree-sitter-typescript = "*"
|
||||||
tree-sitter-rust = "*"
|
tree-sitter-rust = "*"
|
||||||
tree-sitter-toml = "*"
|
tree-sitter-toml = "*"
|
||||||
tree-sitter-cpp = "*"
|
tree-sitter-cpp = "*"
|
||||||
|
tree-sitter-elixir = "*"
|
||||||
|
|
|
@ -342,6 +342,143 @@ async fn test_code_context_retrieval_javascript() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_code_context_retrieval_elixir() {
|
||||||
|
let language = elixir_lang();
|
||||||
|
let mut retriever = CodeContextRetriever::new();
|
||||||
|
|
||||||
|
let text = r#"
|
||||||
|
defmodule File.Stream do
|
||||||
|
@moduledoc """
|
||||||
|
Defines a `File.Stream` struct returned by `File.stream!/3`.
|
||||||
|
|
||||||
|
The following fields are public:
|
||||||
|
|
||||||
|
* `path` - the file path
|
||||||
|
* `modes` - the file modes
|
||||||
|
* `raw` - a boolean indicating if bin functions should be used
|
||||||
|
* `line_or_bytes` - if reading should read lines or a given number of bytes
|
||||||
|
* `node` - the node the file belongs to
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
defstruct path: nil, modes: [], line_or_bytes: :line, raw: true, node: nil
|
||||||
|
|
||||||
|
@type t :: %__MODULE__{}
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def __build__(path, modes, line_or_bytes) do
|
||||||
|
raw = :lists.keyfind(:encoding, 1, modes) == false
|
||||||
|
|
||||||
|
modes =
|
||||||
|
case raw do
|
||||||
|
true ->
|
||||||
|
case :lists.keyfind(:read_ahead, 1, modes) do
|
||||||
|
{:read_ahead, false} -> [:raw | :lists.keydelete(:read_ahead, 1, modes)]
|
||||||
|
{:read_ahead, _} -> [:raw | modes]
|
||||||
|
false -> [:raw, :read_ahead | modes]
|
||||||
|
end
|
||||||
|
|
||||||
|
false ->
|
||||||
|
modes
|
||||||
|
end
|
||||||
|
|
||||||
|
%File.Stream{path: path, modes: modes, raw: raw, line_or_bytes: line_or_bytes, node: node()}
|
||||||
|
|
||||||
|
end
|
||||||
|
"#
|
||||||
|
.unindent();
|
||||||
|
|
||||||
|
let parsed_files = retriever
|
||||||
|
.parse_file(Path::new("foo.ex"), &text, language)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let test_documents = &[
|
||||||
|
Document{
|
||||||
|
name: "defmodule File.Stream".into(),
|
||||||
|
range: 0..1132,
|
||||||
|
content: r#"
|
||||||
|
The below code snippet is from file 'foo.ex'
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
defmodule File.Stream do
|
||||||
|
@moduledoc """
|
||||||
|
Defines a `File.Stream` struct returned by `File.stream!/3`.
|
||||||
|
|
||||||
|
The following fields are public:
|
||||||
|
|
||||||
|
* `path` - the file path
|
||||||
|
* `modes` - the file modes
|
||||||
|
* `raw` - a boolean indicating if bin functions should be used
|
||||||
|
* `line_or_bytes` - if reading should read lines or a given number of bytes
|
||||||
|
* `node` - the node the file belongs to
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
defstruct path: nil, modes: [], line_or_bytes: :line, raw: true, node: nil
|
||||||
|
|
||||||
|
@type t :: %__MODULE__{}
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def __build__(path, modes, line_or_bytes) do
|
||||||
|
raw = :lists.keyfind(:encoding, 1, modes) == false
|
||||||
|
|
||||||
|
modes =
|
||||||
|
case raw do
|
||||||
|
true ->
|
||||||
|
case :lists.keyfind(:read_ahead, 1, modes) do
|
||||||
|
{:read_ahead, false} -> [:raw | :lists.keydelete(:read_ahead, 1, modes)]
|
||||||
|
{:read_ahead, _} -> [:raw | modes]
|
||||||
|
false -> [:raw, :read_ahead | modes]
|
||||||
|
end
|
||||||
|
|
||||||
|
false ->
|
||||||
|
modes
|
||||||
|
end
|
||||||
|
|
||||||
|
%File.Stream{path: path, modes: modes, raw: raw, line_or_bytes: line_or_bytes, node: node()}
|
||||||
|
|
||||||
|
end
|
||||||
|
```"#.unindent(),
|
||||||
|
embedding: vec![],
|
||||||
|
},
|
||||||
|
Document {
|
||||||
|
name: "def __build__".into(),
|
||||||
|
range: 574..1132,
|
||||||
|
content: r#"
|
||||||
|
The below code snippet is from file 'foo.ex'
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
@doc false
|
||||||
|
def __build__(path, modes, line_or_bytes) do
|
||||||
|
raw = :lists.keyfind(:encoding, 1, modes) == false
|
||||||
|
|
||||||
|
modes =
|
||||||
|
case raw do
|
||||||
|
true ->
|
||||||
|
case :lists.keyfind(:read_ahead, 1, modes) do
|
||||||
|
{:read_ahead, false} -> [:raw | :lists.keydelete(:read_ahead, 1, modes)]
|
||||||
|
{:read_ahead, _} -> [:raw | modes]
|
||||||
|
false -> [:raw, :read_ahead | modes]
|
||||||
|
end
|
||||||
|
|
||||||
|
false ->
|
||||||
|
modes
|
||||||
|
end
|
||||||
|
|
||||||
|
%File.Stream{path: path, modes: modes, raw: raw, line_or_bytes: line_or_bytes, node: node()}
|
||||||
|
|
||||||
|
end
|
||||||
|
```"#
|
||||||
|
.unindent(),
|
||||||
|
embedding: vec![],
|
||||||
|
}];
|
||||||
|
|
||||||
|
for idx in 0..test_documents.len() {
|
||||||
|
assert_eq!(test_documents[idx], parsed_files[idx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_code_context_retrieval_cpp() {
|
async fn test_code_context_retrieval_cpp() {
|
||||||
let language = cpp_lang();
|
let language = cpp_lang();
|
||||||
|
@ -850,3 +987,48 @@ fn cpp_lang() -> Arc<Language> {
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn elixir_lang() -> Arc<Language> {
|
||||||
|
Arc::new(
|
||||||
|
Language::new(
|
||||||
|
LanguageConfig {
|
||||||
|
name: "Elixir".into(),
|
||||||
|
path_suffixes: vec!["rs".into()],
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Some(tree_sitter_elixir::language()),
|
||||||
|
)
|
||||||
|
.with_embedding_query(
|
||||||
|
r#"
|
||||||
|
(
|
||||||
|
(unary_operator
|
||||||
|
operator: "@"
|
||||||
|
operand: (call
|
||||||
|
target: (identifier) @unary
|
||||||
|
(#match? @unary "^(doc)$"))
|
||||||
|
) @context
|
||||||
|
.
|
||||||
|
(call
|
||||||
|
target: (identifier) @name
|
||||||
|
(arguments
|
||||||
|
[
|
||||||
|
(identifier) @name
|
||||||
|
(call
|
||||||
|
target: (identifier) @name)
|
||||||
|
(binary_operator
|
||||||
|
left: (call
|
||||||
|
target: (identifier) @name)
|
||||||
|
operator: "when")
|
||||||
|
])
|
||||||
|
(#match? @name "^(def|defp|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp)$")) @item
|
||||||
|
)
|
||||||
|
|
||||||
|
(call
|
||||||
|
target: (identifier) @name
|
||||||
|
(arguments (alias) @name)
|
||||||
|
(#match? @name "^(defmodule|defprotocol)$")) @item
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
27
crates/zed/src/languages/elixir/embedding.scm
Normal file
27
crates/zed/src/languages/elixir/embedding.scm
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
(
|
||||||
|
(unary_operator
|
||||||
|
operator: "@"
|
||||||
|
operand: (call
|
||||||
|
target: (identifier) @unary
|
||||||
|
(#match? @unary "^(doc)$"))
|
||||||
|
) @context
|
||||||
|
.
|
||||||
|
(call
|
||||||
|
target: (identifier) @name
|
||||||
|
(arguments
|
||||||
|
[
|
||||||
|
(identifier) @name
|
||||||
|
(call
|
||||||
|
target: (identifier) @name)
|
||||||
|
(binary_operator
|
||||||
|
left: (call
|
||||||
|
target: (identifier) @name)
|
||||||
|
operator: "when")
|
||||||
|
])
|
||||||
|
(#match? @name "^(def|defp|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp)$")) @item
|
||||||
|
)
|
||||||
|
|
||||||
|
(call
|
||||||
|
target: (identifier) @name
|
||||||
|
(arguments (alias) @name)
|
||||||
|
(#match? @name "^(defmodule|defprotocol)$")) @item
|
Loading…
Add table
Add a link
Reference in a new issue