Skip to content

Commit 14197c9

Browse files
authored
chore: TS test improvements / missing AST coverage (#65)
* chore: splitting tests into specific categories * wip: working on await function test * test: adding await examples * test: splitting up tests * test: enahcning binary operation tests * chore: add more expression tests * chore: fixing new expression * chore: adding conditional expression handling * chore: updating conditional queries * chore: super express query example * chore: adding yield expression test * chore: adding statement tests * chore: adding an empty file for block statement * chore: adding for statement coverage * chore: support Value when generating types from sql * chore: fix test and fix the logic around computing Value from SQL * chore: support while and with * chore: cargo fmt * chore: filter out empty string queries in parse source before sending off to SQL parser * chore: update snapshot * chore: adding ; so the logic proceeds without returning * chore: optional chaining * chore: opt chaining test * chore: class accessors * chore: update tests * chore: remove todos
1 parent 887f3ae commit 14197c9

File tree

87 files changed

+3288
-2130
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+3288
-2130
lines changed

src/core/execute.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use std::path::PathBuf;
1212
use swc_common::errors::Handler;
1313

1414
pub fn execute(queries: &HashMap<PathBuf, Vec<SQL>>, handler: &Handler) -> Result<bool> {
15-
// TODO: later we will add mysql_explain, sqlite_explain depending on the database type
1615
let mut failed = false;
1716
let should_generate_types = &CONFIG
1817
.generate_types_config

src/parser/mod.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,18 +176,20 @@ fn recurse_and_find_sql(mut sqls: &mut Vec<SQL>, stmt: &Stmt, import_alias: &Str
176176
let span: MultiSpan = var.span.into();
177177
let new_sqls = get_sql_from_var_decl(var_decl, &span, import_alias);
178178
let num_new_sqls = new_sqls.len();
179+
179180
sqls.extend(new_sqls);
180181

181182
// We've already found the sqls based on the variable name, we should skip processing further
182183
if num_new_sqls > 0 {
183184
continue;
184185
}
185-
186+
// Try to retrieve name of the variable
187+
let name = var_decl.name.as_ident().map(|ident| ident.sym.to_string());
186188
// this is when the variable name is not found due to syntax like
187189
// const [rows, i] = await connection.execute....
188190
if let Some(init) = &var_decl.init {
189191
let expr = *init.clone();
190-
get_sql_from_expr(&mut sqls, &None, &expr, &span, import_alias);
192+
get_sql_from_expr(&mut sqls, &name, &expr, &span, import_alias);
191193
}
192194
}
193195
}
@@ -277,7 +279,10 @@ pub fn parse_source(path: &PathBuf) -> Result<(HashMap<PathBuf, Vec<SQL>>, Handl
277279
match item {
278280
ModuleItem::Stmt(stmt) => {
279281
let mut sqls = vec![];
280-
recurse_and_find_sql(&mut sqls, stmt, &import_alias).unwrap();
282+
recurse_and_find_sql(&mut sqls, stmt, &import_alias)?;
283+
// This is to prevent any emptry string queries being inserted into sqls_map
284+
// which will be used to run `PREPARE` step and SQL parser logic
285+
let sqls: Vec<SQL> = sqls.into_iter().filter(|sql| !sql.query.is_empty()).collect();
281286
insert_or_append_sqls(&mut sqls_map, &sqls, path);
282287
}
283288
_ => {}

src/parser/tag.rs

Lines changed: 79 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::common::SQL;
22
use swc_common::MultiSpan;
3-
use swc_ecma_ast::{BlockStmt, ClassMember, Expr, Pat, Prop, PropOrSpread, SuperProp, VarDeclarator};
3+
use swc_ecma_ast::{BlockStmt, ClassMember, Expr, OptChainBase, Pat, Prop, PropOrSpread, SuperProp, VarDeclarator};
44

55
use super::{get_var_decl_name_from_key, recurse_and_find_sql};
66

@@ -21,7 +21,8 @@ pub fn process_block_stmt_as_expr(
2121
let expr = &expr.expr;
2222
get_sql_from_expr(sqls, var_decl_name, expr, span, import_alias);
2323
} else {
24-
recurse_and_find_sql(sqls, stmt, import_alias);
24+
// TODO: we should be using `?` and return Results
25+
recurse_and_find_sql(sqls, stmt, import_alias).unwrap();
2526
}
2627
}
2728
}
@@ -83,7 +84,7 @@ pub fn get_sql_from_expr<'a>(
8384
}
8485
}
8586
for arg in &call_expr.args {
86-
get_sql_from_expr(sqls, var_decl_name, &arg.expr, span, import_alias)
87+
get_sql_from_expr(sqls, var_decl_name, &arg.expr, span, import_alias);
8788
}
8889
}
8990
Expr::This(_) => {}
@@ -103,24 +104,23 @@ pub fn get_sql_from_expr<'a>(
103104
Prop::Shorthand(_) => {}
104105
Prop::KeyValue(key_val) => {
105106
let value = &key_val.value;
106-
get_sql_from_expr(sqls, var_decl_name, value, span, import_alias)
107+
get_sql_from_expr(sqls, var_decl_name, value, span, import_alias);
107108
}
108109
Prop::Assign(assign) => {
109110
let value = &assign.value;
110-
get_sql_from_expr(sqls, var_decl_name, value, span, import_alias)
111+
get_sql_from_expr(sqls, var_decl_name, value, span, import_alias);
111112
}
112113
Prop::Getter(getter) => {
113114
let body = &getter.body;
114-
process_block_stmt_as_expr(body, sqls, var_decl_name, span, import_alias)
115+
process_block_stmt_as_expr(body, sqls, var_decl_name, span, import_alias);
115116
}
116-
// TODO: add test
117117
Prop::Setter(setter) => {
118118
let body = &setter.body;
119-
process_block_stmt_as_expr(body, sqls, var_decl_name, span, import_alias)
119+
process_block_stmt_as_expr(body, sqls, var_decl_name, span, import_alias);
120120
}
121121
Prop::Method(method) => {
122122
let body = &method.function.body;
123-
process_block_stmt_as_expr(body, sqls, var_decl_name, span, import_alias)
123+
process_block_stmt_as_expr(body, sqls, var_decl_name, span, import_alias);
124124
}
125125
},
126126
}
@@ -142,8 +142,13 @@ pub fn get_sql_from_expr<'a>(
142142
get_sql_from_expr(sqls, var_decl_name, right, span, import_alias);
143143
}
144144
Expr::Assign(assign) => {
145-
let expr = &assign.right;
146-
return get_sql_from_expr(sqls, var_decl_name, expr, span, import_alias);
145+
let right_expr = &assign.right;
146+
get_sql_from_expr(sqls, var_decl_name, right_expr, span, import_alias);
147+
148+
let left_expr = &assign.left;
149+
left_expr
150+
.as_expr()
151+
.map(|expr| get_sql_from_expr(sqls, var_decl_name, &expr, span, import_alias));
147152
}
148153
Expr::Member(member) => {
149154
let obj = &member.obj;
@@ -159,22 +164,50 @@ pub fn get_sql_from_expr<'a>(
159164
}
160165
}
161166
}
162-
Expr::Cond(_) => {}
167+
Expr::Cond(cond) => {
168+
let test = &cond.test;
169+
let cons = &cond.cons;
170+
let alt = &cond.alt;
171+
get_sql_from_expr(sqls, var_decl_name, test, span, import_alias);
172+
get_sql_from_expr(sqls, var_decl_name, cons, span, import_alias);
173+
get_sql_from_expr(sqls, var_decl_name, alt, span, import_alias);
174+
}
163175
Expr::New(expr) => {
176+
let args = &expr.args;
164177
let expr = &expr.callee;
165-
return get_sql_from_expr(sqls, var_decl_name, expr, span, import_alias);
178+
if let Some(args) = &args {
179+
for arg in args {
180+
get_sql_from_expr(sqls, var_decl_name, &arg.expr, span, import_alias);
181+
}
182+
}
183+
184+
get_sql_from_expr(sqls, var_decl_name, expr, span, import_alias);
166185
}
167186
Expr::Seq(seq) => {
168187
let exprs = &seq.exprs;
169188
for expr in exprs {
170-
get_sql_from_expr(sqls, var_decl_name, expr, span, import_alias)
189+
get_sql_from_expr(sqls, var_decl_name, expr, span, import_alias);
171190
}
172191
}
173192
Expr::Ident(ident) => {}
174193
Expr::Lit(lit) => {}
175194
Expr::Tpl(tpl) => {
195+
let new_sqls: Vec<SQL> = tpl
196+
.quasis
197+
.iter()
198+
.map(|tpl_element| SQL {
199+
var_decl_name: var_decl_name.to_owned(),
200+
query: tpl_element.raw.to_string(),
201+
span: span.clone(),
202+
})
203+
.collect();
204+
205+
if !new_sqls.is_empty() {
206+
sqls.extend(new_sqls);
207+
}
208+
176209
for expr in &tpl.exprs {
177-
get_sql_from_expr(sqls, var_decl_name, expr, span, import_alias)
210+
get_sql_from_expr(sqls, var_decl_name, expr, span, import_alias);
178211
}
179212
}
180213
Expr::Arrow(arrow) => {
@@ -183,7 +216,14 @@ pub fn get_sql_from_expr<'a>(
183216
process_block_stmt_as_expr(&block_stmt, sqls, var_decl_name, span, import_alias);
184217

185218
if let Some(expr) = expr {
186-
return get_sql_from_expr(sqls, var_decl_name, expr, span, import_alias);
219+
get_sql_from_expr(sqls, var_decl_name, expr, span, import_alias);
220+
}
221+
222+
for param in &arrow.params {
223+
let param = param.as_expr();
224+
if let Some(expr) = &param {
225+
get_sql_from_expr(sqls, var_decl_name, expr, span, import_alias);
226+
}
187227
}
188228
}
189229
Expr::Class(class) => {
@@ -203,11 +243,11 @@ pub fn get_sql_from_expr<'a>(
203243
}
204244
ClassMember::Method(method) => {
205245
let body = &method.function.body;
206-
process_block_stmt_as_expr(body, sqls, var_decl_name, span, import_alias)
246+
process_block_stmt_as_expr(body, sqls, var_decl_name, span, import_alias);
207247
}
208248
ClassMember::PrivateMethod(private_method) => {
209249
let body = &private_method.function.body;
210-
process_block_stmt_as_expr(body, sqls, var_decl_name, span, import_alias)
250+
process_block_stmt_as_expr(body, sqls, var_decl_name, span, import_alias);
211251
}
212252
ClassMember::ClassProp(class_prop) => {
213253
let body = &class_prop.value;
@@ -225,15 +265,15 @@ pub fn get_sql_from_expr<'a>(
225265
ClassMember::Empty(_) => {}
226266
ClassMember::StaticBlock(static_block) => {
227267
let body = &static_block.body;
228-
process_block_stmt_as_expr(&Some(body.clone()), sqls, var_decl_name, span, import_alias)
268+
process_block_stmt_as_expr(&Some(body.clone()), sqls, var_decl_name, span, import_alias);
229269
}
230270
ClassMember::AutoAccessor(auto_accessor) => {
231271
let value = &auto_accessor.value;
232272
let key = &auto_accessor.key;
233273

234274
if let Some(expr) = &value {
235275
let var_decl_name = &get_var_decl_name_from_key(&key);
236-
get_sql_from_expr(sqls, var_decl_name, expr, span, import_alias)
276+
get_sql_from_expr(sqls, var_decl_name, expr, span, import_alias);
237277
}
238278
}
239279
}
@@ -254,6 +294,25 @@ pub fn get_sql_from_expr<'a>(
254294
let expr = &paren.expr;
255295
return get_sql_from_expr(sqls, var_decl_name, expr, span, import_alias);
256296
}
297+
Expr::OptChain(opt_chain) => {
298+
let expr = &*opt_chain.base;
299+
match &expr {
300+
OptChainBase::Member(member) => {
301+
let obj = &member.obj;
302+
get_sql_from_expr(sqls, var_decl_name, obj, span, import_alias);
303+
}
304+
OptChainBase::Call(call) => {
305+
let expr = &call.callee;
306+
get_sql_from_expr(sqls, var_decl_name, &expr, span, import_alias);
307+
308+
let args = &call.args;
309+
for arg in args.iter() {
310+
let expr = &arg.expr;
311+
get_sql_from_expr(sqls, var_decl_name, &expr, span, import_alias);
312+
}
313+
}
314+
}
315+
}
257316
Expr::JSXMember(_) => {}
258317
Expr::JSXNamespacedName(_) => {}
259318
Expr::JSXEmpty(_) => {}
@@ -264,7 +323,6 @@ pub fn get_sql_from_expr<'a>(
264323
Expr::TsAs(_) => {}
265324
Expr::TsInstantiation(_) => {}
266325
Expr::PrivateName(_) => {}
267-
Expr::OptChain(_) => {}
268326
Expr::Invalid(_) => {}
269327
Expr::TsSatisfies(_) => {}
270328
}

