Merge commit '5720b249490b3c17245ba772f6be4a43edb4e3b7'

pull/502/head
Wilfred Hughes 2023-03-17 00:12:56 +07:00
commit e24ca47173
19 changed files with 50207 additions and 44530 deletions

@ -9,7 +9,7 @@ Added support for Ada.
Improved parsing for TOML.
Updated grammars for Bash, C, C++, C#, Clojure, CMake, Elixir, Go,
Java and OCaml.
Java, JavaScript and OCaml.
Difftastic now prefers treating files as 'mostly UTF-8' or binary rather than
UTF-16. Many files can be decoded as UTF-16 without decoding errors

@ -12,19 +12,19 @@ jobs:
matrix:
os: [macos-latest, ubuntu-latest]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 14
node-version: 18
- run: npm install
- run: npm test
test_windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 14
node-version: 18
- run: npm install
- run: npm run-script test-windows

@ -0,0 +1,33 @@
name: Publish on crates.io
on:
push:
tags:
- v*
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install Rust stable
run: |
rustup toolchain install stable --profile minimal --no-self-update
- name: Verify publish crate
uses: katyo/publish-crates@v1
with:
dry-run: true
- name: Publish crate
uses: katyo/publish-crates@v1
with:
registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}

@ -7,3 +7,4 @@ build
/examples/npm
package-lock.json
/target/
.build/

@ -0,0 +1,38 @@
// swift-tools-version:5.3
import PackageDescription
let package = Package(
name: "TreeSitterJS",
products: [
.library(name: "TreeSitterJS", targets: ["TreeSitterJS"]),
],
dependencies: [],
targets: [
.target(name: "TreeSitterJS",
path: ".",
exclude: [
"binding.gyp",
"bindings",
"Cargo.toml",
"corpus",
"grammar.js",
"LICENSE",
"Makefile",
"package.json",
"README.md",
"script",
"src/grammar.json",
"src/node-types.json",
"*.wasm",
],
sources: [
"src/parser.c",
"src/scanner.c",
],
resources: [
.copy("queries")
],
publicHeadersPath: "bindings/swift",
cSettings: [.headerSearchPath("src")])
]
)

@ -0,0 +1,16 @@
#ifndef TREE_SITTER_JAVASCRIPT_H_
#define TREE_SITTER_JAVASCRIPT_H_
typedef struct TSLanguage TSLanguage;
#ifdef __cplusplus
extern "C" {
#endif
extern TSLanguage *tree_sitter_javascript();
#ifdef __cplusplus
}
#endif
#endif // TREE_SITTER_JAVASCRIPT_H_

