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`.
|
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:
|
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
|
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.
|
(`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
|
- **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
|
* 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
|
* 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.
|
* 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: ($) =>
|
_unexpected_word: ($) =>
|
||||||
prec.dynamic(
|
prec.dynamic(
|
||||||
@@ -1258,10 +1262,10 @@ const django = grammar({
|
|||||||
seq(
|
seq(
|
||||||
SEP,
|
SEP,
|
||||||
choice(
|
choice(
|
||||||
token(prec(-1, /[^\s%]+/)),
|
token(prec(-1, /(?:[^\s%}]|\}[^\s%}])+/)),
|
||||||
seq(
|
seq(
|
||||||
alias($.identifier, "unexpected_word"),
|
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,
|
-1,
|
||||||
seq(
|
seq(
|
||||||
alias($.identifier, "unexpected_word"),
|
alias($.identifier, "unexpected_word"),
|
||||||
token.immediate(prec(-1, /[^\s%]+/)),
|
token.immediate(prec(-1, /(?:[^\s%}]|\}[^\s%}])+/)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
url_tag: ($) =>
|
url_tag: ($) =>
|
||||||
|
|||||||
+3
-3
@@ -7454,7 +7454,7 @@
|
|||||||
"value": -1,
|
"value": -1,
|
||||||
"content": {
|
"content": {
|
||||||
"type": "PATTERN",
|
"type": "PATTERN",
|
||||||
"value": "[^\\s%]+"
|
"value": "(?:[^\\s%}]|\\}[^\\s%}])+"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -7480,7 +7480,7 @@
|
|||||||
"value": -1,
|
"value": -1,
|
||||||
"content": {
|
"content": {
|
||||||
"type": "PATTERN",
|
"type": "PATTERN",
|
||||||
"value": "[^\\s%]+"
|
"value": "(?:[^\\s%}]|\\}[^\\s%}])+"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -7518,7 +7518,7 @@
|
|||||||
"value": -1,
|
"value": -1,
|
||||||
"content": {
|
"content": {
|
||||||
"type": "PATTERN",
|
"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