Skip to content
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
7 changes: 7 additions & 0 deletions proptest-regressions/domain/lexical_scope/tests/property.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Seeds for failure cases proptest has generated in the past. It is
# automatically read and these particular cases re-run before any
# novel cases are generated.
#
# It is recommended to check this file in to source control so that
# everyone who runs the test benefits from these saved cases.
cc aa2c89921549b725fd6d19803ed345a5c69e25e36c3e5af9b185cc271dc96384 # shrinks to count = 1
7 changes: 7 additions & 0 deletions proptest-regressions/domain/package/tests/add_export.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Seeds for failure cases proptest has generated in the past. It is
# automatically read and these particular cases re-run before any
# novel cases are generated.
#
# It is recommended to check this file in to source control so that
# everyone who runs the test benefits from these saved cases.
cc c30c07b2fcda86b095d61cd5831bb7cb620baf0207cc55f1d72ad0168cba8a47 # shrinks to package = "a", symbol = "a"
7 changes: 7 additions & 0 deletions proptest-regressions/domain/package/tests/merge_options.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Seeds for failure cases proptest has generated in the past. It is
# automatically read and these particular cases re-run before any
# novel cases are generated.
#
# It is recommended to check this file in to source control so that
# everyone who runs the test benefits from these saved cases.
cc fd8f5ca493deed6f17aa556dd701edf1c5e24c596dba9b2dc8d7a811d814c0e7 # shrinks to package = "a", mut symbols = ["a", "b"]
7 changes: 7 additions & 0 deletions proptest-regressions/domain/package/tests/rename.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Seeds for failure cases proptest has generated in the past. It is
# automatically read and these particular cases re-run before any
# novel cases are generated.
#
# It is recommended to check this file in to source control so that
# everyone who runs the test benefits from these saved cases.
cc 00e6776bf24d8eed932106bbf7fdd15d5d02f3a8bb6a107a6f4751e24a29a432 # shrinks to from = "a", to = "a.a", symbol = "a"
7 changes: 7 additions & 0 deletions proptest-regressions/domain/package/tests/sort_exports.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Seeds for failure cases proptest has generated in the past. It is
# automatically read and these particular cases re-run before any
# novel cases are generated.
#
# It is recommended to check this file in to source control so that
# everyone who runs the test benefits from these saved cases.
cc b4e1c869e62416cc01a52c09f5deb90cc8ae69d618a90ad16f85d2f11aed3c77 # shrinks to package = "a", mut symbols = ["a", "aa"]
7 changes: 7 additions & 0 deletions proptest-regressions/domain/package/tests/sort_options.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Seeds for failure cases proptest has generated in the past. It is
# automatically read and these particular cases re-run before any
# novel cases are generated.
#
# It is recommended to check this file in to source control so that
# everyone who runs the test benefits from these saved cases.
cc 8b75b40d618a71bb30508a771d4569c96ac7b021df9e4c8f0614b0d4ec0b541c # shrinks to package = "a", mut option_indexes = [0, 1]
58 changes: 57 additions & 1 deletion src/application/usecase/conditional_sugar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use crate::domain::sexpr::SyntaxTree;
pub use domain::{ConditionalConversionPlan, ConditionalConversionRequest};

