Commit Graph

263 Commits

Author SHA1 Message Date
Lewis Russell
9beb40a4db feat(docs): replace lua2dox.lua
Problem:

The documentation flow (`gen_vimdoc.py`) has several issues:
- it's not very versatile
- depends on doxygen
- doesn't work well with Lua code as it requires an awkward filter script to convert it into pseudo-C.
- The intermediate XML files and filters makes it too much like a rube goldberg machine.

Solution:

Re-implement the flow using Lua, LPEG and treesitter.

- `gen_vimdoc.py` is now replaced with `gen_vimdoc.lua` and replicates a portion of the logic.
- `lua2dox.lua` is gone!
- No more XML files.
- Doxygen is now longer used and instead we now use:
  - LPEG for comment parsing (see `scripts/luacats_grammar.lua` and `scripts/cdoc_grammar.lua`).
  - LPEG for C parsing (see `scripts/cdoc_parser.lua`)
  - Lua patterns for Lua parsing (see `scripts/luacats_parser.lua`).
  - Treesitter for Markdown parsing (see `scripts/text_utils.lua`).
- The generated `runtime/doc/*.mpack` files have been removed.
   - `scripts/gen_eval_files.lua` now instead uses `scripts/cdoc_parser.lua` directly.
- Text wrapping is implemented in `scripts/text_utils.lua` and appears to produce more consistent results (the main contributer to the diff of this change).
2024-02-27 14:41:17 +00:00
Maria José Solano
185752614d refactor(types): fix miscellaneous type warnings 2024-02-25 22:08:11 +00:00
再生花
bb15fa0356 feat(treesitter): add folding for InspectTree (#27518)
As the InspectTree buffer is now a valid tree-sitter query tree, we can
use the bundled fold queries to have folding for the tree.
2024-02-22 14:58:59 -06:00
Gregory Anders
478273a423 fix: fix iter_matches call in query linter (#27496) 2024-02-16 14:00:19 -06:00
Thomas Vigouroux
bd5008de07 fix(treesitter): correctly handle query quantifiers (#24738)
Query patterns can contain quantifiers (e.g. (foo)+ @bar), so a single
capture can map to multiple nodes. The iter_matches API can not handle
this situation because the match table incorrectly maps capture indices
to a single node instead of to an array of nodes.

The match table should be updated to map capture indices to an array of
nodes. However, this is a massively breaking change, so must be done
with a proper deprecation period.

`iter_matches`, `add_predicate` and `add_directive` must opt-in to the
correct behavior for backward compatibility. This is done with a new
"all" option. This option will become the default and removed after the
0.10 release.

Co-authored-by: Christian Clason <c.clason@uni-graz.at>
Co-authored-by: MDeiml <matthias@deiml.net>
Co-authored-by: Gregory Anders <greg@gpanders.com>
2024-02-16 11:54:47 -06:00
Jongwook Choi
d0e9e36a78 refactor(treesitter): {start,stop} are optional in Query:iter_* methods
Document that the `start` and `stop` parameters in
`Query:iter_captures()` and `Query:iter_matches()` are optional.

The tree-sitter lib has been bumped up to 0.20.9, so we also no longer
need "Requires treesitter >= 0.20.9".
2024-02-08 12:42:19 +00:00
Jongwook Choi
800134ea5e refactor(treesitter): typing for Query, TSQuery, and TSQueryInfo
- `TSQuery`: userdata object for parsed query.

- `vim.treesitter.Query`: renamed from `Query`.
  - Add a new field `lang`.

- `TSQueryInfo`:
  - Move to `vim/treesitter/_meta.lua`, because C code owns it.
  - Correct typing for `patterns`, should be a map from `integer`
    (pattern_id) to `(integer|string)[][]` (list of predicates or
    directives).

- `vim.treesitter.QueryInfo` is added.
  - This currently has the same structure as `TSQueryInfo` (exported
    from C code).
  - Document the fields (see `TSQuery:inspect`).

- Add typing for `vim._ts_parse_query()`.
2024-02-08 12:40:16 +00:00
altermo
c0b99bb1de feat(treesitter): show root nodes in :InspectTree (#26944)
Co-authored-by: altermo <>
Co-authored-by: Jongwook Choi <wookayin@gmail.com>
2024-02-06 14:51:53 -06:00
Jongwook Choi
a478bf936b feat(treesitter): use 0-based indexing to show ranges in :InspectTree
Problem:

- `:InspectTree` was showing node ranges in 1-based indexing, i.e., in
  vim cursor position (lnum, col). However, treesitter API adopts
  0-based indexing to represent ranges (Range4). This can often be
  confusing for developers and plugin authors when debugging code
  written with treesiter APIs.

Solution:

- Change to 0-based indexing from 1-based indexing to show node ranges
  in `:InspectTree`.

- Note: To make things not complicated, we do not provide an option or
  keymap to configure which indexing mode to use.
2024-02-05 16:23:22 -05:00
altermo
6c8387067d fix(treesitter): inspect-tree remember opts on buf change 2024-02-04 15:53:29 +00:00
dundargoc
2e982f1aad refactor: create function for deferred loading
The benefit of this is that users only pay for what they use. If e.g.
only `vim.lsp.buf_get_clients()` is called then they don't need to load
all modules under `vim.lsp` which could lead to significant startuptime
saving.

Also `vim.lsp.module` is a bit nicer to user compared to
`require("vim.lsp.module")`.

This isn't used for some nested modules such as `filetype` as it breaks
tests with error messages such as "attempt to index field 'detect'".
It's not entirely certain the reason for this, but it is likely it is
due to filetype being precompiled which would imply deferred loading
isn't needed for performance reasons.
2024-02-03 16:53:41 +01:00
Jongwook Choi
5b1b765610 docs: enforce "treesitter" spelling #27110
It's the "tree-sitter" project, but "treesitter" in our code and docs.
2024-01-28 17:53:14 -08:00
Till Bungert
0892c080d1 revert: "feat(treesitter): add foldtext with treesitter highlighting"
This reverts commit 9ce1623 in favor of #20750.
2024-01-27 08:38:56 +08:00
Daniel Kongsgaard
32849d5667 fix(treesitter): avoid # of nil in _query_linter 2024-01-24 11:03:54 +00:00
Phạm Huy Hoàng
617d1b28d6 fix(treesitter): prefix treesitter types with vim 2024-01-24 10:01:56 +00:00
Christian Clason
674f2513d4 fix(treesitter): validate language alias for injections
Problem: Parsed language annotations can be random garbage so
`nvim_get_runtime_file` throws an error.

Solution: Validate that `alias` is a valid language name before trying
to find a parser for it.
2024-01-18 15:46:08 +01:00
Lewis Russell
2f9ee9b6cf fix(doc): improve doc generation of types using lpeg
Added a lpeg grammar for LuaCATS and use it in lua2dox.lua
2024-01-11 16:24:12 +00:00
Jongwook Choi
fbe40caa7c docs(treesitter): improve 'no parser' error message for InspectTree
Improve error messages for `:InspectTree`, when no parsers are available
for the current buffer and filetype. We can show more informative and
helpful error message for users (e.g., which lang was searched for):

```
 ... No parser available for the given buffer:
+... no parser for 'custom_ft' language, see :help treesitter-parsers
```

Also improve the relevant docs for *treesitter-parsers*.
2024-01-08 09:27:03 +00:00
dundargoc
5f9d4d8afe refactor: use vim.deprecate on all deprecated functions 2023-12-27 00:05:36 +01:00
Jaehwang Jung
7fa292c52d fix(treesitter): outdated highlight due to tree with outdated region
Problem:
A region managed by an injected parser may shrink after re-running the
injection query. If the updated region goes out of the range to be
parsed, then the corresponding tree will remain outdated, possibly
retaining the nodes that shouldn't exist anymore. This results in
outdated highlights.

Solution:
Re-parse an invalid tree if its region intersects the range to be
parsed.
2023-12-24 09:47:59 +01:00
Lewis Russell
2498747add refactor(treesitter): cleanup highlighter
- Remove some unused fields
- Prefix classes with `vim.`
- Move around some functions so the query stuff is at the top.
- Improve type hints
- Rework how hl_cache is implemented
2023-12-20 11:55:25 +00:00
Jaehwang Jung
90a12d4a16 fix(treesitter): prepare highlight states for [s, ]s 2023-12-19 12:24:06 +01:00
Jaehwang Jung
c0cb1e8e94 perf(treesitter): filter out trees outside the visible range early
Problem:
Treesitter highlighter's on_line was iterating all the parsed trees,
which can be quite a lot when injection is used. This may slow down
scrolling and cursor movement in big files with many comment injections
(e.g., lsp/_meta/protocol.lua).

Solution:
In on_win, collect trees inside the visible range, and use them in
on_line.

NOTE:
This optimization depends on the correctness of on_win's botline_guess
parameter (i.e., it's always greater than or equal to the line numbers
passed to on_line). The documentation does not guarantee this, but I
have never noticed a problem so far.
2023-12-17 15:40:59 +00:00
Jaehwang Jung
6f75facb9d fix(treesitter): improve vim.treesitter.foldexpr
* Collect on_bytes and flush at the invocation of the scheduled callback
  to take account of commands that triggers multiple on_bytes.
* More accurately track movement of folds so that foldexpr returns
  reasonable values even when the scheduled computation is not run yet.
* Start computing folds from the line above (+ foldminlines) the changed
  lines to handle the folds that are removed due to the size limit.
* Shrink folds that end at the line at which another fold starts to
  assign proper level to that line.
* Use level '=' for lines that are not computed yet.
2023-12-12 02:29:59 +09:00
Jaehwang Jung
7c6f9690f7 fix(treesitter): fix indexing in foldexpr 2023-12-12 02:29:59 +09:00
Pham Huy Hoang
f5573fba3d fix: Remove nested for_each_tree in TSTreeView (#26328)
Problem:
`LanguageTree:for_each_tree` calls itself for child nodes, so when we
calls `for_each_tree` inside `for_each_tree`, this quickly leads to
exponential tree calls.

Solution:
Use `pairs(child:trees())` directly in this case, as we don't need the
extra callback for each children, this is already handled from the outer
`for_each_tree` call
2023-11-30 10:37:42 -06:00
Gregory Anders
01b91deec7 fix(treesitter): fix parens stacking in inspector display (#26304)
When first opened, the tree-sitter inspector traverses all of the nodes
in the buffer to calculate an array of nodes. This traversal is done
only once, and _all_ nodes (both named and anonymous) are included.
Toggling anonymous nodes in the inspector only changes how the tree is
drawn in the buffer, but does not affect the underlying data structure
at all.

When the buffer is traversed and the list of nodes is calculated, we
don't know whether or not anonymous nodes will be displayed in the
inspector or not. Thus, we cannot determine during traversal where to
put closing parentheses. Instead, this must be done when drawing.

When we draw, the tree structure has been flatted into a single array,
so we lose parent-child relationships that would otherwise make
determining the number of closing parentheses straightforward. However,
we can instead rely on the fact that a delta between the depth of a node
and the depth of the successive node _must_ mean that more closing
parentheses are required:

  (foo
    (bar)
  (baz)  ↑
         │
         └ (bar) and (baz) have different depths, so (bar) must have an
           extra closing parenthesis

This does not depend on whether or not anonymous nodes are displayed and
so works in both cases.
2023-11-30 07:04:20 -06:00
Gregory Anders
4a8bf24ac6 fix(treesitter): adjust indentation in inspector highlights (#26302) 2023-11-29 10:17:53 -06:00
Gregory Anders
18c1fd8e9d docs: document TSNode:byte_length() (#26287)
Also update the type annotation of TSNode:id(), which returns a string,
not an integer.
2023-11-29 08:59:36 -06:00
Pham Huy Hoang
b6e339eb90 fix(treesitter): make InspectTree correctly handle nested injections (#26085)
Problem: Only injections under the top level tree are found.

Solution: Iterate through all trees to find injections. When two
injections are contained within the same node in the parent tree, prefer
the injection with the larger byte length.
2023-11-29 08:16:52 -06:00
Gregory Anders
7bc5ee7f93 fix(treesitter): use proper query syntax for inspector (#26274) 2023-11-29 08:10:02 -06:00
Dmytro Soltys
72ed99319d fix(treesitter): don't invalidate parser when discovering injections
When parsing with a range, languagetree looks up injections and adds
them if needed. This explicitly invalidates parser, making `is_valid`
report `false` both when including and excluding children.

This is an attempt to describe desired behaviour of `is_valid` in tests,
with what ended up being a single line change to satisfy them.
2023-11-27 15:53:26 +01:00
Maria José Solano
315c711700 fix(treesitter): set cursor position when opening inspector 2023-10-19 14:54:10 +02:00
Pham Huy Hoang
ae7020c667 fix(docs): fix TSNode incorrect signatures 2023-10-19 09:23:13 +01:00
Maria José Solano
3fd7449d5a fix(treesitter): check that buf is loaded in autocommands (#25679) 2023-10-17 15:34:39 -05:00
dundargoc
c3d21ad1bc docs: small fixes
Co-authored-by: Wansmer <wansmer@gmail.com>
Co-authored-by: Andrew Voynov <andrewvoynov.b@gmail.com>
Co-authored-by: David Moberg <david.moberg@mediatek.com>
2023-10-10 19:20:32 +02:00
zeertzjq
3af59a415c fix(treesitter): make Visual hl work consistently with foldtext (#25484)
Problem:  Visual highlight is inconsistent on a folded line with
          treesitter foldtext.
Solution: Don't added Folded highlight as it is already in background.
2023-10-03 13:07:03 +08:00
Till Bungert
9ce1623837 feat(treesitter): add foldtext with treesitter highlighting (#25391) 2023-10-01 14:10:51 -05:00
Maria José Solano
bc0bf9d030 docs: fix type warnings 2023-09-23 23:46:45 +01:00
L Lllvvuu
e353c869ce fix(languagetree): don't treat unparsed nodes as occupying full range
This is incorrect in the following scenario:
1. The language tree is Lua > Vim > Lua.
2. An edit simultaneously wipes out the `_regions` of all nodes, while
   taking the Vim injection off-screen.
3. The Vim injection is not re-parsed, so the child Lua `_regions` is
   still `nil`.
4. The child Lua is assumed, incorrectly, to occupy the whole document.
5. This causes the injections to be parsed again, resulting in Lua > Vim
   > Lua > Vim.
6. Now, by the same process, Vim ends up with its range assumed over the
   whole document. Now the parse is broken and results in broken
   highlighting and poor performance.

It should be fine to instead treat an unparsed node as occupying
nothing (i.e. effectively non-existent). Since, either:
- The parent was just parsed, hence defining `_regions`
- The parent was not just parsed, in which case this node doesn't need
  to be parsed either.

Also, the name `has_regions` is confusing; it seems to simply
mean the opposite of "root" or "full_document". However, this PR does
not touch it.
2023-09-22 12:51:51 +01:00
Lewis Russell
877d04d0fb feat(lua): add vim.func._memoize
Memoizes a function, using a custom function to hash the arguments.

Private for now until:

- There are other places in the codebase that could benefit from this
  (e.g. LSP), but might require other changes to accommodate.
- Invalidation of the cache needs to be controllable. Using weak tables
  is an acceptable invalidation policy, but it shouldn't be the only
  one.
- I don't think the story around `hash_fn` is completely thought out. We
  may be able to have a good default hash_fn by hashing each argument,
  so basically a better 'concat'.
2023-09-20 13:42:41 +01:00
Justin M. Keyes
1b55f51d0d docs: misc #24561
fix #24699
fix #25253
2023-09-20 04:15:23 -07:00
Jaehwang Jung
71d9b7d15c fix(treesitter): _trees may not be list-like
Problem:
With incremental injection parsing, injected languages' parsers parse
only the relevant regions and stores the result in _trees with the index
of the corresponding region. Therefore, there can be holes in _trees.

Solution:
* Use generic table functions where appropriate.
* Fix type annotations and docs.
2023-09-17 19:52:35 +01:00
Maria José Solano
28f54a7878 feat(treesitter): add lang parameter to the query editor (#25181) 2023-09-16 19:05:59 +02:00
Jaehwang Jung
7e5ce42977 fix(treesitter): properly combine injection.combined regions
Problem:
It doesn't make much sense to flatten each region (= list of ranges).
This coincidentally worked for region with a single range.

Solution:
Custom function for combining regions.
2023-09-16 17:02:26 +01:00
Lewis Russell
f40a109716 fix(treesitter): fix trim predicate 2023-09-16 14:24:55 +01:00
L Lllvvuu
07080f67fe perf(treesitter): do not scan past given line for predicate match
Problem
---
If a highlighter query returns a significant number of predicate
non-matches, the highlighter will scan well past the end of the window.

Solution
---
In the iterator returned from `iter_captures`, accept an optional
parameter `end_line`. If no parameter provided, the behavior is
unchanged, hence this is a non-invasive tweak.

Fixes: #25113 nvim-treesitter/nvim-treesitter#5057
2023-09-16 13:52:42 +01:00
L Lllvvuu
908843df61 fix(languagetree): apply resolve_lang to metadata['injection.language']
`resolve_lang` is applied to `@injection.language` when it's supplied as a
capture:

f5953edbac/runtime/lua/vim/treesitter/languagetree.lua (L766-L768)

If we want to support `metadata['injection.language']` (as per #22518 and
[tree-sitter upstream](https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection))
then the behavior should be consistent.

Fixes: nvim-treesitter/nvim-treesitter#4918
2023-09-16 11:12:06 +01:00
Maria José Solano
6debb18523 refactor(treesitter): remove duplicated diagnostic code (#24976)
* refactor(treesitter): remove duplicated diagnostic code

* fixup!: fix type errors

* fixup!: add type namespace
2023-09-15 20:45:40 +01:00
Maria José Solano
28233bcb49 refactor(treesitter): rename "preview" => "edit" #25161
"Edit" more closely describes the generic application than "Preview", though
the buffer contents don't (yet) map to an actual file on disk.

https://github.com/neovim/neovim/pull/24703#discussion_r1321719133
2023-09-15 03:10:55 -07:00