Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(grit): improve snippet compiler #3223

Merged
merged 1 commit into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions crates/biome_grit_patterns/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,8 @@ regex = { workspace = true }
rustc-hash = { workspace = true }
serde = { workspace = true, features = ["derive"] }

[dev-dependencies]
insta = { workspace = true }

[lints]
workspace = true
2 changes: 1 addition & 1 deletion crates/biome_grit_patterns/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use biome_rowan::TextRange;

#[derive(Debug, Diagnostic)]
#[diagnostic(severity = Warning)]
pub(crate) struct CompilerDiagnostic {
pub struct CompilerDiagnostic {
#[message]
#[description]
message: String,
Expand Down
120 changes: 63 additions & 57 deletions crates/biome_grit_patterns/src/grit_binding.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,48 @@
use crate::{
grit_context::GritQueryContext, grit_target_language::GritTargetLanguage,
grit_target_node::GritTargetNode, grit_tree::GritTree, source_location_ext::SourceFileExt,
grit_target_node::GritTargetNode, source_location_ext::SourceFileExt, util::TextRangeGritExt,
};
use biome_diagnostics::{display::SourceFile, SourceCode};
use grit_pattern_matcher::{binding::Binding, constant::Constant};
use grit_util::{Ast, AstNode, ByteRange, CodeRange, Range};
use std::path::Path;
use biome_rowan::TextRange;
use grit_pattern_matcher::{
binding::Binding, constant::Constant, effects::Effect, pattern::FileRegistry,
};
use grit_util::{AnalysisLogs, AstNode, ByteRange, CodeRange, Range};
use std::{borrow::Cow, collections::HashMap, path::Path};

#[derive(Clone, Debug, PartialEq)]
pub(crate) enum GritBinding<'a> {
Tree(&'a GritTree),
Node(GritTargetNode),
Constant(&'a Constant),
}
pub enum GritBinding<'a> {
/// Binds to a specific node.
Node(GritTargetNode<'a>),

impl<'a> GritBinding<'a> {
pub fn from_tree(tree: &'a GritTree) -> Self {
Self::Tree(tree)
}
/// Binds to a range in the tree's source text.
Range(TextRange, &'a str),

/// Binds to an empty slot inside a node.
Empty(GritTargetNode<'a>, u32),

/// Binds to an individual constant.
Constant(&'a Constant),
}

impl<'a> Binding<'a, GritQueryContext> for GritBinding<'a> {
fn from_constant(constant: &'a Constant) -> Self {
Self::Constant(constant)
}

fn from_node(node: GritTargetNode) -> Self {
fn from_node(node: GritTargetNode<'a>) -> Self {
Self::Node(node)
}

fn from_path(_path: &'a Path) -> Self {
todo!()
}

fn from_range(_range: ByteRange, _source: &'a str) -> Self {
todo!()
fn from_range(range: ByteRange, source: &'a str) -> Self {
Self::Range(
TextRange::new((range.start as u32).into(), (range.end as u32).into()),
source,
)
}

/// Returns the only node bound by this binding.
Expand All @@ -43,10 +51,10 @@ impl<'a> Binding<'a, GritQueryContext> for GritBinding<'a> {
///
/// Returns `None` if the binding has no associated node, or if there is
/// more than one associated node.
fn singleton(&self) -> Option<GritTargetNode> {
fn singleton(&self) -> Option<GritTargetNode<'a>> {
match self {
Self::Node(node) => Some(node.clone()),
Self::Tree(..) | Self::Constant(..) => None,
Self::Range(..) | Self::Empty(..) | Self::Constant(..) => None,
}
}

Expand All @@ -56,41 +64,37 @@ impl<'a> Binding<'a, GritQueryContext> for GritBinding<'a> {

fn position(&self, _language: &GritTargetLanguage) -> Option<Range> {
match self {
GritBinding::Tree(tree) => {
let source = tree.source();
GritBinding::Node(node) => {
let source = SourceFile::new(SourceCode {
text: &source,
text: node.text(),
line_starts: None,
});
source.to_grit_range(tree.root_node().text_range())
source.to_grit_range(node.text_trimmed_range())
}
GritBinding::Node(node) => {
// TODO: This is probably very inefficient.
let root = node.ancestors().last()?;
let source = root.text().to_string();
GritBinding::Range(range, source) => {
let source = SourceFile::new(SourceCode {
text: &source,
text: source,
line_starts: None,
});
source.to_grit_range(root.text_trimmed_range())
source.to_grit_range(*range)
}
GritBinding::Constant(_) => None,
GritBinding::Empty(..) | GritBinding::Constant(_) => None,
}
}

fn range(&self, _language: &GritTargetLanguage) -> Option<ByteRange> {
match self {
GritBinding::Tree(tree) => Some(tree.root_node().byte_range()),
GritBinding::Node(node) => Some(node.byte_range()),
GritBinding::Constant(_) => None,
GritBinding::Range(range, _) => Some(range.to_byte_range()),
GritBinding::Empty(..) | GritBinding::Constant(_) => None,
}
}

fn code_range(&self, _language: &GritTargetLanguage) -> Option<CodeRange> {
match self {
GritBinding::Tree(tree) => Some(tree.root_node().code_range()),
GritBinding::Node(node) => Some(node.code_range()),
GritBinding::Constant(_) => None,
GritBinding::Range(range, source) => Some(range.to_code_range(source)),
GritBinding::Empty(..) | GritBinding::Constant(_) => None,
}
}

Expand All @@ -114,17 +118,24 @@ impl<'a> Binding<'a, GritQueryContext> for GritBinding<'a> {
fn linearized_text(
&self,
_language: &GritTargetLanguage,
_effects: &[grit_pattern_matcher::effects::Effect<'a, GritQueryContext>],
_files: &grit_pattern_matcher::pattern::FileRegistry<'a, GritQueryContext>,
_memo: &mut std::collections::HashMap<grit_util::CodeRange, Option<String>>,
_effects: &[Effect<'a, GritQueryContext>],
_files: &FileRegistry<'a, GritQueryContext>,
_memo: &mut HashMap<grit_util::CodeRange, Option<String>>,
_distributed_indent: Option<usize>,
_logs: &mut grit_util::AnalysisLogs,
) -> anyhow::Result<std::borrow::Cow<'a, str>> {
_logs: &mut AnalysisLogs,
) -> anyhow::Result<Cow<'a, str>> {
todo!()
}

fn text(&self, _language: &GritTargetLanguage) -> anyhow::Result<std::borrow::Cow<str>> {
todo!()
fn text(&self, _language: &GritTargetLanguage) -> anyhow::Result<Cow<'a, str>> {
match self {
GritBinding::Node(node) => Ok(node.text().into()),
GritBinding::Range(range, source) => {
Ok((&source[range.start().into()..range.end().into()]).into())
}
GritBinding::Empty(_, _) => Ok("".into()),
GritBinding::Constant(constant) => Ok(constant.to_string().into()),
}
}

fn source(&self) -> Option<&'a str> {
Expand All @@ -139,19 +150,25 @@ impl<'a> Binding<'a, GritQueryContext> for GritBinding<'a> {
todo!()
}

fn as_node(&self) -> Option<GritTargetNode> {
todo!()
fn as_node(&self) -> Option<GritTargetNode<'a>> {
match self {
GritBinding::Node(node) => Some(node.clone()),
GritBinding::Range(..) | GritBinding::Empty(..) | GritBinding::Constant(_) => None,
}
}

fn is_list(&self) -> bool {
todo!()
self.as_node().map_or(false, |node| node.is_list())
}

fn list_items(&self) -> Option<impl Iterator<Item = GritTargetNode> + Clone> {
None::<TodoIterator>
fn list_items(&self) -> Option<impl Iterator<Item = GritTargetNode<'a>> + Clone> {
match self {
GritBinding::Node(node) if node.is_list() => Some(node.children()),
_ => None,
}
}

fn parent_node(&self) -> Option<GritTargetNode> {
fn parent_node(&self) -> Option<GritTargetNode<'a>> {
todo!()
}

Expand All @@ -167,14 +184,3 @@ impl<'a> Binding<'a, GritQueryContext> for GritBinding<'a> {
todo!()
}
}

#[derive(Clone)]
struct TodoIterator;

impl Iterator for TodoIterator {
type Item = GritTargetNode;

fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
2 changes: 1 addition & 1 deletion crates/biome_grit_patterns/src/grit_code_snippet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use grit_pattern_matcher::pattern::{
use grit_util::AnalysisLogs;

#[derive(Clone, Debug)]
pub(crate) struct GritCodeSnippet {
pub struct GritCodeSnippet {
pub(crate) patterns: Vec<(GritTargetSyntaxKind, Pattern<GritQueryContext>)>,
pub(crate) source: String,
pub(crate) dynamic_snippet: Option<DynamicPattern<GritQueryContext>>,
Expand Down
12 changes: 6 additions & 6 deletions crates/biome_grit_patterns/src/grit_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::grit_node_patterns::{GritLeafNodePattern, GritNodePattern};
use crate::grit_resolved_pattern::GritResolvedPattern;
use crate::grit_target_language::GritTargetLanguage;
use crate::grit_target_node::GritTargetNode;
use crate::grit_tree::GritTree;
use crate::grit_tree::GritTargetTree;
use anyhow::Result;
use grit_pattern_matcher::context::{ExecContext, QueryContext};
use grit_pattern_matcher::file_owners::FileOwners;
Expand All @@ -15,10 +15,10 @@ use grit_pattern_matcher::pattern::{
use grit_util::AnalysisLogs;

#[derive(Clone, Debug, PartialEq)]
pub(crate) struct GritQueryContext;
pub struct GritQueryContext;

impl QueryContext for GritQueryContext {
type Node<'a> = GritTargetNode;
type Node<'a> = GritTargetNode<'a>;
type NodePattern = GritNodePattern;
type LeafNodePattern = GritLeafNodePattern;
type ExecContext<'a> = GritExecContext;
Expand All @@ -27,11 +27,11 @@ impl QueryContext for GritQueryContext {
type ResolvedPattern<'a> = GritResolvedPattern<'a>;
type Language<'a> = GritTargetLanguage;
type File<'a> = GritFile<'a>;
type Tree<'a> = GritTree;
type Tree<'a> = GritTargetTree;
}

#[derive(Debug)]
pub(crate) struct GritExecContext {
pub struct GritExecContext {
lang: GritTargetLanguage,
}

Expand Down Expand Up @@ -68,7 +68,7 @@ impl<'a> ExecContext<'a, GritQueryContext> for GritExecContext {
todo!()
}

fn files(&self) -> &FileOwners<GritTree> {
fn files(&self) -> &FileOwners<GritTargetTree> {
todo!()
}

Expand Down
2 changes: 1 addition & 1 deletion crates/biome_grit_patterns/src/grit_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use grit_util::Ast;
use path_absolutize::Absolutize;

#[derive(Clone, Debug, PartialEq)]
pub(crate) enum GritFile<'a> {
pub enum GritFile<'a> {
Resolved(Box<ResolvedFile<'a, GritQueryContext>>),
Ptr(FilePtr),
}
Expand Down
14 changes: 7 additions & 7 deletions crates/biome_grit_patterns/src/grit_js_parser.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{grit_analysis_ext::GritAnalysisExt, grit_tree::GritTree};
use crate::{grit_analysis_ext::GritAnalysisExt, grit_tree::GritTargetTree};
use biome_js_parser::{parse, JsParserOptions};
use biome_js_syntax::JsFileSource;
use grit_util::{AnalysisLogs, FileOrigin, Parser, SnippetTree};
Expand All @@ -7,30 +7,30 @@ use std::path::Path;
pub struct GritJsParser;

impl Parser for GritJsParser {
type Tree = GritTree;
type Tree = GritTargetTree;

fn parse_file(
&mut self,
body: &str,
path: Option<&Path>,
logs: &mut AnalysisLogs,
_old_tree: FileOrigin<'_, GritTree>,
) -> Option<GritTree> {
_old_tree: FileOrigin<'_, GritTargetTree>,
) -> Option<GritTargetTree> {
let parse_result = parse(body, JsFileSource::tsx(), JsParserOptions::default());

for diagnostic in parse_result.diagnostics() {
logs.push(diagnostic.to_log(path));
}

Some(GritTree::new(parse_result.syntax().into()))
Some(GritTargetTree::new(parse_result.syntax().into()))
}

fn parse_snippet(
&mut self,
prefix: &'static str,
source: &str,
postfix: &'static str,
) -> SnippetTree<GritTree> {
) -> SnippetTree<GritTargetTree> {
let context = format!("{prefix}{source}{postfix}");

let len = if cfg!(target_arch = "wasm32") {
Expand All @@ -42,7 +42,7 @@ impl Parser for GritJsParser {
let parse_result = parse(&context, JsFileSource::tsx(), JsParserOptions::default());

SnippetTree {
tree: GritTree::new(parse_result.syntax().into()),
tree: GritTargetTree::new(parse_result.syntax().into()),
source: source.to_owned(),
prefix,
postfix,
Expand Down
Loading