mirror of
https://github.com/helix-editor/helix.git
synced 2025-10-06 08:23:27 +02:00
Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
2719a35123 | ||
|
0a6672c626 | ||
|
b51111a364 | ||
|
78980f575b | ||
|
0bb375bafa | ||
|
e88383d990 | ||
|
f4560cb68a | ||
|
cbb3ebafdc | ||
|
0851110d10 | ||
|
3ace581191 | ||
|
c0264b9f7f | ||
|
22dad592b8 | ||
|
ca042a4bde | ||
|
67b1cd32c7 | ||
|
4d12c7c3cf | ||
|
4f56a8e248 | ||
|
dbc392d92c | ||
|
7967d312c0 | ||
|
db48d22384 | ||
|
533ff61d0e | ||
|
b1ce969d80 | ||
|
01bf363446 | ||
|
cc323f7665 | ||
|
60caaf7fc4 | ||
|
ea824ed05d | ||
|
cfae07e7ba | ||
|
56dbc60840 | ||
|
c2e6b9f506 |
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -82,3 +82,7 @@
|
||||
path = helix-syntax/languages/tree-sitter-toml
|
||||
url = https://github.com/ikatyang/tree-sitter-toml
|
||||
shallow = true
|
||||
[submodule "helix-syntax/languages/tree-sitter-elixir"]
|
||||
path = helix-syntax/languages/tree-sitter-elixir
|
||||
url = https://github.com/IceDragon200/tree-sitter-elixir
|
||||
shallow = true
|
||||
|
@@ -42,6 +42,14 @@ Now copy the `runtime/` directory somewhere. Helix will by default look for the
|
||||
runtime inside the same folder as the executable, but that can be overriden via
|
||||
the `HELIX_RUNTIME` environment variable.
|
||||
|
||||
> NOTE: You should set this to <path to repository>/runtime in development (if
|
||||
> running via cargo).
|
||||
|
||||
## Arch Linux
|
||||
There are two packages available from AUR:
|
||||
- `helix-bin`: contains prebuilt binary from GitHub releases
|
||||
- `helix-git`: builds the master branch of this repository
|
||||
|
||||
# Contributing
|
||||
|
||||
Contributors are very welcome! **No contribution is too small and all contributions are valued.**
|
||||
|
@@ -4,3 +4,6 @@ language = "en"
|
||||
multilingual = false
|
||||
src = "src"
|
||||
theme = "colibri"
|
||||
|
||||
[output.html]
|
||||
cname = "docs.helix-editor.com"
|
||||
|
@@ -6,10 +6,7 @@ We provide pre-built binaries on the [GitHub Releases page](https://github.com/h
|
||||
|
||||
TODO: brew tap
|
||||
|
||||
```
|
||||
$ brew tap helix-editor/helix
|
||||
$ brew install helix
|
||||
```
|
||||
Please use a pre-built binary release for the time being.
|
||||
|
||||
## Linux
|
||||
|
||||
@@ -21,7 +18,9 @@ shell for working on Helix.
|
||||
|
||||
### Arch Linux
|
||||
|
||||
A binary package is available on AUR as [helix-bin](https://aur.archlinux.org/packages/helix-bin/).
|
||||
Binary packages are available on AUR:
|
||||
- [helix-bin](https://aur.archlinux.org/packages/helix-bin/) contains the pre-built release
|
||||
- [helix-git](https://aur.archlinux.org/packages/helix-git/) builds the master branch
|
||||
|
||||
## Build from source
|
||||
|
||||
|
@@ -118,7 +118,7 @@ Jumps to various locations.
|
||||
|-----|-----------|
|
||||
| g | Go to the start of the file |
|
||||
| e | Go to the end of the file |
|
||||
| e | Go to definition |
|
||||
| d | Go to definition |
|
||||
| t | Go to type definition |
|
||||
| r | Go to references |
|
||||
| i | Go to implementation |
|
||||
|
@@ -45,7 +45,7 @@ pub fn move_vertically(
|
||||
|
||||
let new_line = match dir {
|
||||
Direction::Backward => row.saturating_sub(count),
|
||||
Direction::Forward => std::cmp::min(row.saturating_add(count), text.len_lines() - 1),
|
||||
Direction::Forward => std::cmp::min(row.saturating_add(count), text.len_lines() - 2),
|
||||
};
|
||||
|
||||
// convert to 0-indexed, subtract another 1 because len_chars() counts \n
|
||||
@@ -76,8 +76,9 @@ pub fn move_next_word_start(slice: RopeSlice, mut begin: usize, count: usize) ->
|
||||
begin += 1;
|
||||
}
|
||||
|
||||
// return if not skip while?
|
||||
skip_over_next(slice, &mut begin, |ch| ch == '\n');
|
||||
if !skip_over_next(slice, &mut begin, |ch| ch == '\n') {
|
||||
return None;
|
||||
};
|
||||
ch = slice.char(begin);
|
||||
|
||||
end = begin + 1;
|
||||
@@ -134,7 +135,7 @@ pub fn move_next_word_end(slice: RopeSlice, mut begin: usize, count: usize) -> O
|
||||
let mut end = begin;
|
||||
|
||||
for _ in 0..count {
|
||||
if begin + 1 == slice.len_chars() {
|
||||
if begin + 2 >= slice.len_chars() {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -145,8 +146,9 @@ pub fn move_next_word_end(slice: RopeSlice, mut begin: usize, count: usize) -> O
|
||||
begin += 1;
|
||||
}
|
||||
|
||||
// return if not skip while?
|
||||
skip_over_next(slice, &mut begin, |ch| ch == '\n');
|
||||
if !skip_over_next(slice, &mut begin, |ch| ch == '\n') {
|
||||
return None;
|
||||
};
|
||||
|
||||
end = begin;
|
||||
|
||||
@@ -199,18 +201,20 @@ fn categorize(ch: char) -> Category {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn skip_over_next<F>(slice: RopeSlice, pos: &mut usize, fun: F)
|
||||
/// Returns true if there are more characters left after the new position.
|
||||
pub fn skip_over_next<F>(slice: RopeSlice, pos: &mut usize, fun: F) -> bool
|
||||
where
|
||||
F: Fn(char) -> bool,
|
||||
{
|
||||
let mut chars = slice.chars_at(*pos);
|
||||
|
||||
for ch in chars {
|
||||
while let Some(ch) = chars.next() {
|
||||
if !fun(ch) {
|
||||
break;
|
||||
}
|
||||
*pos += 1;
|
||||
}
|
||||
chars.next().is_some()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@@ -7,6 +7,10 @@ pub fn find_nth_next(
|
||||
n: usize,
|
||||
inclusive: bool,
|
||||
) -> Option<usize> {
|
||||
if pos >= text.len_chars() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// start searching right after pos
|
||||
let mut chars = text.chars_at(pos + 1);
|
||||
|
||||
|
@@ -107,7 +107,10 @@ fn build_dir(dir: &str, language: &str) {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let ignore = vec!["tree-sitter-typescript".to_string()];
|
||||
let ignore = vec![
|
||||
"tree-sitter-typescript".to_string(),
|
||||
".DS_Store".to_string(),
|
||||
];
|
||||
let dirs = collect_tree_sitter_dirs(&ignore);
|
||||
|
||||
let mut n_jobs = 0;
|
||||
|
1
helix-syntax/languages/tree-sitter-elixir
Submodule
1
helix-syntax/languages/tree-sitter-elixir
Submodule
Submodule helix-syntax/languages/tree-sitter-elixir added at 295e62a43b
@@ -72,6 +72,7 @@ mk_langs!(
|
||||
(CSharp, tree_sitter_c_sharp),
|
||||
(Cpp, tree_sitter_cpp),
|
||||
(Css, tree_sitter_css),
|
||||
(Elixir, tree_sitter_elixir),
|
||||
(Go, tree_sitter_go),
|
||||
// (Haskell, tree_sitter_haskell),
|
||||
(Html, tree_sitter_html),
|
||||
|
@@ -473,10 +473,10 @@ fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
|
||||
let last_line = view.last_line(doc);
|
||||
|
||||
// clamp into viewport
|
||||
let line = cursor.row.clamp(
|
||||
view.first_line + scrolloff,
|
||||
last_line.saturating_sub(scrolloff),
|
||||
);
|
||||
let line = cursor
|
||||
.row
|
||||
.min(view.first_line + scrolloff)
|
||||
.max(last_line.saturating_sub(scrolloff));
|
||||
|
||||
let text = doc.text().slice(..);
|
||||
let pos = pos_at_coords(text, Position::new(line, cursor.col)); // this func will properly truncate to line end
|
||||
@@ -1031,6 +1031,9 @@ pub fn command_mode(cx: &mut Context) {
|
||||
}
|
||||
|
||||
let parts = input.split_ascii_whitespace().collect::<Vec<&str>>();
|
||||
if parts.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(cmd) = cmd::COMMANDS.get(parts[0]) {
|
||||
(cmd.fun)(editor, &parts[1..], event);
|
||||
|
@@ -122,7 +122,9 @@ impl Compositor {
|
||||
}
|
||||
|
||||
pub fn render(&mut self, cx: &mut Context) {
|
||||
self.terminal.autoresize().unwrap();
|
||||
let area = self.size();
|
||||
|
||||
let surface = self.terminal.current_buffer_mut();
|
||||
|
||||
for layer in &self.layers {
|
||||
|
@@ -240,10 +240,12 @@ pub fn default() -> Keymaps {
|
||||
code: KeyCode::PageUp,
|
||||
modifiers: KeyModifiers::NONE
|
||||
} => commands::page_up,
|
||||
ctrl!('b') => commands::page_up,
|
||||
KeyEvent {
|
||||
code: KeyCode::PageDown,
|
||||
modifiers: KeyModifiers::NONE
|
||||
} => commands::page_down,
|
||||
ctrl!('f') => commands::page_down,
|
||||
ctrl!('u') => commands::half_page_up,
|
||||
ctrl!('d') => commands::half_page_down,
|
||||
|
||||
|
@@ -8,11 +8,13 @@ mod ui;
|
||||
|
||||
use application::Application;
|
||||
|
||||
use helix_core::config_dir;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::Error;
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
fn setup_logging(verbosity: u64) -> Result<(), fern::InitError> {
|
||||
fn setup_logging(verbosity: u64) -> Result<()> {
|
||||
let mut base_config = fern::Dispatch::new();
|
||||
|
||||
// Let's say we depend on something which whose "info" level messages are too
|
||||
@@ -27,8 +29,6 @@ fn setup_logging(verbosity: u64) -> Result<(), fern::InitError> {
|
||||
_3_or_more => base_config.level(log::LevelFilter::Trace),
|
||||
};
|
||||
|
||||
let home = dirs_next::home_dir().expect("can't find the home directory");
|
||||
|
||||
// Separate file config so we can include year, month and day in file logs
|
||||
let file_config = fern::Dispatch::new()
|
||||
.format(|out, message, record| {
|
||||
@@ -40,7 +40,7 @@ fn setup_logging(verbosity: u64) -> Result<(), fern::InitError> {
|
||||
message
|
||||
))
|
||||
})
|
||||
.chain(fern::log_file(home.join("helix.log"))?);
|
||||
.chain(fern::log_file(config_dir().join("helix.log"))?);
|
||||
|
||||
base_config.chain(file_config).apply()?;
|
||||
|
||||
@@ -51,7 +51,7 @@ pub struct Args {
|
||||
files: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
fn main() -> Result<()> {
|
||||
let help = format!(
|
||||
"\
|
||||
{} {}
|
||||
@@ -89,14 +89,19 @@ FLAGS:
|
||||
verbosity = 1;
|
||||
}
|
||||
|
||||
setup_logging(verbosity).expect("failed to initialize logging.");
|
||||
let conf_dir = config_dir();
|
||||
|
||||
if !conf_dir.exists() {
|
||||
std::fs::create_dir(&conf_dir);
|
||||
}
|
||||
|
||||
setup_logging(verbosity).context("failed to initialize logging")?;
|
||||
|
||||
let args = Args {
|
||||
files: pargs.finish().into_iter().map(|arg| arg.into()).collect(),
|
||||
};
|
||||
|
||||
// initialize language registry
|
||||
use helix_core::config_dir;
|
||||
use helix_core::syntax::{Loader, LOADER};
|
||||
|
||||
// load $HOME/.config/helix/languages.toml, fallback to default config
|
||||
@@ -105,17 +110,16 @@ FLAGS:
|
||||
.as_deref()
|
||||
.unwrap_or(include_bytes!("../../languages.toml"));
|
||||
|
||||
LOADER.get_or_init(|| {
|
||||
let config = toml::from_slice(toml).expect("Could not parse languages.toml");
|
||||
Loader::new(config)
|
||||
});
|
||||
let config = toml::from_slice(toml).context("Could not parse languages.toml")?;
|
||||
LOADER.get_or_init(|| Loader::new(config));
|
||||
|
||||
let runtime = tokio::runtime::Runtime::new().unwrap();
|
||||
let runtime = tokio::runtime::Runtime::new().context("unable to start tokio runtime")?;
|
||||
|
||||
// TODO: use the thread local executor to spawn the application task separately from the work pool
|
||||
let mut app = Application::new(args).context("unable to create new appliction")?;
|
||||
runtime.block_on(async move {
|
||||
let mut app = Application::new(args).unwrap();
|
||||
|
||||
app.run().await;
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@@ -138,11 +138,9 @@ where
|
||||
|
||||
/// Queries the backend for size and resizes if it doesn't match the previous size.
|
||||
pub fn autoresize(&mut self) -> io::Result<()> {
|
||||
if self.viewport.resize_behavior == ResizeBehavior::Auto {
|
||||
let size = self.size()?;
|
||||
if size != self.viewport.area {
|
||||
self.resize(size)?;
|
||||
}
|
||||
let size = self.size()?;
|
||||
if size != self.viewport.area {
|
||||
self.resize(size)?;
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
@@ -17,6 +17,15 @@ roots = []
|
||||
|
||||
indent = { tab-width = 2, unit = " " }
|
||||
|
||||
[[language]]
|
||||
name = "elixir"
|
||||
scope = "source.elixir"
|
||||
injection-regex = "elixir"
|
||||
file-types = ["ex", "exs"]
|
||||
roots = []
|
||||
|
||||
indent = { tab-width = 2, unit = " " }
|
||||
|
||||
[[language]]
|
||||
name = "json"
|
||||
scope = "source.json"
|
||||
@@ -65,6 +74,17 @@ roots = []
|
||||
|
||||
indent = { tab-width = 2, unit = " " }
|
||||
|
||||
[[language]]
|
||||
name = "typescript"
|
||||
scope = "source.ts"
|
||||
injection-regex = "^(ts|typescript)$"
|
||||
file-types = ["ts"]
|
||||
roots = []
|
||||
# TODO: highlights-jsx, highlights-params
|
||||
|
||||
language-server = { command = "typescript-language-server", args = ["--stdio"] }
|
||||
indent = { tab-width = 2, unit = " " }
|
||||
|
||||
[[language]]
|
||||
name = "css"
|
||||
scope = "source.css"
|
||||
|
146
runtime/queries/elixir/highlights.scm
Normal file
146
runtime/queries/elixir/highlights.scm
Normal file
@@ -0,0 +1,146 @@
|
||||
["when" "and" "or" "not in" "not" "in" "fn" "do" "end" "catch" "rescue" "after" "else"] @keyword
|
||||
|
||||
[(true) (false) (nil)] @constant.builtin
|
||||
|
||||
(keyword
|
||||
[(keyword_literal)
|
||||
":"] @tag)
|
||||
|
||||
(keyword
|
||||
(keyword_string
|
||||
[(string_start)
|
||||
(string_content)
|
||||
(string_end)] @tag))
|
||||
|
||||
[(atom_literal)
|
||||
(atom_start)
|
||||
(atom_content)
|
||||
(atom_end)] @tag
|
||||
|
||||
(comment) @comment
|
||||
|
||||
(escape_sequence) @escape
|
||||
|
||||
(call function: (function_identifier) @keyword
|
||||
(#match? @keyword "^(defmodule|defexception|defp|def|with|case|cond|raise|import|require|use|defmacrop|defmacro|defguardp|defguard|defdelegate|defstruct|alias|defimpl|defprotocol|defoverridable|receive|if|for|try|throw|unless|reraise|super|quote|unquote|unquote_splicing)$"))
|
||||
|
||||
(call function: (function_identifier) @keyword
|
||||
[(call
|
||||
function: (function_identifier) @function
|
||||
(arguments
|
||||
[(identifier) @variable.parameter
|
||||
(_ (identifier) @variable.parameter)
|
||||
(_ (_ (identifier) @variable.parameter))
|
||||
(_ (_ (_ (identifier) @variable.parameter)))
|
||||
(_ (_ (_ (_ (identifier) @variable.parameter))))
|
||||
(_ (_ (_ (_ (_ (identifier) @variable.parameter)))))]))
|
||||
(binary_op
|
||||
left:
|
||||
(call
|
||||
function: (function_identifier) @function
|
||||
(arguments
|
||||
[(identifier) @variable.parameter
|
||||
(_ (identifier) @variable.parameter)
|
||||
(_ (_ (identifier) @variable.parameter))
|
||||
(_ (_ (_ (identifier) @variable.parameter)))
|
||||
(_ (_ (_ (_ (identifier) @variable.parameter))))
|
||||
(_ (_ (_ (_ (_ (identifier) @variable.parameter)))))]))
|
||||
operator: "when")
|
||||
(binary_op
|
||||
left: (identifier) @variable.parameter
|
||||
operator: _ @function
|
||||
right: (identifier) @variable.parameter)]
|
||||
(#match? @keyword "^(defp|def|defmacrop|defmacro|defguardp|defguard|defdelegate)$")
|
||||
(#match? @variable.parameter "^[^_]"))
|
||||
|
||||
(call (function_identifier) @keyword
|
||||
[(call
|
||||
function: (function_identifier) @function)
|
||||
(identifier) @function
|
||||
(binary_op
|
||||
left:
|
||||
[(call
|
||||
function: (function_identifier) @function)
|
||||
(identifier) @function]
|
||||
operator: "when")]
|
||||
(#match? @keyword "^(defp|def|defmacrop|defmacro|defguardp|defguard|defdelegate)$"))
|
||||
|
||||
(anonymous_function
|
||||
(stab_expression
|
||||
left: (bare_arguments
|
||||
[(identifier) @variable.parameter
|
||||
(_ (identifier) @variable.parameter)
|
||||
(_ (_ (identifier) @variable.parameter))
|
||||
(_ (_ (_ (identifier) @variable.parameter)))
|
||||
(_ (_ (_ (_ (identifier) @variable.parameter))))
|
||||
(_ (_ (_ (_ (_ (identifier) @variable.parameter)))))]))
|
||||
(#match? @variable.parameter "^[^_]"))
|
||||
|
||||
(unary_op
|
||||
operator: "@"
|
||||
(call (identifier) @attribute
|
||||
(heredoc
|
||||
[(heredoc_start)
|
||||
(heredoc_content)
|
||||
(heredoc_end)] @doc))
|
||||
(#match? @attribute "^(doc|moduledoc)$"))
|
||||
|
||||
(module) @type
|
||||
|
||||
(unary_op
|
||||
operator: "@" @attribute
|
||||
[(call
|
||||
function: (function_identifier) @attribute)
|
||||
(identifier) @attribute])
|
||||
|
||||
(unary_op
|
||||
operator: _ @operator)
|
||||
|
||||
(binary_op
|
||||
operator: _ @operator)
|
||||
|
||||
(heredoc
|
||||
[(heredoc_start)
|
||||
(heredoc_content)
|
||||
(heredoc_end)] @string)
|
||||
|
||||
(string
|
||||
[(string_start)
|
||||
(string_content)
|
||||
(string_end)] @string)
|
||||
|
||||
(sigil_start) @string.special
|
||||
(sigil_content) @string
|
||||
(sigil_end) @string.special
|
||||
|
||||
(interpolation
|
||||
"#{" @punctuation.special
|
||||
"}" @punctuation.special)
|
||||
|
||||
[
|
||||
","
|
||||
"->"
|
||||
"."
|
||||
] @punctuation.delimiter
|
||||
|
||||
[
|
||||
"("
|
||||
")"
|
||||
"["
|
||||
"]"
|
||||
"{"
|
||||
"}"
|
||||
"<<"
|
||||
">>"
|
||||
] @punctuation.bracket
|
||||
|
||||
[(identifier) @function.special
|
||||
(#match? @function.special "^__.+__$")]
|
||||
|
||||
[(remote_identifier) @function.special
|
||||
(#match? @function.special "^__.+__$")]
|
||||
|
||||
[(identifier) @comment
|
||||
(#match? @comment "^_")]
|
||||
|
||||
(ERROR) @warning
|
28
runtime/queries/javascript/indents.toml
Normal file
28
runtime/queries/javascript/indents.toml
Normal file
@@ -0,0 +1,28 @@
|
||||
indent = [
|
||||
"array",
|
||||
"object",
|
||||
"arguments",
|
||||
"formal_parameters",
|
||||
|
||||
"statement_block",
|
||||
"object_pattern",
|
||||
"class_body",
|
||||
"named_imports",
|
||||
|
||||
"binary_expression",
|
||||
"return_statement",
|
||||
"template_substitution",
|
||||
# (expression_statement (call_expression))
|
||||
"export_clause",
|
||||
|
||||
# typescript
|
||||
"enum_declaration",
|
||||
"interface_declaration",
|
||||
"object_type",
|
||||
]
|
||||
|
||||
outdent = [
|
||||
"}",
|
||||
"]",
|
||||
")"
|
||||
]
|
36
runtime/queries/typescript/highlights.scm
Normal file
36
runtime/queries/typescript/highlights.scm
Normal file
@@ -0,0 +1,36 @@
|
||||
; inherits: javascript
|
||||
|
||||
; Types
|
||||
|
||||
(type_identifier) @type
|
||||
(predefined_type) @type.builtin
|
||||
|
||||
((identifier) @type
|
||||
(#match? @type "^[A-Z]"))
|
||||
|
||||
(type_arguments
|
||||
"<" @punctuation.bracket
|
||||
">" @punctuation.bracket)
|
||||
|
||||
; Variables
|
||||
|
||||
(required_parameter (identifier) @variable.parameter)
|
||||
(optional_parameter (identifier) @variable.parameter)
|
||||
|
||||
; Keywords
|
||||
|
||||
[
|
||||
"abstract"
|
||||
"declare"
|
||||
"enum"
|
||||
"export"
|
||||
"implements"
|
||||
"interface"
|
||||
"keyof"
|
||||
"namespace"
|
||||
"private"
|
||||
"protected"
|
||||
"public"
|
||||
"type"
|
||||
"readonly"
|
||||
] @keyword
|
1
runtime/queries/typescript/indents.toml
Symbolic link
1
runtime/queries/typescript/indents.toml
Symbolic link
@@ -0,0 +1 @@
|
||||
../javascript/indents.toml
|
2
runtime/queries/typescript/locals.scm
Normal file
2
runtime/queries/typescript/locals.scm
Normal file
@@ -0,0 +1,2 @@
|
||||
(required_parameter (identifier) @local.definition)
|
||||
(optional_parameter (identifier) @local.definition)
|
23
runtime/queries/typescript/tags.scm
Normal file
23
runtime/queries/typescript/tags.scm
Normal file
@@ -0,0 +1,23 @@
|
||||
(function_signature
|
||||
name: (identifier) @name) @definition.function
|
||||
|
||||
(method_signature
|
||||
name: (property_identifier) @name) @definition.method
|
||||
|
||||
(abstract_method_signature
|
||||
name: (property_identifier) @name) @definition.method
|
||||
|
||||
(abstract_class_declaration
|
||||
name: (type_identifier) @name) @definition.class
|
||||
|
||||
(module
|
||||
name: (identifier) @name) @definition.module
|
||||
|
||||
(interface_declaration
|
||||
name: (type_identifier) @name) @definition.interface
|
||||
|
||||
(type_annotation
|
||||
(type_identifier) @name) @reference.type
|
||||
|
||||
(new_expression
|
||||
constructor: (identifier) @name) @reference.class
|
Reference in New Issue
Block a user