fn safe(request: &ConditionalConversionRequest<'_>) -> Result<()> {
let tree = SyntaxTree::parse(request.input)?;
domain::require_supported_dialect(request.dialect)?;
let tree = SyntaxTree::parse_with_dialect(request.input, request.dialect)?;
Ok(reject_common_lisp_reader_conditionals(
&tree,
request.dialect,
Expand Down Expand Up @@ -40,3 +41,58 @@ pub fn plan_convert_if_to_unless(
safe(&request)?;
domain::plan_convert_if_to_unless(request)
}

#[cfg(test)]
mod tests {
use super::*;
use crate::domain::dialect::Dialect;

const DIALECTS: [Dialect; 7] = [
Dialect::CommonLisp,
Dialect::EmacsLisp,
Dialect::Scheme,
Dialect::Clojure,
Dialect::Janet,
Dialect::Fennel,
Dialect::Unknown,
];

fn request(input: &str, dialect: Dialect) -> ConditionalConversionRequest<'_> {
ConditionalConversionRequest {
input,
dialect,
path: "0".parse().expect("path"),
}
}

#[test]
fn every_command_gates_all_dialects_before_parsing() {
let support_error = "conditional conversion supports only Common Lisp and Emacs Lisp";
for dialect in DIALECTS {
let errors = [
plan_convert_when_to_if(request(")", dialect)).unwrap_err(),
plan_convert_unless_to_if(request(")", dialect)).unwrap_err(),
plan_convert_if_to_when(request(")", dialect)).unwrap_err(),
plan_convert_if_to_unless(request(")", dialect)).unwrap_err(),
];
for error in errors {
if matches!(dialect, Dialect::CommonLisp | Dialect::EmacsLisp) {
assert_ne!(error.to_string(), support_error, "{dialect:?}: {error:#}");
} else {
assert_eq!(error.to_string(), support_error, "{dialect:?}");
}
}
}
}

#[test]
fn supported_reader_collisions_use_the_requested_dialect() {
for (dialect, input) in [
(Dialect::CommonLisp, r"(when ok one two) #\)"),
(Dialect::EmacsLisp, r"(when ok one two) ?\)"),
] {
let plan = plan_convert_when_to_if(request(input, dialect)).expect("conversion");
assert!(plan.changed);
}
}
}
54 changes: 53 additions & 1 deletion src/application/usecase/convert_cond_to_if.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,59 @@ use crate::domain::sexpr::SyntaxTree;
pub use domain::{ConvertCondToIfPlan, ConvertCondToIfRequest};

pub fn plan_convert_cond_to_if(request: ConvertCondToIfRequest<'_>) -> Result<ConvertCondToIfPlan> {
let tree = SyntaxTree::parse(request.input)?;
domain::require_supported_dialect(request.dialect, "convert-cond-to-if")?;
let tree = SyntaxTree::parse_with_dialect(request.input, request.dialect)?;
reject_common_lisp_reader_conditionals(&tree, request.dialect)?;
domain::plan_convert_cond_to_if(request)
}

#[cfg(test)]
mod tests {
use super::*;
use crate::domain::dialect::Dialect;

const DIALECTS: [Dialect; 7] = [
Dialect::CommonLisp,
Dialect::EmacsLisp,
Dialect::Scheme,
Dialect::Clojure,
Dialect::Janet,
Dialect::Fennel,
Dialect::Unknown,
];

fn request<'a>(input: &'a str, dialect: Dialect, path: &str) -> ConvertCondToIfRequest<'a> {
ConvertCondToIfRequest {
input,
dialect,
path: path.parse().expect("path"),
}
}

#[test]
fn all_dialects_are_gated_before_parsing() {
let support_error = "convert-cond-to-if currently supports only Common Lisp and Emacs Lisp";
for dialect in DIALECTS {
let error = plan_convert_cond_to_if(request(")", dialect, "0")).unwrap_err();
if matches!(dialect, Dialect::CommonLisp | Dialect::EmacsLisp) {
assert_ne!(error.to_string(), support_error, "{dialect:?}: {error:#}");
} else {
assert_eq!(error.to_string(), support_error, "{dialect:?}");
}
}
}

#[test]
fn supported_reader_collisions_use_the_requested_dialect() {
for (dialect, input) in [
(
Dialect::CommonLisp,
r"#\) (cond (ready yes) ((quote t) no))",
),
(Dialect::EmacsLisp, r"?\) (cond (ready yes) ((quote t) no))"),
] {
let plan = plan_convert_cond_to_if(request(input, dialect, "1")).expect("conversion");
assert!(plan.changed);
}
}
}
54 changes: 49 additions & 5 deletions src/application/usecase/convert_flet_to_labels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
use anyhow::Result;

use crate::application::usecase::mutation_safety::reject_common_lisp_reader_conditionals;
use crate::domain::dialect::Dialect;
use crate::domain::local_function_binding as domain;
use crate::domain::sexpr::SyntaxTree;

Expand All @@ -12,9 +11,54 @@ pub use domain::{ConvertFletToLabelsPlan, ConvertFletToLabelsRequest};
pub fn plan_convert_flet_to_labels(
request: ConvertFletToLabelsRequest<'_>,
) -> Result<ConvertFletToLabelsPlan> {
let tree = SyntaxTree::parse(request.input)?;
if request.dialect == Dialect::CommonLisp {
reject_common_lisp_reader_conditionals(&tree, request.dialect)?;
}
domain::validate_convert_flet_to_labels_dialect(request.dialect)?;
let tree = SyntaxTree::parse_with_dialect(request.input, request.dialect)?;
reject_common_lisp_reader_conditionals(&tree, request.dialect)?;
domain::plan_convert_flet_to_labels(request)
}

#[cfg(test)]
mod tests {
use super::*;
use crate::domain::dialect::Dialect;

#[test]
fn accepts_common_lisp_reader_literal() {
let input = r"#\) (flet ((helper (value) value)) (helper 1))";
let plan = plan_convert_flet_to_labels(ConvertFletToLabelsRequest {
input,
dialect: Dialect::CommonLisp,
path: "1".parse().expect("path"),
})
.expect("plan");

assert_eq!(
plan.rewritten,
r"#\) (labels ((helper (value) value)) (helper 1))"
);
}

#[test]
fn unsupported_dialect_gate_precedes_parsing() {
for dialect in [
Dialect::EmacsLisp,
Dialect::Scheme,
Dialect::Clojure,
Dialect::Janet,
Dialect::Fennel,
Dialect::Unknown,
] {
let error = plan_convert_flet_to_labels(ConvertFletToLabelsRequest {
input: ")",
dialect,
path: "0".parse().expect("path"),
})
.expect_err("unsupported dialect");

assert_eq!(
error.to_string(),
"convert-flet-to-labels supports only Common Lisp"
);
}
}
}
51 changes: 50 additions & 1 deletion src/application/usecase/convert_if_to_cond.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,56 @@ use crate::domain::sexpr::SyntaxTree;
pub use domain::{ConvertIfToCondPlan, ConvertIfToCondRequest};

