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

feat(grit): implement GritQL log() function #4003

Merged
merged 1 commit into from
Sep 19, 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
11 changes: 10 additions & 1 deletion crates/biome_grit_patterns/src/grit_binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,16 @@ impl<'a> Binding<'a, GritQueryContext> for GritBinding<'a> {
}

fn get_sexp(&self) -> Option<String> {
None
Some(match self {
Self::File(path) => format!("({})", path.display()),
Self::Node(grit_target_node) => format!("({grit_target_node:?})"),
Self::Range(text_range, source) => format!(
"({})",
&source[text_range.start().into()..text_range.end().into()]
),
Self::Empty(_, _) => "(empty)".to_owned(),
Self::Constant(constant) => format!("({constant})"),
})
}

fn position(&self, _language: &GritTargetLanguage) -> Option<Range> {
Expand Down
6 changes: 3 additions & 3 deletions crates/biome_grit_patterns/src/grit_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use grit_pattern_matcher::file_owners::{FileOwner, FileOwners};
use grit_pattern_matcher::pattern::{
FilePtr, FileRegistry, Matcher, Pattern, ResolvedPattern, State, VariableSourceLocations,
};
use grit_util::{Ast, ByteRange, InputRanges, Range, VariableMatch};
use grit_util::{AnalysisLogs, Ast, ByteRange, InputRanges, Range, VariableMatch};
use im::Vector;
use std::collections::{BTreeMap, BTreeSet};
use std::ffi::OsStr;
Expand Down Expand Up @@ -64,7 +64,7 @@ pub struct GritQuery {
}

impl GritQuery {
pub fn execute(&self, file: GritTargetFile) -> Result<Vec<GritQueryResult>> {
pub fn execute(&self, file: GritTargetFile) -> Result<(Vec<GritQueryResult>, AnalysisLogs)> {
let file_owners = FileOwners::new();
let files = vec![file];
let file_ptr = FilePtr::new(0, 0);
Expand Down Expand Up @@ -100,7 +100,7 @@ impl GritQuery {
}
}

Ok(results)
Ok((results, logs))
}

pub fn from_node(
Expand Down
12 changes: 10 additions & 2 deletions crates/biome_grit_patterns/src/grit_target_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::util::TextRangeGritExt;
use biome_js_syntax::{JsSyntaxKind, JsSyntaxNode, JsSyntaxToken};
use biome_rowan::{NodeOrToken, SyntaxKind, SyntaxSlot, TextRange};
use grit_util::{AstCursor, AstNode as GritAstNode, ByteRange, CodeRange};
use std::{borrow::Cow, ops::Deref, str::Utf8Error};
use std::{borrow::Cow, fmt::Debug, ops::Deref, str::Utf8Error};

use NodeOrToken::*;

Expand Down Expand Up @@ -187,7 +187,7 @@ generate_target_node! {
[JsLanguage, JsSyntaxNode, JsSyntaxToken, JsSyntaxKind]
}

#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, PartialEq)]
pub struct GritTargetNode<'a> {
node: GritTargetLanguageNode,
tree: &'a GritTargetTree,
Expand Down Expand Up @@ -263,6 +263,14 @@ impl<'a> GritTargetNode<'a> {
}
}

impl<'a> Debug for GritTargetNode<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("GritTargetNode")
.field("node", &self.node)
.finish()
}
}

