Merged PR #758
This commit is contained in:
Generated
+1
-3
@@ -2180,7 +2180,6 @@ dependencies = [
|
||||
"ast-grep-core",
|
||||
"brush-builtins",
|
||||
"brush-core",
|
||||
"cc",
|
||||
"clap",
|
||||
"dashmap",
|
||||
"globset",
|
||||
@@ -3262,8 +3261,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tree-sitter-glimmer"
|
||||
version = "0.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "295346943475457f55688342f14675e2a54ba3e8f3d224f11d10477d99e70330"
|
||||
source = "git+https://github.com/ember-tooling/tree-sitter-glimmer?tag=v1.6.0-tree-sitter-glimmer#88af85568bde3b91acb5d4c352ed094d0c1f9d84"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"tree-sitter",
|
||||
|
||||
@@ -13,6 +13,7 @@ repository = "https://github.com/can1357/oh-my-pi"
|
||||
[patch.crates-io]
|
||||
brush-core = { path = "crates/brush-core-vendored" }
|
||||
brush-builtins = { path = "crates/brush-builtins-vendored" }
|
||||
tree-sitter-glimmer = { git = "https://github.com/ember-tooling/tree-sitter-glimmer", tag = "v1.6.0-tree-sitter-glimmer" }
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
lto = "fat"
|
||||
|
||||
@@ -138,6 +138,5 @@ windows-sys = { version = "0.61", features = [
|
||||
] }
|
||||
[build-dependencies]
|
||||
napi-build = "2"
|
||||
cc = "1"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
||||
+162
-33
@@ -31,6 +31,11 @@ struct GrammarSpec {
|
||||
node_types_rel: &'static str,
|
||||
}
|
||||
|
||||
struct LockedPackage {
|
||||
version: String,
|
||||
source: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct RawTypeRef {
|
||||
#[serde(rename = "type")]
|
||||
@@ -361,27 +366,6 @@ const GRAMMARS: &[GrammarSpec] = &[
|
||||
fn main() {
|
||||
napi_build::setup();
|
||||
generate_chunk_schema();
|
||||
|
||||
let scanner_dir = Path::new("vendor/tree-sitter-glimmer");
|
||||
let scanner_path = scanner_dir.join("scanner.c");
|
||||
let parser_header_path = scanner_dir.join("parser.h");
|
||||
|
||||
println!("cargo:rerun-if-changed={}", scanner_path.display());
|
||||
println!("cargo:rerun-if-changed={}", parser_header_path.display());
|
||||
|
||||
let mut build = cc::Build::new();
|
||||
build
|
||||
.std("c11")
|
||||
.include(scanner_dir)
|
||||
.file(&scanner_path)
|
||||
// Vendored code: suppress warnings (including the ar -D probe noise on
|
||||
// macOS where Apple's ar rejects the deterministic flag).
|
||||
.cargo_warnings(false);
|
||||
|
||||
#[cfg(target_env = "msvc")]
|
||||
build.flag("-utf-8");
|
||||
|
||||
build.compile("tree-sitter-glimmer-scanner");
|
||||
}
|
||||
|
||||
fn generate_chunk_schema() {
|
||||
@@ -392,15 +376,17 @@ fn generate_chunk_schema() {
|
||||
.expect("pi-natives should live under the workspace root");
|
||||
let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR should be set"));
|
||||
let output_path = out_dir.join("chunk_schema.json");
|
||||
let locked_versions = locked_package_versions(&workspace_root.join("Cargo.lock"));
|
||||
let locked_packages = locked_packages(&workspace_root.join("Cargo.lock"));
|
||||
let registry_roots = cargo_registry_roots();
|
||||
let git_roots = cargo_git_checkout_roots();
|
||||
let mut languages = BTreeMap::new();
|
||||
|
||||
for grammar in GRAMMARS {
|
||||
let Some(version) = locked_versions.get(grammar.package) else {
|
||||
let Some(locked) = locked_packages.get(grammar.package) else {
|
||||
continue;
|
||||
};
|
||||
let Some(package_dir) = find_registry_package_dir(®istry_roots, grammar.package, version)
|
||||
let Some(package_dir) =
|
||||
find_locked_package_dir(®istry_roots, &git_roots, grammar.package, locked)
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
@@ -658,6 +644,36 @@ fn cargo_registry_roots() -> Vec<PathBuf> {
|
||||
roots
|
||||
}
|
||||
|
||||
fn cargo_git_checkout_roots() -> Vec<PathBuf> {
|
||||
let mut roots = Vec::new();
|
||||
if let Some(cargo_home) = env::var_os("CARGO_HOME") {
|
||||
roots.push(PathBuf::from(cargo_home).join("git").join("checkouts"));
|
||||
}
|
||||
if let Some(home) = env::var_os("HOME") {
|
||||
roots.push(
|
||||
PathBuf::from(home)
|
||||
.join(".cargo")
|
||||
.join("git")
|
||||
.join("checkouts"),
|
||||
);
|
||||
}
|
||||
roots
|
||||
}
|
||||
|
||||
fn find_locked_package_dir(
|
||||
registry_roots: &[PathBuf],
|
||||
git_roots: &[PathBuf],
|
||||
package: &str,
|
||||
locked: &LockedPackage,
|
||||
) -> Option<PathBuf> {
|
||||
match locked.source.as_deref() {
|
||||
Some(source) if source.starts_with("git+") => {
|
||||
find_git_package_dir(git_roots, package, &locked.version, git_revision(source))
|
||||
},
|
||||
_ => find_registry_package_dir(registry_roots, package, &locked.version),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_registry_package_dir(
|
||||
registry_roots: &[PathBuf],
|
||||
package: &str,
|
||||
@@ -677,32 +693,145 @@ fn find_registry_package_dir(
|
||||
None
|
||||
}
|
||||
|
||||
fn locked_package_versions(lock_path: &Path) -> HashMap<String, String> {
|
||||
fn find_git_package_dir(
|
||||
git_roots: &[PathBuf],
|
||||
package: &str,
|
||||
version: &str,
|
||||
revision: Option<&str>,
|
||||
) -> Option<PathBuf> {
|
||||
for git_root in git_roots {
|
||||
let Ok(checkout_dirs) = fs::read_dir(git_root) else {
|
||||
continue;
|
||||
};
|
||||
for checkout_dir in checkout_dirs.flatten() {
|
||||
let Ok(revision_dirs) = fs::read_dir(checkout_dir.path()) else {
|
||||
continue;
|
||||
};
|
||||
for revision_dir in revision_dirs.flatten() {
|
||||
let revision_path = revision_dir.path();
|
||||
let Some(revision_name) = revision_path.file_name().and_then(|name| name.to_str())
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
if !revision_matches(revision_name, revision) {
|
||||
continue;
|
||||
}
|
||||
if let Some(package_dir) = find_manifest_package_dir(&revision_path, package, version) {
|
||||
return Some(package_dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn revision_matches(revision_name: &str, revision: Option<&str>) -> bool {
|
||||
revision.is_none_or(|revision| {
|
||||
revision.starts_with(revision_name) || revision_name.starts_with(revision)
|
||||
})
|
||||
}
|
||||
|
||||
fn find_manifest_package_dir(root: &Path, package: &str, version: &str) -> Option<PathBuf> {
|
||||
if manifest_matches_package(&root.join("Cargo.toml"), package, version) {
|
||||
return Some(root.to_path_buf());
|
||||
}
|
||||
|
||||
let Ok(entries) = fs::read_dir(root) else {
|
||||
return None;
|
||||
};
|
||||
for entry in entries.flatten() {
|
||||
let candidate = entry.path();
|
||||
if candidate.is_dir()
|
||||
&& manifest_matches_package(&candidate.join("Cargo.toml"), package, version)
|
||||
{
|
||||
return Some(candidate);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn manifest_matches_package(manifest_path: &Path, package: &str, version: &str) -> bool {
|
||||
let Ok(source) = fs::read_to_string(manifest_path) else {
|
||||
return false;
|
||||
};
|
||||
let mut in_package = false;
|
||||
let mut name_matches = false;
|
||||
let mut version_matches = false;
|
||||
|
||||
for line in source.lines() {
|
||||
let trimmed = line.trim();
|
||||
if trimmed.starts_with('[') {
|
||||
in_package = trimmed == "[package]";
|
||||
continue;
|
||||
}
|
||||
if !in_package {
|
||||
continue;
|
||||
}
|
||||
if let Some(value) = toml_string_value(trimmed, "name") {
|
||||
name_matches = value == package;
|
||||
continue;
|
||||
}
|
||||
if let Some(value) = toml_string_value(trimmed, "version") {
|
||||
version_matches = value == version;
|
||||
}
|
||||
}
|
||||
|
||||
name_matches && version_matches
|
||||
}
|
||||
|
||||
fn git_revision(source: &str) -> Option<&str> {
|
||||
source.rsplit_once('#').and_then(|(_, revision)| {
|
||||
if revision.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(revision)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn locked_packages(lock_path: &Path) -> HashMap<String, LockedPackage> {
|
||||
let source = fs::read_to_string(lock_path).expect("Cargo.lock should be readable");
|
||||
let mut versions = HashMap::new();
|
||||
let mut packages = HashMap::new();
|
||||
let mut current_name = None;
|
||||
let mut current_version = None;
|
||||
let mut current_source = None;
|
||||
|
||||
for line in source.lines() {
|
||||
let trimmed = line.trim();
|
||||
if trimmed == "[[package]]" {
|
||||
if let (Some(name), Some(version)) = (current_name.take(), current_version.take()) {
|
||||
versions.insert(name, version);
|
||||
packages.insert(name, LockedPackage { version, source: current_source.take() });
|
||||
}
|
||||
current_source = None;
|
||||
continue;
|
||||
}
|
||||
if let Some(value) = trimmed.strip_prefix("name = \"") {
|
||||
current_name = value.strip_suffix('"').map(ToOwned::to_owned);
|
||||
if let Some(value) = toml_string_value(trimmed, "name") {
|
||||
current_name = Some(value.to_string());
|
||||
continue;
|
||||
}
|
||||
if let Some(value) = trimmed.strip_prefix("version = \"") {
|
||||
current_version = value.strip_suffix('"').map(ToOwned::to_owned);
|
||||
if let Some(value) = toml_string_value(trimmed, "version") {
|
||||
current_version = Some(value.to_string());
|
||||
continue;
|
||||
}
|
||||
if let Some(value) = toml_string_value(trimmed, "source") {
|
||||
current_source = Some(value.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
if let (Some(name), Some(version)) = (current_name, current_version) {
|
||||
versions.insert(name, version);
|
||||
packages.insert(name, LockedPackage { version, source: current_source });
|
||||
}
|
||||
|
||||
versions
|
||||
packages
|
||||
}
|
||||
|
||||
fn toml_string_value<'a>(line: &'a str, key: &str) -> Option<&'a str> {
|
||||
let value = line
|
||||
.strip_prefix(key)?
|
||||
.trim_start()
|
||||
.strip_prefix('=')?
|
||||
.trim_start()
|
||||
.strip_prefix('"')?;
|
||||
let end = value.find('"')?;
|
||||
Some(&value[..end])
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn generated_schema_covers_expected_languages() {
|
||||
for language in ["python", "nix", "toml", "typescript", "rust", "yaml"] {
|
||||
for language in ["python", "nix", "toml", "typescript", "rust", "yaml", "handlebars"] {
|
||||
assert!(has_schema(language), "{language} should have generated schema data");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,219 +0,0 @@
|
||||
#ifndef TREE_SITTER_PARSER_H_
|
||||
#define TREE_SITTER_PARSER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ts_builtin_sym_error ((TSSymbol)-1)
|
||||
#define ts_builtin_sym_end 0
|
||||
#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
|
||||
|
||||
#ifndef TREE_SITTER_API_H_
|
||||
typedef uint16_t TSStateId;
|
||||
typedef uint16_t TSSymbol;
|
||||
typedef uint16_t TSFieldId;
|
||||
typedef struct TSLanguage TSLanguage;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
TSFieldId field_id;
|
||||
uint8_t child_index;
|
||||
bool inherited;
|
||||
} TSFieldMapEntry;
|
||||
|
||||
typedef struct {
|
||||
uint16_t index;
|
||||
uint16_t length;
|
||||
} TSFieldMapSlice;
|
||||
|
||||
typedef struct {
|
||||
bool visible;
|
||||
bool named;
|
||||
bool supertype;
|
||||
} TSSymbolMetadata;
|
||||
|
||||
typedef struct TSLexer TSLexer;
|
||||
|
||||
struct TSLexer {
|
||||
int32_t lookahead;
|
||||
TSSymbol result_symbol;
|
||||
void (*advance)(TSLexer *, bool);
|
||||
void (*mark_end)(TSLexer *);
|
||||
uint32_t (*get_column)(TSLexer *);
|
||||
bool (*is_at_included_range_start)(const TSLexer *);
|
||||
bool (*eof)(const TSLexer *);
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
TSParseActionTypeShift,
|
||||
TSParseActionTypeReduce,
|
||||
TSParseActionTypeAccept,
|
||||
TSParseActionTypeRecover,
|
||||
} TSParseActionType;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t type;
|
||||
TSStateId state;
|
||||
bool extra;
|
||||
bool repetition;
|
||||
} shift;
|
||||
struct {
|
||||
uint8_t type;
|
||||
uint8_t child_count;
|
||||
TSSymbol symbol;
|
||||
int16_t dynamic_precedence;
|
||||
uint16_t production_id;
|
||||
} reduce;
|
||||
uint8_t type;
|
||||
} TSParseAction;
|
||||
|
||||
typedef struct {
|
||||
uint16_t lex_state;
|
||||
uint16_t external_lex_state;
|
||||
} TSLexMode;
|
||||
|
||||
typedef union {
|
||||
TSParseAction action;
|
||||
struct {
|
||||
uint8_t count;
|
||||
bool reusable;
|
||||
} entry;
|
||||
} TSParseActionEntry;
|
||||
|
||||
typedef struct {
|
||||
int32_t start;
|
||||
int32_t end;
|
||||
} TSCharacterRange;
|
||||
|
||||
struct TSLanguage {
|
||||
uint32_t version;
|
||||
uint32_t symbol_count;
|
||||
uint32_t alias_count;
|
||||
uint32_t token_count;
|
||||
uint32_t external_token_count;
|
||||
uint32_t state_count;
|
||||
uint32_t large_state_count;
|
||||
uint32_t production_id_count;
|
||||
uint32_t field_count;
|
||||
uint16_t max_alias_sequence_length;
|
||||
const uint16_t *parse_table;
|
||||
const uint16_t *small_parse_table;
|
||||
const uint32_t *small_parse_table_map;
|
||||
const TSParseActionEntry *parse_actions;
|
||||
const char * const *symbol_names;
|
||||
const char * const *field_names;
|
||||
const TSFieldMapSlice *field_map_slices;
|
||||
const TSFieldMapEntry *field_map_entries;
|
||||
const TSSymbolMetadata *symbol_metadata;
|
||||
const TSSymbol *public_symbol_map;
|
||||
const uint16_t *alias_map;
|
||||
const TSSymbol *alias_sequences;
|
||||
const TSLexMode *lex_modes;
|
||||
bool (*lex_fn)(TSLexer *, TSStateId);
|
||||
bool (*keyword_lex_fn)(TSLexer *, TSStateId);
|
||||
TSSymbol keyword_capture_token;
|
||||
struct {
|
||||
const bool *states;
|
||||
const TSSymbol *symbol_map;
|
||||
void *(*create)(void);
|
||||
void (*destroy)(void *);
|
||||
bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
|
||||
unsigned (*serialize)(void *, char *);
|
||||
void (*deserialize)(void *, const char *, unsigned);
|
||||
} external_scanner;
|
||||
const TSStateId *primary_state_ids;
|
||||
};
|
||||
|
||||
static inline bool set_contains(TSCharacterRange *ranges, uint32_t len, int32_t lookahead) {
|
||||
uint32_t index = 0;
|
||||
uint32_t size = len - index;
|
||||
while (size > 1) {
|
||||
uint32_t half_size = size / 2;
|
||||
uint32_t mid_index = index + half_size;
|
||||
TSCharacterRange *range = &ranges[mid_index];
|
||||
if (lookahead >= range->start && lookahead <= range->end) {
|
||||
return true;
|
||||
} else if (lookahead > range->end) {
|
||||
index = mid_index;
|
||||
}
|
||||
size -= half_size;
|
||||
}
|
||||
TSCharacterRange *range = &ranges[index];
|
||||
return (lookahead >= range->start && lookahead <= range->end);
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define UNUSED __pragma(warning(suppress : 4101))
|
||||
#else
|
||||
#define UNUSED __attribute__((unused))
|
||||
#endif
|
||||
|
||||
#define START_LEXER() \
|
||||
bool result = false; \
|
||||
bool skip = false; \
|
||||
UNUSED \
|
||||
bool eof = false; \
|
||||
int32_t lookahead; \
|
||||
goto start; \
|
||||
next_state: \
|
||||
lexer->advance(lexer, skip); \
|
||||
start: \
|
||||
skip = false; \
|
||||
lookahead = lexer->lookahead;
|
||||
|
||||
#define ADVANCE(state_value) \
|
||||
{ \
|
||||
state = state_value; \
|
||||
goto next_state; \
|
||||
}
|
||||
|
||||
#define ADVANCE_MAP(...) \
|
||||
{ \
|
||||
static const uint16_t map[] = { __VA_ARGS__ }; \
|
||||
for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \
|
||||
if (map[i] == lookahead) { \
|
||||
state = map[i + 1]; \
|
||||
goto next_state; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SKIP(state_value) \
|
||||
{ \
|
||||
skip = true; \
|
||||
state = state_value; \
|
||||
goto next_state; \
|
||||
}
|
||||
|
||||
#define ACCEPT_TOKEN(symbol_value) \
|
||||
result = true; \
|
||||
lexer->result_symbol = symbol_value; \
|
||||
lexer->mark_end(lexer);
|
||||
|
||||
#define END_STATE() return result;
|
||||
|
||||
#define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT)
|
||||
|
||||
#define STATE(id) id
|
||||
|
||||
#define ACTIONS(id) id
|
||||
|
||||
#define SHIFT(state_value) \
|
||||
{{ \
|
||||
.shift = { \
|
||||
.type = TSParseActionTypeShift, \
|
||||
.state = (state_value) \
|
||||
} \
|
||||
}}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,152 +0,0 @@
|
||||
// Vendored from tree-sitter-glimmer 0.0.1 because the published crate does
|
||||
// not compile its external scanner in bindings/rust/build.rs.
|
||||
#include "parser.h"
|
||||
#include <wctype.h>
|
||||
|
||||
enum TokenType {
|
||||
COMMENT
|
||||
};
|
||||
|
||||
void *tree_sitter_glimmer_external_scanner_create() { return NULL; }
|
||||
void tree_sitter_glimmer_external_scanner_destroy(void *payload) { (void)payload; }
|
||||
void tree_sitter_glimmer_external_scanner_reset(void *payload) { (void)payload; }
|
||||
unsigned tree_sitter_glimmer_external_scanner_serialize(void *payload, char *buffer) {
|
||||
(void)payload;
|
||||
(void)buffer;
|
||||
return 0;
|
||||
}
|
||||
void tree_sitter_glimmer_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {
|
||||
(void)payload;
|
||||
(void)buffer;
|
||||
(void)length;
|
||||
}
|
||||
|
||||
static void advance(TSLexer *lexer) { lexer->advance(lexer, false); }
|
||||
|
||||
static bool scan_html_comment(TSLexer *lexer) {
|
||||
if (lexer->lookahead != '!') return false;
|
||||
advance(lexer);
|
||||
if (lexer->lookahead != '-') return false;
|
||||
advance(lexer);
|
||||
if (lexer->lookahead != '-') return false;
|
||||
advance(lexer);
|
||||
|
||||
unsigned dashes = 0;
|
||||
while (lexer->lookahead) {
|
||||
switch (lexer->lookahead) {
|
||||
case '-':
|
||||
++dashes;
|
||||
break;
|
||||
case '>':
|
||||
if (dashes >= 2) {
|
||||
lexer->result_symbol = COMMENT;
|
||||
advance(lexer);
|
||||
lexer->mark_end(lexer);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
dashes = 0;
|
||||
}
|
||||
advance(lexer);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool scan_multi_line_handlebars_comment(TSLexer *lexer) {
|
||||
if (lexer->lookahead != '-') return false;
|
||||
|
||||
unsigned dashes = 0;
|
||||
unsigned brackets = 0;
|
||||
while (lexer->lookahead) {
|
||||
switch (lexer->lookahead) {
|
||||
case '-':
|
||||
++dashes;
|
||||
break;
|
||||
case '}':
|
||||
++brackets;
|
||||
if (dashes >= 2 && brackets == 2) {
|
||||
lexer->result_symbol = COMMENT;
|
||||
advance(lexer);
|
||||
lexer->mark_end(lexer);
|
||||
return true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
dashes = 0;
|
||||
brackets = 0;
|
||||
}
|
||||
advance(lexer);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool scan_single_line_handlebars_comment(TSLexer *lexer) {
|
||||
unsigned brackets = 0;
|
||||
while (lexer->lookahead) {
|
||||
switch (lexer->lookahead) {
|
||||
case '}':
|
||||
++brackets;
|
||||
if (brackets == 2) {
|
||||
lexer->result_symbol = COMMENT;
|
||||
advance(lexer);
|
||||
lexer->mark_end(lexer);
|
||||
return true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
brackets = 0;
|
||||
}
|
||||
advance(lexer);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool scan_handlebars_comment(TSLexer *lexer) {
|
||||
if (lexer->lookahead != '{') return false;
|
||||
advance(lexer);
|
||||
if (lexer->lookahead != '!') return false;
|
||||
advance(lexer);
|
||||
|
||||
switch (lexer->lookahead) {
|
||||
case '-':
|
||||
advance(lexer);
|
||||
return scan_multi_line_handlebars_comment(lexer);
|
||||
default:
|
||||
advance(lexer);
|
||||
return scan_single_line_handlebars_comment(lexer);
|
||||
}
|
||||
}
|
||||
|
||||
bool tree_sitter_glimmer_external_scanner_scan(
|
||||
void *payload,
|
||||
TSLexer *lexer,
|
||||
const bool *valid_symbols
|
||||
) {
|
||||
(void)payload;
|
||||
|
||||
while (iswspace(lexer->lookahead)) {
|
||||
lexer->advance(lexer, true);
|
||||
}
|
||||
|
||||
if (valid_symbols[COMMENT]) {
|
||||
switch (lexer->lookahead) {
|
||||
case '<':
|
||||
lexer->mark_end(lexer);
|
||||
advance(lexer);
|
||||
return scan_html_comment(lexer);
|
||||
case '{':
|
||||
lexer->mark_end(lexer);
|
||||
advance(lexer);
|
||||
return scan_handlebars_comment(lexer);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user