pub fn plan_convert_if_to_cond(request: ConvertIfToCondRequest<'_>) -> Result<ConvertIfToCondPlan> {
let tree = SyntaxTree::parse(request.input)?;
domain::require_supported_dialect(request.dialect, "convert-if-to-cond")?;
let tree = SyntaxTree::parse_with_dialect(request.input, request.dialect)?;
reject_common_lisp_reader_conditionals(&tree, request.dialect)?;
domain::plan_convert_if_to_cond(request)
}

#[cfg(test)]
mod tests {
use super::*;
use crate::domain::dialect::Dialect;

const DIALECTS: [Dialect; 7] = [
Dialect::CommonLisp,
Dialect::EmacsLisp,
Dialect::Scheme,
Dialect::Clojure,
Dialect::Janet,
Dialect::Fennel,
Dialect::Unknown,
];

fn request<'a>(input: &'a str, dialect: Dialect, path: &str) -> ConvertIfToCondRequest<'a> {
ConvertIfToCondRequest {
input,
dialect,
path: path.parse().expect("path"),
}
}

#[test]
fn all_dialects_are_gated_before_parsing() {
let support_error = "convert-if-to-cond currently supports only Common Lisp and Emacs Lisp";
for dialect in DIALECTS {
let error = plan_convert_if_to_cond(request(")", dialect, "0")).unwrap_err();
if matches!(dialect, Dialect::CommonLisp | Dialect::EmacsLisp) {
assert_ne!(error.to_string(), support_error, "{dialect:?}: {error:#}");
} else {
assert_eq!(error.to_string(), support_error, "{dialect:?}");
}
}
}

#[test]
fn supported_reader_collisions_use_the_requested_dialect() {
for (dialect, input) in [
(Dialect::CommonLisp, r"#\) (if ready yes no)"),
(Dialect::EmacsLisp, r"?\) (if ready yes no)"),
] {
let plan = plan_convert_if_to_cond(request(input, dialect, "1")).expect("conversion");
assert!(plan.changed);
}
}
}
54 changes: 49 additions & 5 deletions src/application/usecase/convert_labels_to_flet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
use anyhow::Result;

use crate::application::usecase::mutation_safety::reject_common_lisp_reader_conditionals;
use crate::domain::dialect::Dialect;
use crate::domain::local_function_binding as domain;
use crate::domain::sexpr::SyntaxTree;

Expand All @@ -12,9 +11,54 @@ pub use domain::{ConvertLabelsToFletPlan, ConvertLabelsToFletRequest};
pub fn plan_convert_labels_to_flet(
request: ConvertLabelsToFletRequest<'_>,
) -> Result<ConvertLabelsToFletPlan> {
let tree = SyntaxTree::parse(request.input)?;
if request.dialect == Dialect::CommonLisp {
reject_common_lisp_reader_conditionals(&tree, request.dialect)?;
}
domain::validate_convert_labels_to_flet_dialect(request.dialect)?;
let tree = SyntaxTree::parse_with_dialect(request.input, request.dialect)?;
reject_common_lisp_reader_conditionals(&tree, request.dialect)?;
domain::plan_convert_labels_to_flet(request)
}

#[cfg(test)]
mod tests {
use super::*;
use crate::domain::dialect::Dialect;

#[test]
fn accepts_common_lisp_reader_literal() {
let input = r"#\) (labels ((helper (value) value)) (helper 1))";
let plan = plan_convert_labels_to_flet(ConvertLabelsToFletRequest {
input,
dialect: Dialect::CommonLisp,
path: "1".parse().expect("path"),
})
.expect("plan");

assert_eq!(
plan.rewritten,
r"#\) (flet ((helper (value) value)) (helper 1))"
);
}

#[test]
fn unsupported_dialect_gate_precedes_parsing() {
for dialect in [
Dialect::EmacsLisp,
Dialect::Scheme,
Dialect::Clojure,
Dialect::Janet,
Dialect::Fennel,
Dialect::Unknown,
] {
let error = plan_convert_labels_to_flet(ConvertLabelsToFletRequest {
input: ")",
dialect,
path: "0".parse().expect("path"),
})
.expect_err("unsupported dialect");

assert_eq!(
error.to_string(),
"convert-labels-to-flet supports only Common Lisp"
);
}
}
}
Loading