src/ts_generator/sql_parser/expressions/translate_data_type.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,26 @@ use crate::{
33
ts_generator::types::ts_query::TsFieldType,
44
};
55
use sqlparser::ast::DataType;
6+
use sqlparser::ast::Value;
7+
8+
pub fn translate_value(value: &Value) -> Option<TsFieldType> {
9+
match &value {
10+
Value::Number(_, _) => Some(TsFieldType::Number),
11+
Value::SingleQuotedString(_) => Some(TsFieldType::String),
12+
Value::DollarQuotedString(_) => Some(TsFieldType::String),
13+
Value::EscapedStringLiteral(_) => Some(TsFieldType::String),
14+
Value::SingleQuotedByteStringLiteral(_) => Some(TsFieldType::String),
15+
Value::DoubleQuotedByteStringLiteral(_) => Some(TsFieldType::String),
16+
Value::RawStringLiteral(_) => Some(TsFieldType::String),
17+
Value::NationalStringLiteral(_) => Some(TsFieldType::String),
18+
Value::HexStringLiteral(_) => Some(TsFieldType::String),
19+
Value::DoubleQuotedString(_) => Some(TsFieldType::String),
20+
Value::Boolean(_) => Some(TsFieldType::Boolean),
21+
Value::Null => Some(TsFieldType::Null),
22+
Value::UnQuotedString(_) => Some(TsFieldType::String),
23+
Value::Placeholder(_) => None,
24+
}
25+
}
626

727
pub fn translate_data_type(data_type: &DataType) -> TsFieldType {
828
match &data_type {

src/ts_generator/sql_parser/expressions/translate_expr.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::common::lazy::{CONFIG, DB_SCHEMA};
22
use crate::ts_generator::errors::TsGeneratorError;
3+
use crate::ts_generator::sql_parser::expressions::translate_data_type::translate_value;
34
use crate::ts_generator::sql_parser::expressions::translate_table_with_joins::translate_table_from_expr;
45
use crate::ts_generator::sql_parser::expressions::{
56
functions::is_string_function, translate_data_type::translate_data_type,
@@ -298,7 +299,14 @@ pub fn translate_expr(
298299
db_conn,
299300
is_selection,
300301
),
301-
Expr::Value(placeholder) => ts_query.insert_param(&TsFieldType::Boolean, &Some(placeholder.to_string())),
302+
Expr::Value(placeholder) => {
303+
let ts_field_type = translate_value(&placeholder);
304+
305+
if let Some(ts_field_type) = ts_field_type {
306+
return ts_query.insert_result(alias, &[ts_field_type], is_selection, expr_for_logging);
307+
}
308+
ts_query.insert_param(&TsFieldType::Boolean, &Some(placeholder.to_string()))
309+
}
302310
Expr::JsonAccess {
303311
left: _,
304312
operator: _,

0 commit comments

Comments
 (0)