@ -103,11 +103,12 @@ module.exports = grammar({
seq(
'export',
choice(
seq('*', $._from_clause, $._semicolon),
seq(alias($.namespace_import_export, $.namespace_export), $._from_clause, $._semicolon),
seq($.export_clause, $._from_clause, $._semicolon),
seq($.export_clause, $._semicolon)
)
seq('*', $._from_clause),
seq($.namespace_export, $._from_clause),
seq($.export_clause, $._from_clause),
$.export_clause,
),
$._semicolon,
),
seq(
repeat(field('decorator', $.decorator)),
@ -128,21 +129,30 @@ module.exports = grammar({
)
),
namespace_export: $ => seq(
'*', 'as', $._module_export_name
),
export_clause: $ => seq(
'{',
commaSep(alias($._import_export_specifier, $.export_specifier)),
commaSep($.export_specifier),
optional(','),
'}'
),
_import_export_specifier: $ => seq(
field('name', $.identifier),
export_specifier: $ => seq(
field('name', $._module_export_name),
optional(seq(
'as',
field('alias', $.identifier)
field('alias', $._module_export_name)
))
),
_module_export_name: $ => choice(
$.identifier,
$.string,
),
declaration: $ => choice(
$.function_declaration,
$.generator_function_declaration,
@ -167,14 +177,14 @@ module.exports = grammar({
),
import_clause: $ => choice(
alias($.namespace_import_export, $.namespace_import),
$.namespace_import,
$.named_imports,
seq(
$.identifier,
optional(seq(
',',
choice(
alias($.namespace_import_export, $.namespace_import),
$.namespace_import,
$.named_imports
)
))
@ -185,17 +195,26 @@ module.exports = grammar({
"from", field('source', $.string)
),
namespace_import_export: $ => seq(
namespace_import: $ => seq(
"*", "as", $.identifier
),
named_imports: $ => seq(
'{',
commaSep(alias($._import_export_specifier, $.import_specifier)),
commaSep($.import_specifier),
optional(','),
'}'
),
import_specifier: $ => choice(
field('name', $.identifier),
seq(
field('name', $._module_export_name),
'as',
field('alias', $.identifier)
),
),
//
// Statements
//
@ -436,6 +455,7 @@ module.exports = grammar({
expression: $ => choice(
$.primary_expression,
$.glimmer_template,
$._jsx_element,
$.jsx_fragment,
$.assignment_expression,
@ -543,6 +563,24 @@ module.exports = grammar({
']'
),
glimmer_template: $ => choice(
seq(
field('open_tag', $.glimmer_opening_tag),
field('content', repeat($._glimmer_template_content)),
field('close_tag', $.glimmer_closing_tag),
),
// empty template has no content
// <template></template>
seq(
field('open_tag', $.glimmer_opening_tag),
field('close_tag', $.glimmer_closing_tag),
),
),
_glimmer_template_content: $ => /.{1,}/,
glimmer_opening_tag: $ => seq('<template>'),
glimmer_closing_tag: $ => seq('</template>'),
_jsx_element: $ => choice($.jsx_element, $.jsx_self_closing_element),
jsx_element: $ => seq(
@ -709,6 +747,8 @@ module.exports = grammar({
_call_signature: $ => field('parameters', $.formal_parameters),
_formal_parameter: $ => choice($.pattern, $.assignment_pattern),
optional_chain: $ => '?.',
call_expression: $ => choice(
prec('call', seq(
field('function', $.expression),
@ -716,7 +756,7 @@ module.exports = grammar({
)),
prec('member', seq(
field('function', $.primary_expression),
'?.',
field('optional_chain', $.optional_chain),
field('arguments', $.arguments)
))
),
@ -734,7 +774,7 @@ module.exports = grammar({
member_expression: $ => prec('member', seq(
field('object', choice($.expression, $.primary_expression)),
choice('.', '?.'),
choice('.', field('optional_chain', $.optional_chain)),
field('property', choice(
$.private_property_identifier,
alias($.identifier, $.property_identifier)))
@ -742,7 +782,7 @@ module.exports = grammar({
subscript_expression: $ => prec.right('member', seq(
field('object', choice($.expression, $.primary_expression)),
optional('?.'),
optional(field('optional_chain', $.optional_chain)),
'[', field('index', $._expressions), ']'
)),
@ -810,7 +850,7 @@ module.exports = grammar({
['*', 'binary_times'],
['/', 'binary_times'],
['%', 'binary_times'],
['**', 'binary_exp'],
['**', 'binary_exp', 'right'],
['<', 'binary_relation'],
['<=', 'binary_relation'],
['==', 'binary_equality'],
@ -822,8 +862,8 @@ module.exports = grammar({
['??', 'ternary'],
['instanceof', 'binary_relation'],
['in', 'binary_relation'],
].map(([operator, precedence]) =>
prec.left(precedence, seq(
].map(([operator, precedence, associativity]) =>
(associativity === 'right' ? prec.right : prec.left)(precedence, seq(
field('left', $.expression),
field('operator', operator),
field('right', $.expression)
@ -911,7 +951,18 @@ module.exports = grammar({
'/*',
/[^*]*\*+([^/*][^*]*\*+)*/,
'/'
)
),
// https://tc39.es/ecma262/#sec-html-like-comments
seq('<!--', /.*/),
// This allows code to exist before this token on the same line.
//
// Technically, --> is supposed to have nothing before it on the same line
// except for comments and whitespace, but that is difficult to express,
// and in general tree sitter grammars tend to prefer to be overly
// permissive anyway.
//
// This approach does not appear to cause problems in practice.
seq('-->', /.*/)
)),
template_string: $ => seq(
@ -1062,7 +1113,9 @@ module.exports = grammar({
'{',
repeat(choice(
seq(field('member', $.method_definition), optional(';')),
seq(field('member', $.field_definition), $._semicolon)
seq(field('member', $.field_definition), $._semicolon),
field('member', $.class_static_block),
field('template', $.glimmer_template)
)),
'}'
),
@ -1083,6 +1136,11 @@ module.exports = grammar({
')'
),
class_static_block: $ => seq(
'static',
field('body', $.statement_block)
),
// This negative dynamic precedence ensures that during error recovery,
// unfinished constructs are generally treated as literal expressions,
// not patterns.

@ -99,7 +99,7 @@
[
";"
"?."
(optional_chain)
"."
","
] @punctuation.delimiter

@ -18,3 +18,15 @@
((comment) @injection.content
(#set! injection.language "jsdoc"))
; Parse Ember/Glimmer/Handlebars/HTMLBars/etc. template literals
; e.g.: await render(hbs`<SomeComponent />`)
(call_expression
function: ((identifier) @_name
(#eq? @_name "hbs"))
arguments: ((template_string) @glimmer
(#offset! @glimmer 0 1 0 -1)))
; Ember Unified <template> syntax
; e.g.: <template><SomeComponent @arg={{double @value}} /></template>
((glimmer_template) @glimmer)

@ -86,3 +86,14 @@
(new_expression
constructor: (_) @name) @reference.class
(export_statement value: (assignment_expression left: (identifier) @name right: ([
(number)
(string)
(identifier)
(undefined)
(null)
(new_expression)
(binary_expression)
(call_expression)
]))) @definition.constant

@ -53,32 +53,19 @@
{
"type": "SYMBOL",
"name": "_from_clause"
},
{
"type": "SYMBOL",
"name": "_semicolon"
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "namespace_import_export"
},
"named": true,
"value": "namespace_export"
},
{
"type": "SYMBOL",
"name": "_from_clause"
"name": "namespace_export"
},
{
"type": "SYMBOL",
"name": "_semicolon"
"name": "_from_clause"
}
]
},
@ -92,27 +79,18 @@
{
"type": "SYMBOL",
"name": "_from_clause"
},
{
"type": "SYMBOL",
"name": "_semicolon"
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "export_clause"
},
{
"type": "SYMBOL",
"name": "_semicolon"
}
]
"type": "SYMBOL",
"name": "export_clause"
}
]
},
{
"type": "SYMBOL",
"name": "_semicolon"
}
]
},
@ -190,6 +168,23 @@
}
]
},
"namespace_export": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "*"
},
{
"type": "STRING",
"value": "as"
},
{
"type": "SYMBOL",
"name": "_module_export_name"
}
]
},
"export_clause": {
"type": "SEQ",
"members": [
@ -204,13 +199,8 @@
"type": "SEQ",
"members": [
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "_import_export_specifier"
},
"named": true,
"value": "export_specifier"
"type": "SYMBOL",
"name": "export_specifier"
},
{
"type": "REPEAT",
@ -222,13 +212,8 @@
"value": ","
},
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "_import_export_specifier"
},
"named": true,
"value": "export_specifier"
"type": "SYMBOL",
"name": "export_specifier"
}
]
}
@ -258,7 +243,7 @@
}
]
},
"_import_export_specifier": {
"export_specifier": {
"type": "SEQ",
"members": [
{
@ -266,7 +251,7 @@
"name": "name",
"content": {
"type": "SYMBOL",
"name": "identifier"
"name": "_module_export_name"
}
},
{
@ -284,7 +269,7 @@
"name": "alias",
"content": {
"type": "SYMBOL",
"name": "identifier"
"name": "_module_export_name"
}
}
]
@ -296,6 +281,19 @@
}
]
},
"_module_export_name": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "SYMBOL",
"name": "string"
}
]
},
"declaration": {
"type": "CHOICE",
"members": [
@ -371,13 +369,8 @@
"type": "CHOICE",
"members": [
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "namespace_import_export"
},
"named": true,
"value": "namespace_import"
"type": "SYMBOL",
"name": "namespace_import"
},
{
"type": "SYMBOL",
@ -404,13 +397,8 @@
"type": "CHOICE",
"members": [
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "namespace_import_export"
},
"named": true,
"value": "namespace_import"
"type": "SYMBOL",
"name": "namespace_import"
},
{
"type": "SYMBOL",
@ -446,7 +434,7 @@
}
]
},
"namespace_import_export": {
"namespace_import": {
"type": "SEQ",
"members": [
{
@ -477,13 +465,8 @@
"type": "SEQ",
"members": [
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "_import_export_specifier"
},
"named": true,
"value": "import_specifier"
"type": "SYMBOL",
"name": "import_specifier"
},
{
"type": "REPEAT",
@ -495,13 +478,8 @@
"value": ","
},
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "_import_export_specifier"
},
"named": true,
"value": "import_specifier"
"type": "SYMBOL",
"name": "import_specifier"
}
]
}
@ -531,6 +509,44 @@
}
]
},
"import_specifier": {
"type": "CHOICE",
"members": [
{
"type": "FIELD",
"name": "name",
"content": {
"type": "SYMBOL",
"name": "identifier"
}
},
{
"type": "SEQ",
"members": [
{
"type": "FIELD",
"name": "name",
"content": {
"type": "SYMBOL",
"name": "_module_export_name"
}
},
{
"type": "STRING",
"value": "as"
},
{
"type": "FIELD",
"name": "alias",
"content": {
"type": "SYMBOL",
"name": "identifier"
}
}
]
}
]
},
"statement": {
"type": "CHOICE",
"members": [
@ -1624,6 +1640,10 @@
"type": "SYMBOL",
"name": "primary_expression"
},
{
"type": "SYMBOL",
"name": "glimmer_template"
},
{
"type": "SYMBOL",
"name": "_jsx_element"
@ -2304,6 +2324,86 @@
}
]
},
"glimmer_template": {
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "FIELD",
"name": "open_tag",
"content": {
"type": "SYMBOL",
"name": "glimmer_opening_tag"
}
},
{
"type": "FIELD",
"name": "content",
"content": {
"type": "REPEAT",
"content": {
"type": "SYMBOL",
"name": "_glimmer_template_content"
}
}
},
{
"type": "FIELD",
"name": "close_tag",
"content": {
"type": "SYMBOL",
"name": "glimmer_closing_tag"
}
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "FIELD",
"name": "open_tag",
"content": {
"type": "SYMBOL",
"name": "glimmer_opening_tag"
}
},
{
"type": "FIELD",
"name": "close_tag",
"content": {
"type": "SYMBOL",
"name": "glimmer_closing_tag"
}
}
]
}
]
},
"_glimmer_template_content": {
"type": "PATTERN",
"value": ".{1,}"
},
"glimmer_opening_tag": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "<template>"
}
]
},
"glimmer_closing_tag": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "</template>"
}
]
},
"_jsx_element": {
"type": "CHOICE",
"members": [
@ -3160,6 +3260,10 @@
}
]
},
"optional_chain": {
"type": "STRING",
"value": "?."
},
"call_expression": {
"type": "CHOICE",
"members": [
@ -3212,8 +3316,12 @@
}
},
{
"type": "STRING",
"value": "?."
"type": "FIELD",
"name": "optional_chain",
"content": {
"type": "SYMBOL",
"name": "optional_chain"
}
},
{
"type": "FIELD",
@ -3326,8 +3434,12 @@
"value": "."
},
{
"type": "STRING",
"value": "?."
"type": "FIELD",
"name": "optional_chain",
"content": {
"type": "SYMBOL",
"name": "optional_chain"
}
}
]
},
@ -3383,8 +3495,12 @@
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "?."
"type": "FIELD",
"name": "optional_chain",
"content": {
"type": "SYMBOL",
"name": "optional_chain"
}
},
{
"type": "BLANK"
@ -4124,7 +4240,7 @@
}
},
{
"type": "PREC_LEFT",
"type": "PREC_RIGHT",
"value": "binary_exp",
"content": {
"type": "SEQ",
@ -4844,6 +4960,32 @@
"value": "/"
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "<!--"
},
{
"type": "PATTERN",
"value": ".*"
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "-->"
},
{
"type": "PATTERN",
"value": ".*"
}
]
}
]
}
@ -5856,6 +5998,22 @@
"name": "_semicolon"
}
]
},
{
"type": "FIELD",
"name": "member",
"content": {
"type": "SYMBOL",
"name": "class_static_block"
}
},
{
"type": "FIELD",
"name": "template",
"content": {
"type": "SYMBOL",
"name": "glimmer_template"
}
}
]
}
@ -5977,6 +6135,23 @@
}
]
},
"class_static_block": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "static"
},
{
"type": "FIELD",
"name": "body",
"content": {
"type": "SYMBOL",
"name": "statement_block"
}
}
]
},
"pattern": {
"type": "PREC_DYNAMIC",
"value": -1,

@ -45,6 +45,10 @@
"type": "binary_expression",
"named": true
},
{
"type": "glimmer_template",
"named": true
},
{
"type": "jsx_element",
"named": true
@ -768,6 +772,16 @@
"named": true
}
]
},
"optional_chain": {
"multiple": false,
"required": false,
"types": [
{
"type": "optional_chain",
"named": true
}
]
}
}
},
@ -859,6 +873,10 @@
"multiple": true,
"required": false,
"types": [
{
"type": "class_static_block",
"named": true
},
{
"type": "field_definition",
"named": true
@ -868,6 +886,16 @@
"named": true
}
]
},
"template": {
"multiple": true,
"required": false,
"types": [
{
"type": "glimmer_template",
"named": true
}
]
}
}
},
@ -932,6 +960,22 @@
]
}
},
{
"type": "class_static_block",
"named": true,
"fields": {
"body": {
"multiple": false,
"required": true,
"types": [
{
"type": "statement_block",
"named": true
}
]
}
}
},
{
"type": "computed_property_name",
"named": true,
@ -1063,6 +1107,10 @@
{
"type": "identifier",
"named": true
},
{
"type": "string",
"named": true
}
]
},
@ -1073,6 +1121,10 @@
{
"type": "identifier",
"named": true
},
{
"type": "string",
"named": true
}
]
}
@ -1560,6 +1612,42 @@
}
}
},
{
"type": "glimmer_closing_tag",
"named": true,
"fields": {}
},
{
"type": "glimmer_opening_tag",
"named": true,
"fields": {}
},
{
"type": "glimmer_template",
"named": true,
"fields": {
"close_tag": {
"multiple": false,
"required": true,
"types": [
{
"type": "glimmer_closing_tag",
"named": true
}
]
},
"open_tag": {
"multiple": false,
"required": true,
"types": [
{
"type": "glimmer_opening_tag",
"named": true
}
]
}
}
},
{
"type": "if_statement",
"named": true,
@ -1645,6 +1733,10 @@
{
"type": "identifier",
"named": true
},
{
"type": "string",
"named": true
}
]
}
@ -2006,6 +2098,16 @@
}
]
},
"optional_chain": {
"multiple": false,
"required": false,
"types": [
{
"type": "optional_chain",
"named": true
}
]
},
"property": {
"multiple": false,
"required": true,
@ -2115,6 +2217,10 @@
{
"type": "identifier",
"named": true
},
{
"type": "string",
"named": true
}
]
}
@ -2583,6 +2689,16 @@
"named": true
}
]
},
"optional_chain": {
"multiple": false,
"required": false,
"types": [
{
"type": "optional_chain",
"named": true
}
]
}
}
},
@ -3130,6 +3246,10 @@
"type": "<",
"named": false
},
{
"type": "</template>",
"named": false
},
{
"type": "<<",
"named": false
@ -3142,6 +3262,10 @@
"type": "<=",
"named": false
},
{
"type": "<template>",
"named": false
},
{
"type": "=",
"named": false
@ -3186,10 +3310,6 @@
"type": "?",
"named": false
},
{
"type": "?.",
"named": false
},
{
"type": "??",
"named": false
@ -3366,6 +3486,10 @@
"type": "of",
"named": false
},
{
"type": "optional_chain",
"named": true
},
{
"type": "private_property_identifier",
"named": true

File diff suppressed because it is too large Load Diff

@ -123,6 +123,7 @@ struct TSLanguage {
unsigned (*serialize)(void *, char *);
void (*deserialize)(void *, const char *, unsigned);
} external_scanner;
const TSStateId *primary_state_ids;
};
/*

@ -360,6 +360,10 @@ class Foo extends require('another-class') {
super()
}
static {
this.#foo = 'bar';
}
bar() {
super.a()
this.#baz()
@ -403,6 +407,15 @@ class Foo extends require('another-class') {
(formal_parameters)
(statement_block
(expression_statement (call_expression (super) (arguments)))))
(class_static_block
(statement_block
(expression_statement
(assignment_expression
(member_expression
(this)
(private_property_identifier))
(string
(string_fragment))))))
(method_definition
(property_identifier)
(formal_parameters)
@ -767,7 +780,7 @@ a ?. b;
(expression_statement
(member_expression (identifier) (property_identifier)))
(expression_statement
(member_expression (identifier) (property_identifier))))
(member_expression (identifier) (optional_chain) (property_identifier))))
============================================
Optional chaining array access
@ -782,7 +795,7 @@ a ?. [b];
(expression_statement
(subscript_expression (identifier) (identifier)))
(expression_statement
(subscript_expression (identifier) (identifier))))
(subscript_expression (identifier) (optional_chain) (identifier))))
============================================
Optional function calls
@ -796,14 +809,16 @@ d.e?.(f);
(program
(expression_statement
(call_expression (identifier) (arguments (identifier))))
(call_expression (identifier) (optional_chain) (arguments (identifier))))
(expression_statement
(call_expression
(subscript_expression (identifier) (identifier))
(optional_chain)
(arguments (identifier))))
(expression_statement
(call_expression
(member_expression (identifier) (property_identifier))
(optional_chain)
(arguments (identifier)))))
============================================
@ -902,6 +917,7 @@ i--;
i + j * 3 - j % 5;
2 ** i * 3;
2 * i ** 3;
2 ** i ** 3;
+x;
-x;
@ -921,6 +937,9 @@ i + j * 3 - j % 5;
(expression_statement (binary_expression
(number)
(binary_expression (identifier) (number))))
(expression_statement (binary_expression
(number)
(binary_expression (identifier) (number))))
(expression_statement (unary_expression (identifier)))
(expression_statement (unary_expression (identifier))))

@ -0,0 +1,136 @@
============================================
Simple
============================================
const Named = <template>
{{ (doubled foo) }}
</template>
----
(program
(lexical_declaration
(variable_declarator
(identifier)
(glimmer_template
(glimmer_opening_tag)
(glimmer_closing_tag)))))
============================================
Empty
============================================
<template></template>
----
(program
(expression_statement
(glimmer_template
(glimmer_opening_tag)
(glimmer_closing_tag))))
============================================
Two Components
============================================
const WithSemi = <template>
{{ (doubled foo) }}
</template>;
<template>
<WithSemi />
</template>;
----
(program
(lexical_declaration
(variable_declarator
(identifier)
(glimmer_template
(glimmer_opening_tag)
(glimmer_closing_tag))))
(expression_statement
(glimmer_template
(glimmer_opening_tag)
(glimmer_closing_tag))))
============================================
Multiple Assignment
============================================
const Empty = <template></template>
const WithSemi = <template>
<Empty />
{{ (doubled foo) }}
</template>;
<template>
<WithSemi />
</template>;
----
(program
(lexical_declaration
(variable_declarator
(identifier)
(glimmer_template
(glimmer_opening_tag)
(glimmer_closing_tag))))
(lexical_declaration
(variable_declarator
(identifier)
(glimmer_template
(glimmer_opening_tag)
(glimmer_closing_tag))))
(expression_statement
(glimmer_template
(glimmer_opening_tag)
(glimmer_closing_tag))))
============================================
Class Component
============================================
class InClass {
<template>
{{this.whatever}}
</template>
}
----
(program
(class_declaration
(identifier)
(class_body
(glimmer_template
(glimmer_opening_tag)
(glimmer_closing_tag)))))
============================================
JS Regex Evasion
============================================
<template>
{{#if true}}
{{/if}}
</template>
----
(program
(expression_statement
(glimmer_template
(glimmer_opening_tag)
(glimmer_closing_tag)
)))

@ -0,0 +1,43 @@
============================================
JSDoc
============================================
/*
* @return {void}
*/
function foo() {}
----
(program
(comment)
(function_declaration
(identifier)
(formal_parameters)
(statement_block)))
============================================
JSX
============================================
const foo = 2;
<div>{{foo}}</div>
----
(program
(lexical_declaration
(variable_declarator
(identifier)
(number)))
(expression_statement
(jsx_element
(jsx_opening_element
(identifier))
(jsx_expression
(object
(shorthand_property_identifier)))
(jsx_closing_element
(identifier)))))

