-
-
Notifications
You must be signed in to change notification settings - Fork 400
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: add Grit target node bindings (#2746)
- Loading branch information
Showing
14 changed files
with
496 additions
and
34 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
123 changes: 107 additions & 16 deletions
123
crates/biome_grit_patterns/src/grit_target_language.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,116 @@ | ||
use crate::grit_node::GritNode; | ||
mod js_target_language; | ||
|
||
pub use js_target_language::JsTargetLanguage; | ||
|
||
use crate::grit_target_node::{GritTargetNode, GritTargetSyntaxKind}; | ||
use biome_rowan::SyntaxKind; | ||
use grit_util::Language; | ||
|
||
#[derive(Clone, Copy)] | ||
pub struct GritTargetLanguage; | ||
/// Generates the `GritTargetLanguage` enum. | ||
/// | ||
/// This enum contains a variant for every language that we support running Grit | ||
/// queries on. We implement Grit's [`Language`] trait on this enum, and | ||
/// implement the slightly more convenient [`GritTargetLanguageImpl`] for | ||
/// creating language-specific implementations. | ||
macro_rules! generate_target_language { | ||
($($language:ident),+) => { | ||
#[derive(Clone, Debug)] | ||
pub enum GritTargetLanguage { | ||
$($language($language)),+ | ||
} | ||
|
||
impl Language for GritTargetLanguage { | ||
type Node<'a> = GritNode; | ||
$(impl From<$language> for GritTargetLanguage { | ||
fn from(value: $language) -> Self { | ||
Self::$language(value) | ||
} | ||
})+ | ||
|
||
fn language_name(&self) -> &'static str { | ||
todo!() | ||
} | ||
impl GritTargetLanguage { | ||
fn metavariable_kind(&self) -> GritTargetSyntaxKind { | ||
match self { | ||
$(Self::$language(_) => $language::metavariable_kind().into()),+ | ||
} | ||
} | ||
|
||
fn snippet_context_strings(&self) -> &[(&'static str, &'static str)] { | ||
todo!() | ||
} | ||
fn is_alternative_metavariable_kind(&self, kind: GritTargetSyntaxKind) -> bool { | ||
match self { | ||
$(Self::$language(_) => $language::is_alternative_metavariable_kind(kind)),+ | ||
} | ||
} | ||
} | ||
|
||
fn is_comment(&self, _node: &Self::Node<'_>) -> bool { | ||
todo!() | ||
} | ||
impl Language for GritTargetLanguage { | ||
type Node<'a> = GritTargetNode; | ||
|
||
fn language_name(&self) -> &'static str { | ||
match self { | ||
$(Self::$language(language) => language.language_name()),+ | ||
} | ||
} | ||
|
||
fn snippet_context_strings(&self) -> &[(&'static str, &'static str)] { | ||
match self { | ||
$(Self::$language(language) => language.snippet_context_strings()),+ | ||
} | ||
} | ||
|
||
fn is_comment(&self, node: &GritTargetNode) -> bool { | ||
match self { | ||
$(Self::$language(language) => language.is_comment(node)),+ | ||
} | ||
} | ||
|
||
fn is_metavariable(&self, node: &GritTargetNode) -> bool { | ||
node.kind() == self.metavariable_kind() | ||
|| (self.is_alternative_metavariable_kind(node.kind()) | ||
&& self.exact_replaced_variable_regex().is_match(&node.text_trimmed().to_string())) | ||
} | ||
} | ||
}; | ||
} | ||
|
||
generate_target_language! { | ||
JsTargetLanguage | ||
} | ||
|
||
/// Trait to be implemented by the language-specific implementations. | ||
/// | ||
/// This is used to make language implementations a little easier, by not | ||
/// forcing them to reimplement methods that are common across implementations. | ||
trait GritTargetLanguageImpl { | ||
type Kind: SyntaxKind; | ||
|
||
fn language_name(&self) -> &'static str; | ||
|
||
/// Strings that provide context for parsing snippets. | ||
/// | ||
/// Snippet contexts help when a snippet is a valid AST subtree, but needs | ||
/// to be in a larger tree to parse. For example, matching on a table name | ||
/// like ` $schema.$table` in SQL is not valid SQL by itself, only when | ||
/// surrounded by something like `SELECT x from $schema.$table` is the | ||
/// snippet valid. | ||
/// | ||
/// This method returns a list of strings that are used to match the snippet | ||
/// in the larger tree. For example, the SQL implementation returns | ||
/// `["SELECT 1 from ", ";"]` to match a table name in a SQL query. | ||
fn snippet_context_strings(&self) -> &[(&'static str, &'static str)]; | ||
|
||
/// Determines whether the given target node is a comment. | ||
fn is_comment(&self, node: &GritTargetNode) -> bool; | ||
|
||
/// Returns the syntax kind for metavariables. | ||
fn metavariable_kind() -> Self::Kind; | ||
|
||
fn is_metavariable(&self, _node: &Self::Node<'_>) -> bool { | ||
todo!() | ||
/// Returns whether the given syntax kind is an "alternative" kind for | ||
/// metavariables. | ||
/// | ||
/// For example, in JavaScript, the content of a template string may also | ||
/// contain metavariables. | ||
/// | ||
/// Note that any node kind for which this returns `true` should have a | ||
/// (trimmed) text representation which corresponds exactly to the | ||
/// metavariable representation. | ||
fn is_alternative_metavariable_kind(_kind: GritTargetSyntaxKind) -> bool { | ||
false | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
crates/biome_grit_patterns/src/grit_target_language/js_target_language.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
use super::GritTargetLanguageImpl; | ||
use crate::grit_target_node::{GritTargetNode, GritTargetSyntaxKind}; | ||
use biome_js_syntax::JsSyntaxKind; | ||
use biome_parser::{token_set, TokenSet}; | ||
|
||
const COMMENT_KINDS: TokenSet<JsSyntaxKind> = | ||
token_set![JsSyntaxKind::COMMENT, JsSyntaxKind::MULTILINE_COMMENT]; | ||
|
||
#[derive(Clone, Debug)] | ||
pub struct JsTargetLanguage; | ||
|
||
impl GritTargetLanguageImpl for JsTargetLanguage { | ||
type Kind = JsSyntaxKind; | ||
|
||
fn language_name(&self) -> &'static str { | ||
"JavaScript" | ||
} | ||
|
||
fn snippet_context_strings(&self) -> &[(&'static str, &'static str)] { | ||
&[ | ||
("", ""), | ||
("import ", " from 'GRIT_PACKAGE';"), | ||
("GRIT_VALUE ", " GRIT_VALUE"), | ||
("class GRIT_CLASS ", " {}"), | ||
("class GRIT_CLASS { ", " GRIT_PROP = 'GRIT_VALUE'; }"), | ||
("", " function GRIT_FUNCTION() {}"), | ||
("GRIT_OBJ = { ", " }"), | ||
("class GRIT_CLASS { ", " }"), | ||
("GRIT_VAR = ", ""), | ||
("<f>", "</f>"), | ||
("<f ", " />"), | ||
("function GRIT_FN(", ") {}"), | ||
("var ", ";"), | ||
("", " class GRIT_CLASS {}"), | ||
("function GRIT_FN(GRIT_ARG:", ") { }"), | ||
("import { ", " } from 'GRIT_PACKAGE'"), | ||
("function GRIT_FN(GRIT_ARG", ") { }"), | ||
("GRIT_FN<{ ", " }>();"), | ||
] | ||
} | ||
|
||
fn is_comment(&self, node: &GritTargetNode) -> bool { | ||
node.kind() | ||
.as_js_kind() | ||
.map_or(false, |kind| COMMENT_KINDS.contains(kind)) | ||
} | ||
|
||
fn metavariable_kind() -> Self::Kind { | ||
JsSyntaxKind::JS_GRIT_METAVARIABLE | ||
} | ||
|
||
fn is_alternative_metavariable_kind(kind: GritTargetSyntaxKind) -> bool { | ||
kind.as_js_kind().map_or(false, |kind| { | ||
kind == JsSyntaxKind::JS_TEMPLATE_ELEMENT_LIST | ||
|| kind == JsSyntaxKind::TS_TEMPLATE_ELEMENT_LIST | ||
}) | ||
} | ||
} |
Oops, something went wrong.