mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +00:00
more tests and start adding redirects
This commit is contained in:
parent
6f3c41e01c
commit
e945bfac77
2 changed files with 316 additions and 16 deletions
|
@ -12,14 +12,15 @@ pub enum ArgumentBuilderType {
|
|||
/// A node that hasn't yet been built.
|
||||
#[derive(Clone)]
|
||||
pub struct ArgumentBuilder<S: Any + Clone> {
|
||||
value: ArgumentBuilderType,
|
||||
|
||||
arguments: BTreeMap<String, Rc<RefCell<CommandNode<S>>>>,
|
||||
children: BTreeMap<String, Rc<RefCell<CommandNode<S>>>>,
|
||||
literals: BTreeMap<String, Rc<RefCell<CommandNode<S>>>>,
|
||||
arguments: BTreeMap<String, Rc<RefCell<CommandNode<S>>>>,
|
||||
|
||||
executes: Option<Rc<dyn Fn(&CommandContext<S>) -> i32>>,
|
||||
command: Option<Rc<dyn Fn(&CommandContext<S>) -> i32>>,
|
||||
requirement: Rc<dyn Fn(Rc<S>) -> bool>,
|
||||
target: Option<Rc<RefCell<CommandNode<S>>>>,
|
||||
|
||||
value: ArgumentBuilderType,
|
||||
forks: bool,
|
||||
modifier: Option<Rc<dyn RedirectModifier<S>>>,
|
||||
}
|
||||
|
@ -34,10 +35,11 @@ impl<S: Any + Clone> ArgumentBuilder<S> {
|
|||
children: BTreeMap::new(),
|
||||
literals: BTreeMap::new(),
|
||||
arguments: BTreeMap::new(),
|
||||
executes: None,
|
||||
command: None,
|
||||
requirement: Rc::new(|_| true),
|
||||
forks: false,
|
||||
modifier: None,
|
||||
target: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,7 +64,7 @@ impl<S: Any + Clone> ArgumentBuilder<S> {
|
|||
where
|
||||
F: Fn(&CommandContext<S>) -> i32 + 'static,
|
||||
{
|
||||
self.executes = Some(Rc::new(f));
|
||||
self.command = Some(Rc::new(f));
|
||||
self.clone()
|
||||
}
|
||||
|
||||
|
@ -74,6 +76,25 @@ impl<S: Any + Clone> ArgumentBuilder<S> {
|
|||
self.clone()
|
||||
}
|
||||
|
||||
pub fn redirect(&mut self, target: Rc<RefCell<CommandNode<S>>>) -> Self {
|
||||
self.forward(target, None, false)
|
||||
}
|
||||
|
||||
pub fn forward(
|
||||
&mut self,
|
||||
target: Rc<RefCell<CommandNode<S>>>,
|
||||
modifier: Option<Rc<dyn RedirectModifier<S>>>,
|
||||
fork: bool,
|
||||
) -> Self {
|
||||
if !self.arguments.is_empty() {
|
||||
panic!("Cannot forward a node with children");
|
||||
}
|
||||
self.target = Some(target);
|
||||
self.modifier = modifier;
|
||||
self.forks = fork;
|
||||
self.clone()
|
||||
}
|
||||
|
||||
pub fn build(self) -> CommandNode<S> {
|
||||
CommandNode {
|
||||
value: self.value,
|
||||
|
@ -82,9 +103,9 @@ impl<S: Any + Clone> ArgumentBuilder<S> {
|
|||
literals: self.literals,
|
||||
arguments: self.arguments,
|
||||
|
||||
command: self.executes.clone(),
|
||||
command: self.command.clone(),
|
||||
requirement: self.requirement.clone(),
|
||||
redirect: None,
|
||||
redirect: self.target,
|
||||
forks: self.forks,
|
||||
modifier: self.modifier,
|
||||
}
|
||||
|
@ -98,7 +119,7 @@ impl<S: Any + Clone> Debug for ArgumentBuilder<S> {
|
|||
.field("children", &self.children)
|
||||
.field("literals", &self.literals)
|
||||
.field("arguments", &self.arguments)
|
||||
.field("executes", &self.executes.is_some())
|
||||
.field("executes", &self.command.is_some())
|
||||
// .field("requirement", &self.requirement)
|
||||
.field("forks", &self.forks)
|
||||
// .field("modifier", &self.modifier)
|
||||
|
|
|
@ -26,9 +26,10 @@ impl<S: Any + Clone> CommandDispatcher<S> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn register(&mut self, node: ArgumentBuilder<S>) {
|
||||
pub fn register(&mut self, node: ArgumentBuilder<S>) -> Rc<RefCell<CommandNode<S>>> {
|
||||
let build = Rc::new(RefCell::new(node.build()));
|
||||
self.root.borrow_mut().add_child(&build);
|
||||
build
|
||||
}
|
||||
|
||||
pub fn parse(&self, command: StringReader, source: S) -> ParseResults<S> {
|
||||
|
@ -241,7 +242,10 @@ impl<S: Any + Clone> Clone for CommandDispatcher<S> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::builder::literal_argument_builder::literal;
|
||||
use crate::{
|
||||
builder::{literal_argument_builder::literal, required_argument_builder::argument},
|
||||
parsers::integer,
|
||||
};
|
||||
|
||||
struct CommandSource {}
|
||||
|
||||
|
@ -260,7 +264,7 @@ mod tests {
|
|||
// }
|
||||
#[test]
|
||||
fn create_and_execute_command() {
|
||||
let mut subject = CommandDispatcher::<Rc<CommandSource>>::new();
|
||||
let mut subject = CommandDispatcher::new();
|
||||
subject.register(literal("foo").executes(|_| 42));
|
||||
|
||||
assert_eq!(
|
||||
|
@ -279,7 +283,7 @@ mod tests {
|
|||
// }
|
||||
#[test]
|
||||
fn create_and_execute_offset_command() {
|
||||
let mut subject = CommandDispatcher::<Rc<CommandSource>>::new();
|
||||
let mut subject = CommandDispatcher::new();
|
||||
subject.register(literal("foo").executes(|_| 42));
|
||||
|
||||
assert_eq!(
|
||||
|
@ -300,7 +304,7 @@ mod tests {
|
|||
// }
|
||||
#[test]
|
||||
fn create_and_merge_commands() {
|
||||
let mut subject = CommandDispatcher::<Rc<CommandSource>>::new();
|
||||
let mut subject = CommandDispatcher::new();
|
||||
subject.register(literal("base").then(literal("foo").executes(|_| 42)));
|
||||
subject.register(literal("base").then(literal("bar").executes(|_| 42)));
|
||||
|
||||
|
@ -332,7 +336,7 @@ mod tests {
|
|||
// }
|
||||
#[test]
|
||||
fn execute_unknown_command() {
|
||||
let mut subject = CommandDispatcher::<Rc<CommandSource>>::new();
|
||||
let mut subject = CommandDispatcher::new();
|
||||
subject.register(literal("bar"));
|
||||
subject.register(literal("baz"));
|
||||
|
||||
|
@ -359,7 +363,7 @@ mod tests {
|
|||
// }
|
||||
#[test]
|
||||
fn execute_impermissible_command() {
|
||||
let mut subject = CommandDispatcher::<Rc<CommandSource>>::new();
|
||||
let mut subject = CommandDispatcher::new();
|
||||
subject.register(literal("foo").requires(|_| false));
|
||||
|
||||
let execute_result = subject.execute("foo".into(), Rc::new(CommandSource {}));
|
||||
|
@ -371,4 +375,279 @@ mod tests {
|
|||
}
|
||||
assert_eq!(err.cursor().unwrap(), 0);
|
||||
}
|
||||
// @Test
|
||||
// public void testExecuteEmptyCommand() throws Exception {
|
||||
// subject.register(literal(""));
|
||||
|
||||
// try {
|
||||
// subject.execute("", source);
|
||||
// fail();
|
||||
// } catch (final CommandSyntaxException ex) {
|
||||
// assertThat(ex.getType(), is(CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand()));
|
||||
// assertThat(ex.getCursor(), is(0));
|
||||
// }
|
||||
// }
|
||||
#[test]
|
||||
fn execute_empty_command() {
|
||||
let mut subject = CommandDispatcher::new();
|
||||
subject.register(literal(""));
|
||||
|
||||
let execute_result = subject.execute("".into(), Rc::new(CommandSource {}));
|
||||
|
||||
let err = execute_result.err().unwrap();
|
||||
match err.type_ {
|
||||
BuiltInExceptions::DispatcherUnknownCommand => {}
|
||||
_ => panic!("Unexpected error"),
|
||||
}
|
||||
assert_eq!(err.cursor().unwrap(), 0);
|
||||
}
|
||||
// @Test
|
||||
// public void testExecuteUnknownSubcommand() throws Exception {
|
||||
// subject.register(literal("foo").executes(command));
|
||||
|
||||
// try {
|
||||
// subject.execute("foo bar", source);
|
||||
// fail();
|
||||
// } catch (final CommandSyntaxException ex) {
|
||||
// assertThat(ex.getType(), is(CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument()));
|
||||
// assertThat(ex.getCursor(), is(4));
|
||||
// }
|
||||
// }
|
||||
#[test]
|
||||
fn execute_unknown_subcommand() {
|
||||
let mut subject = CommandDispatcher::new();
|
||||
subject.register(literal("foo").executes(|_| 42));
|
||||
|
||||
let execute_result = subject.execute("foo bar".into(), Rc::new(CommandSource {}));
|
||||
|
||||
let err = execute_result.err().unwrap();
|
||||
match err.type_ {
|
||||
BuiltInExceptions::DispatcherUnknownArgument => {}
|
||||
_ => panic!("Unexpected error"),
|
||||
}
|
||||
assert_eq!(err.cursor().unwrap(), 4);
|
||||
}
|
||||
// @Test
|
||||
// public void testExecuteIncorrectLiteral() throws Exception {
|
||||
// subject.register(literal("foo").executes(command).then(literal("bar")));
|
||||
|
||||
// try {
|
||||
// subject.execute("foo baz", source);
|
||||
// fail();
|
||||
// } catch (final CommandSyntaxException ex) {
|
||||
// assertThat(ex.getType(), is(CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument()));
|
||||
// assertThat(ex.getCursor(), is(4));
|
||||
// }
|
||||
// }
|
||||
#[test]
|
||||
fn execute_incorrect_literal() {
|
||||
let mut subject = CommandDispatcher::new();
|
||||
subject.register(literal("foo").executes(|_| 42).then(literal("bar")));
|
||||
|
||||
let execute_result = subject.execute("foo baz".into(), Rc::new(CommandSource {}));
|
||||
|
||||
let err = execute_result.err().unwrap();
|
||||
match err.type_ {
|
||||
BuiltInExceptions::DispatcherUnknownArgument => {}
|
||||
_ => panic!("Unexpected error"),
|
||||
}
|
||||
assert_eq!(err.cursor().unwrap(), 4);
|
||||
}
|
||||
// @Test
|
||||
// public void testExecuteAmbiguousIncorrectArgument() throws Exception {
|
||||
// subject.register(
|
||||
// literal("foo").executes(command)
|
||||
// .then(literal("bar"))
|
||||
// .then(literal("baz"))
|
||||
// );
|
||||
|
||||
// try {
|
||||
// subject.execute("foo unknown", source);
|
||||
// fail();
|
||||
// } catch (final CommandSyntaxException ex) {
|
||||
// assertThat(ex.getType(), is(CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument()));
|
||||
// assertThat(ex.getCursor(), is(4));
|
||||
// }
|
||||
// }
|
||||
#[test]
|
||||
fn execute_ambiguous_incorrect_argument() {
|
||||
let mut subject = CommandDispatcher::new();
|
||||
subject.register(
|
||||
literal("foo")
|
||||
.executes(|_| 42)
|
||||
.then(literal("bar"))
|
||||
.then(literal("baz")),
|
||||
);
|
||||
|
||||
let execute_result = subject.execute("foo unknown".into(), Rc::new(CommandSource {}));
|
||||
|
||||
let err = execute_result.err().unwrap();
|
||||
match err.type_ {
|
||||
BuiltInExceptions::DispatcherUnknownArgument => {}
|
||||
_ => panic!("Unexpected error"),
|
||||
}
|
||||
assert_eq!(err.cursor().unwrap(), 4);
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testExecuteSubcommand() throws Exception {
|
||||
// final Command<Object> subCommand = mock(Command.class);
|
||||
// when(subCommand.run(any())).thenReturn(100);
|
||||
|
||||
// subject.register(literal("foo").then(
|
||||
// literal("a")
|
||||
// ).then(
|
||||
// literal("=").executes(subCommand)
|
||||
// ).then(
|
||||
// literal("c")
|
||||
// ).executes(command));
|
||||
|
||||
// assertThat(subject.execute("foo =", source), is(100));
|
||||
// verify(subCommand).run(any(CommandContext.class));
|
||||
// }
|
||||
#[test]
|
||||
fn test_execute_subcommand() {
|
||||
let mut subject = CommandDispatcher::new();
|
||||
|
||||
subject.register(
|
||||
literal("foo")
|
||||
.then(literal("a"))
|
||||
.then(literal("=").executes(|_| 100))
|
||||
.then(literal("c"))
|
||||
.executes(|_| 42),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
subject
|
||||
.execute("foo =".into(), Rc::new(CommandSource {}))
|
||||
.unwrap(),
|
||||
100
|
||||
);
|
||||
}
|
||||
// @Test
|
||||
// public void testParseIncompleteLiteral() throws Exception {
|
||||
// subject.register(literal("foo").then(literal("bar").executes(command)));
|
||||
|
||||
// final ParseResults<Object> parse = subject.parse("foo ", source);
|
||||
// assertThat(parse.getReader().getRemaining(), equalTo(" "));
|
||||
// assertThat(parse.getContext().getNodes().size(), is(1));
|
||||
// }
|
||||
#[test]
|
||||
fn test_parse_incomplete_literal() {
|
||||
let mut subject = CommandDispatcher::new();
|
||||
subject.register(literal("foo").then(literal("bar").executes(|_| 42)));
|
||||
|
||||
let parse = subject.parse("foo ".into(), Rc::new(CommandSource {}));
|
||||
assert_eq!(parse.reader.remaining(), " ");
|
||||
assert_eq!(parse.context.nodes.len(), 1);
|
||||
}
|
||||
// @Test
|
||||
// public void testParseIncompleteArgument() throws Exception {
|
||||
// subject.register(literal("foo").then(argument("bar", integer()).executes(command)));
|
||||
|
||||
// final ParseResults<Object> parse = subject.parse("foo ", source);
|
||||
// assertThat(parse.getReader().getRemaining(), equalTo(" "));
|
||||
// assertThat(parse.getContext().getNodes().size(), is(1));
|
||||
// }
|
||||
#[test]
|
||||
fn test_parse_incomplete_argument() {
|
||||
let mut subject = CommandDispatcher::new();
|
||||
subject.register(literal("foo").then(argument("bar", integer()).executes(|_| 42)));
|
||||
|
||||
let parse = subject.parse("foo ".into(), Rc::new(CommandSource {}));
|
||||
assert_eq!(parse.reader.remaining(), " ");
|
||||
assert_eq!(parse.context.nodes.len(), 1);
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testExecuteAmbiguiousParentSubcommand() throws Exception {
|
||||
// final Command<Object> subCommand = mock(Command.class);
|
||||
// when(subCommand.run(any())).thenReturn(100);
|
||||
|
||||
// subject.register(
|
||||
// literal("test")
|
||||
// .then(
|
||||
// argument("incorrect", integer())
|
||||
// .executes(command)
|
||||
// )
|
||||
// .then(
|
||||
// argument("right", integer())
|
||||
// .then(
|
||||
// argument("sub", integer())
|
||||
// .executes(subCommand)
|
||||
// )
|
||||
// )
|
||||
// );
|
||||
|
||||
// assertThat(subject.execute("test 1 2", source), is(100));
|
||||
// verify(subCommand).run(any(CommandContext.class));
|
||||
// verify(command, never()).run(any());
|
||||
// }
|
||||
#[test]
|
||||
fn test_execute_ambiguious_parent_subcommand() {
|
||||
let mut subject = CommandDispatcher::new();
|
||||
|
||||
subject.register(
|
||||
literal("test")
|
||||
.then(argument("incorrect", integer()).executes(|_| 42))
|
||||
.then(
|
||||
argument("right", integer()).then(argument("sub", integer()).executes(|_| 100)),
|
||||
),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
subject
|
||||
.execute("test 1 2".into(), Rc::new(CommandSource {}))
|
||||
.unwrap(),
|
||||
100
|
||||
);
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testExecuteAmbiguiousParentSubcommandViaRedirect() throws Exception {
|
||||
// final Command<Object> subCommand = mock(Command.class);
|
||||
// when(subCommand.run(any())).thenReturn(100);
|
||||
|
||||
// final LiteralCommandNode<Object> real = subject.register(
|
||||
// literal("test")
|
||||
// .then(
|
||||
// argument("incorrect", integer())
|
||||
// .executes(command)
|
||||
// )
|
||||
// .then(
|
||||
// argument("right", integer())
|
||||
// .then(
|
||||
// argument("sub", integer())
|
||||
// .executes(subCommand)
|
||||
// )
|
||||
// )
|
||||
// );
|
||||
|
||||
// subject.register(literal("redirect").redirect(real));
|
||||
|
||||
// assertThat(subject.execute("redirect 1 2", source), is(100));
|
||||
// verify(subCommand).run(any(CommandContext.class));
|
||||
// verify(command, never()).run(any());
|
||||
// }
|
||||
// #[test]
|
||||
// fn test_execute_ambiguious_parent_subcommand_via_redirect() {
|
||||
// let mut subject = CommandDispatcher::new();
|
||||
|
||||
// let real = subject.register(
|
||||
// literal("test")
|
||||
// .then(argument("incorrect", integer()).executes(|_| 42))
|
||||
// .then(
|
||||
// argument("right", integer()).then(argument("sub", integer()).executes(|_| 100)),
|
||||
// ),
|
||||
// );
|
||||
|
||||
// subject.register(literal("redirect").redirect(real));
|
||||
|
||||
// assert_eq!(
|
||||
// subject
|
||||
// .execute("redirect 1 2".into(), Rc::new(CommandSource {}))
|
||||
// .unwrap(),
|
||||
// 100
|
||||
// );
|
||||
// }
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue