Skip to content

Commit

Permalink
Merge branch 'main' into css_in_vue
Browse files Browse the repository at this point in the history
  • Loading branch information
ilevyor committed Mar 28, 2024
2 parents cf056d9 + 542cca3 commit d2956b9
Show file tree
Hide file tree
Showing 19 changed files with 275 additions and 281 deletions.
79 changes: 59 additions & 20 deletions crates/core/src/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ use crate::pattern::resolved_pattern::CodeRange;
use crate::pattern::state::{get_top_level_effects, FileRegistry};
use crate::pattern::{Effect, EffectKind};
use anyhow::{anyhow, Result};
use grit_util::AstNode;
use marzano_language::language::{FieldId, Language};
use marzano_language::target_language::TargetLanguage;
use marzano_util::analysis_logs::{AnalysisLogBuilder, AnalysisLogs};
use marzano_util::node_with_source::NodeWithSource;
use marzano_util::position::{Position, Range};
use marzano_util::tree_sitter_util::children_by_field_id_count;
use std::iter;
use std::ops::Range as StdRange;
use std::path::Path;
use std::{borrow::Cow, collections::HashMap, fmt::Display};
Expand Down Expand Up @@ -103,6 +105,17 @@ fn pad_snippet(padding: &str, snippet: &str) -> String {
result
}

fn adjust_ranges(substitutions: &mut [(EffectRange, String)], index: usize, delta: isize) {
for (EffectRange { range, .. }, _) in substitutions.iter_mut() {
if range.start >= index {
range.start = (range.start as isize + delta) as usize;
}
if range.end >= index {
range.end = (range.end as isize + delta) as usize;
}
}
}

