contain template variable errors
This commit is contained in:
1 parent
ccb80972b6
commit
7979890227
5 files changed
+2304
-2201
No files matched your search
@@ -206,7 +206,9 @@ before its scanner token, so `{% else x %}` stays the `else` of its group, `{% e
|
||||
its `if` (it used to leave the whole file an `ERROR`), and `{% static "a.css" "b.css" %}` is a `static_tag`.
|
||||
The node is a run of hidden `_unexpected_word`s, and three details make it work:
|
||||
|
||||
- **Lexical precedence -1.** A loose word is `token(prec(-1, /[^\s%]+/))`. Tree-sitter weighs lexical
|
||||
- **Lexical precedence -1.** A loose word is `token(prec(-1, /(?:[^\s%}]|\}[^\s%}])+/))`, which never holds `}}`:
|
||||
lexer states are shared between parse states, so the token is tried inside `{{ }}` too, and after
|
||||
`{{ x| ` it once swallowed the closing braces and left recovery nothing to close the variable with. Tree-sitter weighs lexical
|
||||
precedence before match length, so a token an argument really takes wins wherever one is valid
|
||||
(`b|upper` stays a filtered value) and a loose word only matches where nothing else can.
|
||||
- **Identifiers are words too.** Wherever a keyword is valid — after `{% for a in b`, where `reversed` may
|
||||
|
||||
+7
-3
@@ -1251,6 +1251,10 @@ const django = grammar({
|
||||
* as an identifier to check for the keyword, so an identifier is a word
|
||||
* here too, followed by whatever touches it ("a=2", "x.y|upper"). It is
|
||||
* aliased so that queries/locals.scm does not take it for a reference.
|
||||
*
|
||||
* A word never holds "}}": tree-sitter shares lexer states between parse
|
||||
* states, so the token is tried inside {{ }} as well, and after "{{ x|" it
|
||||
* would swallow the closing braces and leave recovery nothing to close with.
|
||||
*/
|
||||
_unexpected_word: ($) =>
|
||||
prec.dynamic(
|
||||
@@ -1258,10 +1262,10 @@ const django = grammar({
|
||||
seq(
|
||||
SEP,
|
||||
choice(
|
||||
token(prec(-1, /[^\s%]+/)),
|
||||
token(prec(-1, /(?:[^\s%}]|\}[^\s%}])+/)),
|
||||
seq(
|
||||
alias($.identifier, "unexpected_word"),
|
||||
optional(token.immediate(prec(-1, /[^\s%]+/))),
|
||||
optional(token.immediate(prec(-1, /(?:[^\s%}]|\}[^\s%}])+/))),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -1277,7 +1281,7 @@ const django = grammar({
|
||||
-1,
|
||||
seq(
|
||||
alias($.identifier, "unexpected_word"),
|
||||
token.immediate(prec(-1, /[^\s%]+/)),
|
||||
token.immediate(prec(-1, /(?:[^\s%}]|\}[^\s%}])+/)),
|
||||
),
|
||||
),
|
||||
url_tag: ($) =>
|
||||
|
||||
+3
-3
@@ -7454,7 +7454,7 @@
|
||||
"value": -1,
|
||||
"content": {
|
||||
"type": "PATTERN",
|
||||
"value": "[^\\s%]+"
|
||||
"value": "(?:[^\\s%}]|\\}[^\\s%}])+"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -7480,7 +7480,7 @@
|
||||
"value": -1,
|
||||
"content": {
|
||||
"type": "PATTERN",
|
||||
"value": "[^\\s%]+"
|
||||
"value": "(?:[^\\s%}]|\\}[^\\s%}])+"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -7518,7 +7518,7 @@
|
||||
"value": -1,
|
||||
"content": {
|
||||
"type": "PATTERN",
|
||||
"value": "[^\\s%]+"
|
||||
"value": "(?:[^\\s%}]|\\}[^\\s%}])+"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2253
-2194
File diff suppressed because it is too large.
Load diff
@@ -608,3 +608,41 @@ a{{{ x }}
|
||||
---
|
||||
|
||||
|
||||
|
||||
==================
|
||||
A Filter Pipe With No Filter Stays In Its Variable
|
||||
==================
|
||||
|
||||
{{ oops| }}
|
||||
{% if x == 1 %}
|
||||
hello
|
||||
{% endif %}
|
||||
|
||||
---
|
||||
|
||||
(template
|
||||
(content)
|
||||
(template_variable
|
||||
(filtered_value
|
||||
(value
|
||||
(variable_attribute
|
||||
(identifier))))
|
||||
(ERROR))
|
||||
(content)
|
||||
(if_group
|
||||
(if_block
|
||||
(if_tag
|
||||
(predicate
|
||||
(filtered_value
|
||||
(value
|
||||
(variable_attribute
|
||||
(identifier))))
|
||||
(binaryOperator)
|
||||
(filtered_value
|
||||
(value
|
||||
(literal
|
||||
(number))))))
|
||||
(template
|
||||
(content)))
|
||||
(endif_tag))
|
||||
(content))
|
||||
Reference in new issue
Block a user