impl<'a> Deref for GritTargetNode<'a> {
type Target = GritTargetLanguageNode;

Expand Down
1 change: 1 addition & 0 deletions crates/biome_grit_patterns/src/pattern_compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ mod limit_compiler;
mod list_compiler;
mod list_index_compiler;
mod literal_compiler;
mod log_compiler;
mod map_accessor_compiler;
mod map_compiler;
mod match_compiler;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use super::{compilation_context::NodeCompilationContext, PatternCompiler};
use super::{
compilation_context::NodeCompilationContext, log_compiler::LogCompiler, PatternCompiler,
};
use crate::{grit_context::GritQueryContext, CompileError, NodeLikeArgumentError};
use biome_grit_syntax::{
AnyGritMaybeNamedArg, AnyGritPattern, GritNamedArgList, GritNodeLike, GritSyntaxKind,
Expand All @@ -18,6 +20,11 @@ pub(super) fn call_pattern_from_node_with_name(
context: &mut NodeCompilationContext,
is_rhs: bool,
) -> Result<Pattern<GritQueryContext>, CompileError> {
if name == "log" {
return LogCompiler::from_named_args(node.named_args(), context)
.map(|log| Pattern::Log(Box::new(log)));
}

let named_args = named_args_from_node(node, &name, context)?;
let mut args = named_args_to_map(named_args, context)?;
let named_args_count = node.named_args().into_iter().count();
Expand Down
33 changes: 33 additions & 0 deletions crates/biome_grit_patterns/src/pattern_compiler/log_compiler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use super::call_compiler::*;
use super::compilation_context::NodeCompilationContext;
use crate::{grit_context::GritQueryContext, CompileError};
use biome_grit_syntax::GritNamedArgList;
use grit_pattern_matcher::pattern::{Log, Pattern, VariableInfo};

pub(crate) struct LogCompiler;

impl LogCompiler {
pub(crate) fn from_named_args(
named_args: GritNamedArgList,
context: &mut NodeCompilationContext,
) -> Result<Log<GritQueryContext>, CompileError> {
let named_args = node_to_args_pairs(
"log",
named_args,
&context.compilation.lang,
&Some(vec!["message".to_owned(), "variable".to_owned()]),
)?;
let mut args = named_args_to_map(named_args, context)?;
let message = args.remove("$message");
let variable = args.remove("$variable");
let variable = variable.and_then(|pattern| match pattern {
Pattern::Variable(variable) => {
let source_location = &context.vars_array[variable.scope][variable.index];
Some(VariableInfo::new(source_location.name.clone(), variable))
}
_ => None,
});

Ok(Log::new(variable, message))
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
use super::call_compiler::*;
use super::compilation_context::NodeCompilationContext;
use super::log_compiler::LogCompiler;
use crate::NodeLikeArgumentError;
use crate::{grit_context::GritQueryContext, CompileError};
use biome_grit_syntax::GritPredicateCall;
use biome_rowan::AstNode;
use grit_pattern_matcher::pattern::PrCall;
use grit_pattern_matcher::pattern::{PrCall, Predicate};

pub(crate) struct PrCallCompiler;

impl PrCallCompiler {
pub(crate) fn from_node(
node: &GritPredicateCall,
context: &mut NodeCompilationContext,
) -> Result<PrCall<GritQueryContext>, CompileError> {
) -> Result<Predicate<GritQueryContext>, CompileError> {
let name = node.name()?;
let name = name.text();

if name == "log" {
return LogCompiler::from_named_args(node.named_args(), context).map(Predicate::Log);
}

let info = if let Some(info) = context.compilation.predicate_definition_info.get(&name) {
info
} else if let Some(info) = context.compilation.function_definition_info.get(&name) {
Expand All @@ -37,6 +42,6 @@ impl PrCallCompiler {
}

let args = match_args_to_params(&name, args, &params, &context.compilation.lang)?;
Ok(PrCall::new(info.index, args))
Ok(Predicate::Call(Box::new(PrCall::new(info.index, args))))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@ impl PredicateCompiler {
AnyGritPredicate::GritPredicateAssignment(node) => Ok(Predicate::Assignment(Box::new(
PrAssignmentCompiler::from_node(node, context)?,
))),
AnyGritPredicate::GritPredicateCall(node) => Ok(Predicate::Call(Box::new(
PrCallCompiler::from_node(node, context)?,
))),
AnyGritPredicate::GritPredicateCall(node) => PrCallCompiler::from_node(node, context),
AnyGritPredicate::GritPredicateEqual(node) => Ok(Predicate::Equal(Box::new(
PrEqualCompiler::from_node(node, context)?,
))),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,38 +523,6 @@ mod tests {
,
),
),
tree: GritTargetTree {
root: JsLanguage(
Node(
0: JS_MODULE@0..20
0: (empty)
1: (empty)
2: JS_DIRECTIVE_LIST@0..0
3: JS_MODULE_ITEM_LIST@0..20
0: JS_EXPRESSION_STATEMENT@0..20
0: JS_CALL_EXPRESSION@0..20
0: JS_STATIC_MEMBER_EXPRESSION@0..11
0: JS_IDENTIFIER_EXPRESSION@0..7
0: JS_REFERENCE_IDENTIFIER@0..7
0: IDENT@0..7 "console" [] []
1: DOT@7..8 "." [] []
2: JS_NAME@8..11
0: IDENT@8..11 "log" [] []
1: (empty)
2: (empty)
3: JS_CALL_ARGUMENTS@11..20
0: L_PAREN@11..12 "(" [] []
1: JS_CALL_ARGUMENT_LIST@12..19
0: JS_STRING_LITERAL_EXPRESSION@12..19
0: JS_STRING_LITERAL@12..19 "'hello'" [] []
2: R_PAREN@19..20 ")" [] []
1: (empty)
4: EOF@20..20 "" [] []
,
),
),
source: "console.log('hello')",
},
}
"###);
}
Expand Down
25 changes: 18 additions & 7 deletions crates/biome_grit_patterns/tests/quick_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use biome_js_syntax::JsFileSource;
#[test]
fn test_query() {
let parse_grit_result = parse_grit(
"`console.log($args)` where {
$args <: contains `world`
"`console.log($arg)` => . where {
log(message=\"This is a debug log\", variable=$arg),
}
",
);
Expand All @@ -28,16 +28,27 @@ fn test_query() {
println!("Diagnostics from compiling query:\n{:?}", query.diagnostics);
}

let body = r#"console.log("hello, world");
console.log("hello", world);
console.log(`hello ${world}`);
"#;
let body = r#"console.log("grape");"#;

let file = GritTargetFile {
path: "test.js".into(),
parse: parse(body, JsFileSource::tsx(), JsParserOptions::default()).into(),
};
let results = query.execute(file).expect("could not execute query");
let (results, logs) = query.execute(file).expect("could not execute query");

println!("Results: {results:#?}");

if !logs.is_empty() {
println!(
"\n## Logs\n\n{}",
logs.iter()
.map(|log| format!(
"Message: {}Syntax: {}",
log.message,
log.syntax_tree.as_deref().unwrap_or_default()
))
.collect::<Vec<_>>()
.join("\n")
);
}
}
19 changes: 17 additions & 2 deletions crates/biome_grit_patterns/tests/spec_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,27 @@ fn run_test(input: &'static str, _: &str, _: &str, _: &str) {
}
};

let results = query
let (results, logs) = query
.execute(target_file)
.unwrap_or_else(|err| panic!("cannot execute query from {query_path:?}: {err:?}"));
let snapshot_result = SnapshotResult::from_query_results(results);

let snapshot = format!("{snapshot_result:#?}");
let snapshot = if logs.is_empty() {
format!("{snapshot_result:#?}")
} else {
let logs = logs
.iter()
.map(|log| {
format!(
"Message: {}Syntax: {}",
log.message,
log.syntax_tree.as_deref().unwrap_or_default()
)
})
.collect::<Vec<_>>()
.join("\n");
format!("{snapshot_result:#?}\n\n## Logs\n\n{logs}")
};

insta::with_settings!({
prepend_module_to_snapshot => false,
Expand Down
3 changes: 3 additions & 0 deletions crates/biome_grit_patterns/tests/specs/ts/log.grit
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
`console.log($arg)` => . where {
log(message="This is a debug log", variable=$arg),
}
17 changes: 17 additions & 0 deletions crates/biome_grit_patterns/tests/specs/ts/log.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
source: crates/biome_grit_patterns/tests/spec_tests.rs
expression: log
---
SnapshotResult {
messages: [],
matched_ranges: [
"1:1-1:21",
],
rewritten_files: [],
created_files: [],
}

## Logs

Message: This is a debug log
Syntax: (GritTargetNode { node: JsLanguage(Node(JS_CALL_ARGUMENT_LIST@12..19)) })
1 change: 1 addition & 0 deletions crates/biome_grit_patterns/tests/specs/ts/log.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log("grape");
2 changes: 1 addition & 1 deletion crates/biome_service/src/file_handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@ pub(crate) fn search(
query: &GritQuery,
_settings: WorkspaceSettingsHandle,
) -> Result<Vec<TextRange>, WorkspaceError> {
let query_result = query
let (query_result, _logs) = query
.execute(GritTargetFile {
path: path.to_path_buf(),
parse,
Expand Down