@ -41,6 +41,7 @@ import * as name from "module-name";
import { member } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 } from "module-name";
import { "string name" as alias } from "module-name";
import defaultMember, { member1, member2 as alias2 } from "module-name";
import defaultMember, * as name from "module-name";
import "module-name";
@ -62,6 +63,8 @@ import.meta.url;
(import_clause (named_imports (import_specifier (identifier)) (import_specifier (identifier)))) (string (string_fragment)))
(import_statement
(import_clause (named_imports (import_specifier (identifier)) (import_specifier (identifier) (identifier)))) (string (string_fragment)))
(import_statement
(import_clause (named_imports (import_specifier (string (string_fragment)) (identifier)))) (string (string_fragment)))
(import_statement
(import_clause (identifier) (named_imports (import_specifier (identifier)) (import_specifier (identifier) (identifier)))) (string (string_fragment)))
(import_statement
@ -95,6 +98,7 @@ Exports
export { name1, name2, name3, nameN };
export { variable1 as name1, variable2 as name2, nameN };
export { variable1 as "string name" };
export let name1, name2, nameN;
export let name1 = value1, name2 = value2, name3, nameN;
@ -106,8 +110,11 @@ export { name1 as default };
export * from 'foo';
export * as someIdentifier from "someModule";
export * as "string name" from "someModule";
export { name1, name2, nameN } from 'foo';
export { import1 as name1, import2 as name2, nameN } from 'foo';
export { import1 as "string name" } from 'foo';
export { "string import" as "string export" } from 'foo';
----
@ -123,6 +130,9 @@ export { import1 as name1, import2 as name2, nameN } from 'foo';
(export_specifier name: (identifier) alias: (identifier))
(export_specifier name: (identifier) alias: (identifier))
(export_specifier name: (identifier))))
(export_statement
(export_clause
(export_specifier name: (identifier) alias: (string (string_fragment)))))
(export_statement
declaration: (lexical_declaration
(variable_declarator name: (identifier))
@ -151,6 +161,9 @@ export { import1 as name1, import2 as name2, nameN } from 'foo';
(export_statement
(namespace_export (identifier))
source: (string (string_fragment)))
(export_statement
(namespace_export (string (string_fragment)))
source: (string (string_fragment)))
(export_statement
(export_clause
(export_specifier name: (identifier))
@ -162,6 +175,14 @@ export { import1 as name1, import2 as name2, nameN } from 'foo';
(export_specifier name: (identifier) alias: (identifier))
(export_specifier name: (identifier) alias: (identifier))
(export_specifier name: (identifier)))
source: (string (string_fragment)))
(export_statement
(export_clause
(export_specifier name: (identifier) alias: (string (string_fragment))))
source: (string (string_fragment)))
(export_statement
(export_clause
(export_specifier name: (string (string_fragment)) alias: (string (string_fragment))))
source: (string (string_fragment))))
============================================
@ -627,6 +648,40 @@ y // comment
(program (expression_statement
(binary_expression (identifier) (comment) (identifier))))
==========================================
HTML Comments
==========================================
<!-- we can put whatever we like here. this affects one line only.
y * z;
<!-- and here as well. these do not have to have matching close comments.
x + 1; --> for some reason you can put text after a close comment.
--> note that the x + 1 above should be rejected according to the spec.
--> it should instead be rejected as invalid.
--> you are supposed to only have whitespace or comments before
--> an HTML close comment.
---
(program
(comment)
(expression_statement
(binary_expression
(identifier)
(identifier)))
(comment)
(expression_statement
(binary_expression
(identifier)
(number)))
(comment)
(comment)
(comment)
(comment)
(comment))
============================================
Switch statements
============================================