diff options
author | A-Walrus | 2022-08-05 00:12:14 +0000 |
---|---|---|
committer | GitHub | 2022-08-05 00:12:14 +0000 |
commit | cfa882557eb24cf0bed0485d0811d3f35832ba4b (patch) | |
tree | 5470412f52a7c79e37e1f827e3b8e36ebd88864b /helix-core/src | |
parent | f32c05db857c61fddb45b66d2ca1de2bd70b7db2 (diff) |
Fix nondeterministic highlighting (#3275)
* Fix nondeterministic highlighting
This is done by prefering matches in the begining, ie for
`keyword.function`, `keyword` is a better match than `function`.
* Use all positions and not just leftmost
Fixes possible edgecase with something like `function.method.builtin`
and the queries `function.builtin` and `function.method`
* Switch to bitmask for slightly better performance
* Make matches from the start of string
Also change comments to match new behaviour
Diffstat (limited to 'helix-core/src')
-rw-r--r-- | helix-core/src/syntax.rs | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs index 4188d148..99922d37 100644 --- a/helix-core/src/syntax.rs +++ b/helix-core/src/syntax.rs @@ -1356,8 +1356,8 @@ impl HighlightConfiguration { /// Tree-sitter syntax-highlighting queries specify highlights in the form of dot-separated /// highlight names like `punctuation.bracket` and `function.method.builtin`. Consumers of /// these queries can choose to recognize highlights with different levels of specificity. - /// For example, the string `function.builtin` will match against `function.method.builtin` - /// and `function.builtin.constructor`, but will not match `function.method`. + /// For example, the string `function.builtin` will match against `function.builtin.constructor` + /// but will not match `function.method.builtin` and `function.method`. /// /// When highlighting, results are returned as `Highlight` values, which contain the index /// of the matched highlight this list of highlight names. @@ -1377,11 +1377,13 @@ impl HighlightConfiguration { let recognized_name = recognized_name; let mut len = 0; let mut matches = true; - for part in recognized_name.split('.') { - len += 1; - if !capture_parts.contains(&part) { - matches = false; - break; + for (i, part) in recognized_name.split('.').enumerate() { + match capture_parts.get(i) { + Some(capture_part) if *capture_part == part => len += 1, + _ => { + matches = false; + break; + } } } if matches && len > best_match_len { |