// in multiline snippets, remove padding from every line equal to the padding of the first line,
// such that the first line is left-aligned.
pub(crate) fn adjust_padding<'a>(
Expand Down Expand Up @@ -136,14 +149,11 @@ pub(crate) fn adjust_padding<'a>(
for line in lines {
result.push('\n');
index += 1;
for (EffectRange { range, .. }, _) in substitutions.iter_mut() {
if range.start >= index {
range.start = (range.start as isize + delta) as usize;
}
if range.end >= index {
range.end = (range.end as isize + delta) as usize;
}
if line.trim().is_empty() {
adjust_ranges(substitutions, index, -(line.len() as isize));
continue;
}
adjust_ranges(substitutions, index, delta);
let line = line.strip_prefix(&padding).ok_or_else(|| {
anyhow!(
"expected line \n{}\n to start with {} spaces, code is either not indented with spaces, or does not consistently indent code blocks",
Expand Down Expand Up @@ -460,7 +470,9 @@ impl<'a> Binding<'a> {
pub fn text(&self) -> String {
match self {
Binding::Empty(_, _, _) => "".to_string(),
Binding::Node(source, node) => node_text(source, node).to_string(),
Binding::Node(source, node) => {
NodeWithSource::new(node.clone(), source).text().to_string()
}
Binding::String(s, r) => s[r.start_byte as usize..r.end_byte as usize].into(),
Binding::FileName(s) => s.to_string_lossy().into(),
Binding::List(source, _, _) => {
Expand All @@ -470,13 +482,7 @@ impl<'a> Binding<'a> {
"".to_string()
}
}
Binding::ConstantRef(c) => match c {
Constant::Boolean(b) => b.to_string(),
Constant::String(s) => s.to_string(),
Constant::Integer(i) => i.to_string(),
Constant::Float(d) => d.to_string(),
Constant::Undefined => String::new(),
},
Binding::ConstantRef(c) => c.to_string(),
}
}

Expand Down Expand Up @@ -522,6 +528,44 @@ impl<'a> Binding<'a> {
matches!(self, Self::List(..))
}

/// Returns an iterator over the items in a list.
///
/// Returns `None` if the binding is not bound to a list.
pub(crate) fn list_items(&self) -> Option<impl Iterator<Item = NodeWithSource<'a>>> {
match self {
Self::List(src, node, field_id) => {
let field_id = *field_id;
let mut cursor = node.walk();
cursor.goto_first_child();
let mut done = false;
Some(
iter::from_fn(move || {
while !done {
while cursor.field_id() != Some(field_id) {
if !cursor.goto_next_sibling() {
return None;
}
}
let result = cursor.node();
if !cursor.goto_next_sibling() {
done = true;
}
return Some(result);
}

Check failure on line 554 in crates/core/src/binding.rs

View workflow job for this annotation

GitHub Actions / clippy

this loop never actually loops

error: this loop never actually loops --> crates/core/src/binding.rs:543:25 | 543 | / while !done { 544 | | while cursor.field_id() != Some(field_id) { 545 | | if !cursor.goto_next_sibling() { 546 | | return None; ... | 553 | | return Some(result); 554 | | } | |_________________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#never_loop = note: `#[deny(clippy::never_loop)]` on by default
None
})
.filter(|child| child.is_named())
.map(|named_child| NodeWithSource::new(named_child, src)),
)
}
Self::Empty(..)
| Self::Node(..)
| Self::String(..)
| Self::ConstantRef(..)
| Self::FileName(..) => None,
}
}

/// Returns the parent node of this binding.
///
/// Returns `None` if the binding has no relation to a node.
Expand Down Expand Up @@ -576,8 +620,3 @@ impl<'a> Binding<'a> {
Ok(())
}
}

pub(crate) fn node_text<'a>(source: &'a str, node: &Node) -> &'a str {
let range = Range::from(node.range());
&source[range.start_byte as usize..range.end_byte as usize]
}
2 changes: 1 addition & 1 deletion crates/core/src/pattern/after.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ impl Matcher for After {
};
let prev_node = resolve!(node.previous_non_trivia_node());
if !self.after.execute(
&ResolvedPattern::from_node(prev_node.source, prev_node.node),
&ResolvedPattern::from_node(prev_node),
&mut cur_state,
context,
logs,
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/pattern/ast_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ impl Matcher for ASTNode {
)
} else if let Some(child) = node.child_by_field_id(*field_id) {
pattern.execute(
&ResolvedPattern::from_node(source, child),
&ResolvedPattern::from_node(NodeWithSource::new(child, source)),
&mut cur_state,
context,
logs,
Expand Down
2 changes: 1 addition & 1 deletion crates/core/src/pattern/before.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ impl Matcher for Before {
};
let next_node = resolve!(node.next_non_trivia_node());
if !self.before.execute(
&ResolvedPattern::from_node(next_node.source, next_node.node),
&ResolvedPattern::from_node(next_node),
&mut cur_state,
context,
logs,
Expand Down
42 changes: 16 additions & 26 deletions crates/core/src/pattern/built_in_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,28 +402,20 @@ fn distinct_fn<'a>(
Ok(ResolvedPattern::List(unique_list))
}
Some(ResolvedPattern::Binding(binding)) => match binding.last() {
Some(b) => match b {
Binding::List(src, parent_node, field_id) => {
Some(b) => {
if let Some(list_items) = b.list_items() {
let mut unique_list = Vector::new();
for child in parent_node
.children_by_field_id(*field_id, &mut parent_node.walk())
.filter(|child| child.is_named())
{
let resolved = ResolvedPattern::from_node(src, child);
for item in list_items {
let resolved = ResolvedPattern::from_node(item);
if !unique_list.contains(&resolved) {
unique_list.push_back(resolved);
}
}
Ok(ResolvedPattern::List(unique_list))
}
Binding::String(..)
| Binding::FileName(_)
| Binding::Node(..)
| Binding::Empty(..)
| Binding::ConstantRef(_) => {
} else {
bail!("distinct takes a list as the first argument")
}
},
}
None => Ok(ResolvedPattern::Binding(binding)),
},
_ => Err(anyhow!("distinct takes a list as the first argument")),
Expand Down Expand Up @@ -454,19 +446,17 @@ fn shuffle_fn<'a>(
Ok(ResolvedPattern::List(shuffled_list.into()))
}
ResolvedPattern::Binding(binding) => match binding.last() {
Some(Binding::List(src, parent_node, field_id)) => {
let mut list = parent_node
.children_by_field_id(*field_id, &mut parent_node.walk())
.filter(|child| child.is_named())
.collect::<Vec<_>>();
list.shuffle(state.get_rng());
let list = list
.into_iter()
.map(|child| ResolvedPattern::from_node(src, child))
.collect::<Vector<_>>();
Ok(ResolvedPattern::List(list))
Some(b) => {
if let Some(list_items) = b.list_items() {
let mut list: Vec<_> = list_items.collect();
list.shuffle(state.get_rng());
let list: Vector<_> =
list.into_iter().map(ResolvedPattern::from_node).collect();
Ok(ResolvedPattern::List(list))
} else {
Err(anyhow!("shuffle takes a list as the first argument"))
}
}
Some(_) => Err(anyhow!("shuffle takes a list as the first argument")),
None => Err(anyhow!("shuffle argument must be bound")),
},
ResolvedPattern::Snippets(_)
Expand Down
38 changes: 12 additions & 26 deletions crates/core/src/pattern/code_snippet.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
use crate::{binding::Binding, context::Context, resolve};

use super::{
dynamic_snippet::{DynamicPattern, DynamicSnippet},
patterns::{Matcher, Name, Pattern},
resolved_pattern::ResolvedPattern,
variable::{register_variable, VariableSourceLocations},
State,
};
use crate::{context::Context, resolve};
use anyhow::{anyhow, bail, Result};
use core::fmt::Debug;
use marzano_util::{analysis_logs::AnalysisLogs, position::Range};
use std::collections::BTreeMap;
use tree_sitter::Node;

use marzano_language::{
language::{nodes_from_indices, Language, SortId},
target_language::TargetLanguage,
};
use marzano_util::{analysis_logs::AnalysisLogs, position::Range};
use std::collections::BTreeMap;
use tree_sitter::Node;

#[derive(Debug, Clone)]
pub struct CodeSnippet {
pub(crate) patterns: Vec<(SortId, Pattern)>,
Expand Down Expand Up @@ -117,28 +116,15 @@ impl Matcher for CodeSnippet {
}
};

let node = match binding {
Binding::Empty(_, _, _) => return Ok(false),
Binding::Node(_, node) => node.to_owned(),
// maybe String should instead be fake node? eg for comment_content
Binding::String(_, _) => return Ok(false),
Binding::List(_, node, id) => {
let mut cursor = node.walk();
let mut list = node.children_by_field_id(*id, &mut cursor);
if let Some(child) = list.next() {
if list.next().is_some() {
return Ok(false);
}
child
} else {
return Ok(false);
}
}
Binding::FileName(_) => return Ok(false),
Binding::ConstantRef(_) => return Ok(false),
let Some(node) = binding.singleton() else {
return Ok(false);
};

if let Some((_, pattern)) = self.patterns.iter().find(|(id, _)| *id == node.kind_id()) {
if let Some((_, pattern)) = self
.patterns
.iter()
.find(|(id, _)| *id == node.node.kind_id())
{
pattern.execute(resolved_pattern, state, context, logs)
} else {
Ok(false)
Expand Down
67 changes: 30 additions & 37 deletions crates/core/src/pattern/contains.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use super::{
use anyhow::{anyhow, Result};
use core::fmt::Debug;
use im::vector;
use marzano_util::analysis_logs::AnalysisLogs;
use marzano_util::{analysis_logs::AnalysisLogs, node_with_source::NodeWithSource};

use std::collections::BTreeMap;

Expand Down Expand Up @@ -86,7 +86,7 @@ fn execute_until<'a>(
let mut still_computing = true;
while still_computing {
let node = cursor.node();
let node_lhs = ResolvedPattern::from_node(src, node);
let node_lhs = ResolvedPattern::from_node(NodeWithSource::new(node, src));

let state = cur_state.clone();
if the_contained.execute(&node_lhs, &mut cur_state, context, logs)? {
Expand Down Expand Up @@ -137,50 +137,43 @@ impl Matcher for Contains {
match resolved_pattern {
ResolvedPattern::Binding(bindings) => {
let binding = resolve!(bindings.last());
let mut did_match = false;
let mut cur_state = init_state.clone();
let mut cursor; // needed for scope in case of list.
match binding {
Binding::Empty(_, _, _) => Ok(false),
Binding::String(_, _) => Ok(false),
Binding::Node(src, node) => execute_until(
if let Some(node) = binding.as_node() {
execute_until(
init_state,
node,
src,
&node.node,
node.source,
context,
logs,
&self.contains,
&self.until,
),
Binding::List(src, node, field_id) => {
cursor = node.walk();
let children = node.children_by_field_id(*field_id, &mut cursor);

for child in children {
let state = cur_state.clone();
if self.execute(
&ResolvedPattern::from_node(src, child),
&mut cur_state,
context,
logs,
)? {
did_match = true;
} else {
cur_state = state;
}
)
} else if let Some(list_items) = binding.list_items() {
let mut did_match = false;
let mut cur_state = init_state.clone();
for item in list_items {
let state = cur_state.clone();
if self.execute(
&ResolvedPattern::from_node(item),
&mut cur_state,
context,
logs,
)? {
did_match = true;
} else {
cur_state = state;
}
}

if did_match {
*init_state = cur_state;
}
Ok(did_match)
if did_match {
*init_state = cur_state;
}
Binding::FileName(_) => Ok(false),
Ok(did_match)
} else if let Some(_c) = binding.as_constant() {
// this seems like an infinite loop, todo return false?
Binding::ConstantRef(_c) => {
self.contains
.execute(resolved_pattern, init_state, context, logs)
}
self.contains
.execute(resolved_pattern, init_state, context, logs)
} else {
Ok(false)
}
}
ResolvedPattern::List(elements) => {
Expand Down
Loading

0 comments on commit d2956b9

Please sign in to comment.