mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
Fix clippy issues and add a couple tests to dispatcher
This commit is contained in:
parent
10cd1733cb
commit
2e90422561
33 changed files with 158 additions and 79 deletions
|
@ -41,21 +41,21 @@ impl<S: Any + Clone> ArgumentBuilder<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn then(&mut self, node: ArgumentBuilder<S>) -> &mut Self {
|
pub fn then(&mut self, node: ArgumentBuilder<S>) -> Self {
|
||||||
let built_node = node.build();
|
let built_node = node.build();
|
||||||
let name = built_node.name();
|
let name = built_node.name();
|
||||||
let node_reference = Rc::new(RefCell::new(built_node.clone()));
|
let node_reference = Rc::new(RefCell::new(built_node.clone()));
|
||||||
self.children
|
self.children
|
||||||
.insert(name.to_string(), node_reference.clone());
|
.insert(name.to_string(), node_reference.clone());
|
||||||
match &built_node.value {
|
match &built_node.value {
|
||||||
ArgumentBuilderType::Literal(literal) => {
|
ArgumentBuilderType::Literal(_) => {
|
||||||
self.literals.insert(name.to_string(), node_reference);
|
self.literals.insert(name.to_string(), node_reference);
|
||||||
}
|
}
|
||||||
ArgumentBuilderType::Argument(argument) => {
|
ArgumentBuilderType::Argument(_) => {
|
||||||
self.arguments.insert(name.to_string(), node_reference);
|
self.arguments.insert(name.to_string(), node_reference);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self
|
self.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn executes<F>(&mut self, f: F) -> Self
|
pub fn executes<F>(&mut self, f: F) -> Self
|
||||||
|
|
|
@ -1,14 +1,5 @@
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
|
||||||
use crate::{
|
|
||||||
context::CommandContextBuilder,
|
|
||||||
exceptions::{
|
|
||||||
builtin_exceptions::BuiltInExceptions, command_syntax_exception::CommandSyntaxException,
|
|
||||||
},
|
|
||||||
string_range::StringRange,
|
|
||||||
string_reader::StringReader,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::argument_builder::{ArgumentBuilder, ArgumentBuilderType};
|
use super::argument_builder::{ArgumentBuilder, ArgumentBuilderType};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
|
|
|
@ -16,7 +16,7 @@ impl Argument {
|
||||||
pub fn new(name: &str, parser: Rc<dyn Parser>) -> Self {
|
pub fn new(name: &str, parser: Rc<dyn Parser>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
parser: parser,
|
parser,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,9 +41,6 @@ impl Debug for Argument {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shortcut for creating a new argument builder node.
|
/// Shortcut for creating a new argument builder node.
|
||||||
pub fn argument<'a, S: Any + Clone>(
|
pub fn argument<S: Any + Clone>(name: &str, parser: impl Parser + 'static) -> ArgumentBuilder<S> {
|
||||||
name: &'a str,
|
|
||||||
parser: impl Parser + 'static,
|
|
||||||
) -> ArgumentBuilder<S> {
|
|
||||||
ArgumentBuilder::new(Argument::new(name, Rc::new(parser)).into())
|
ArgumentBuilder::new(Argument::new(name, Rc::new(parser)).into())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{any::Any, cell::RefCell, collections::HashMap, fmt::Debug, ptr, rc::Rc};
|
use std::{any::Any, cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
dispatcher::CommandDispatcher, modifier::RedirectModifier, string_range::StringRange,
|
dispatcher::CommandDispatcher, modifier::RedirectModifier, string_range::StringRange,
|
||||||
|
@ -73,7 +73,7 @@ impl<S: Any + Clone> CommandContextBuilder<S> {
|
||||||
nodes: self.nodes.clone(),
|
nodes: self.nodes.clone(),
|
||||||
source: self.source.clone(),
|
source: self.source.clone(),
|
||||||
command: self.command.clone(),
|
command: self.command.clone(),
|
||||||
child: self.child.clone().map(|c| Rc::new(c.build(&input))),
|
child: self.child.clone().map(|c| Rc::new(c.build(input))),
|
||||||
range: self.range.clone(),
|
range: self.range.clone(),
|
||||||
forks: self.forks,
|
forks: self.forks,
|
||||||
modifier: self.modifier.clone(),
|
modifier: self.modifier.clone(),
|
||||||
|
@ -125,7 +125,7 @@ impl<S: Any + Clone> CommandContext<S> {
|
||||||
if Rc::ptr_eq(&source, &self.source) {
|
if Rc::ptr_eq(&source, &self.source) {
|
||||||
return self.clone();
|
return self.clone();
|
||||||
}
|
}
|
||||||
return CommandContext {
|
CommandContext {
|
||||||
source,
|
source,
|
||||||
input: self.input.clone(),
|
input: self.input.clone(),
|
||||||
arguments: self.arguments.clone(),
|
arguments: self.arguments.clone(),
|
||||||
|
@ -136,11 +136,11 @@ impl<S: Any + Clone> CommandContext<S> {
|
||||||
child: self.child.clone(),
|
child: self.child.clone(),
|
||||||
modifier: self.modifier.clone(),
|
modifier: self.modifier.clone(),
|
||||||
forks: self.forks,
|
forks: self.forks,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_nodes(&self) -> bool {
|
pub fn has_nodes(&self) -> bool {
|
||||||
return !self.nodes.is_empty();
|
!self.nodes.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn argument(&self, name: &str) -> Option<Rc<dyn Any>> {
|
pub fn argument(&self, name: &str) -> Option<Rc<dyn Any>> {
|
||||||
|
|
|
@ -75,8 +75,7 @@ impl<S: Any + Clone> CommandDispatcher<S> {
|
||||||
reader.cursor = cursor;
|
reader.cursor = cursor;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if reader.can_read() {
|
if reader.can_read() && reader.peek() != ' ' {
|
||||||
if reader.peek() != ' ' {
|
|
||||||
errors.insert(
|
errors.insert(
|
||||||
Rc::new((*child.borrow()).clone()),
|
Rc::new((*child.borrow()).clone()),
|
||||||
BuiltInExceptions::DispatcherExpectedArgumentSeparator
|
BuiltInExceptions::DispatcherExpectedArgumentSeparator
|
||||||
|
@ -85,7 +84,6 @@ impl<S: Any + Clone> CommandDispatcher<S> {
|
||||||
reader.cursor = cursor;
|
reader.cursor = cursor;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
context.with_command(&child.borrow().command);
|
context.with_command(&child.borrow().command);
|
||||||
if reader.can_read_length(if child.borrow().redirect.is_none() {
|
if reader.can_read_length(if child.borrow().redirect.is_none() {
|
||||||
|
@ -120,7 +118,7 @@ impl<S: Any + Clone> CommandDispatcher<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if potentials.len() > 0 {
|
if !potentials.is_empty() {
|
||||||
if potentials.len() > 1 {
|
if potentials.len() > 1 {
|
||||||
potentials.sort_by(|a, b| {
|
potentials.sort_by(|a, b| {
|
||||||
if !a.reader.can_read() && b.reader.can_read() {
|
if !a.reader.can_read() && b.reader.can_read() {
|
||||||
|
@ -174,11 +172,11 @@ impl<S: Any + Clone> CommandDispatcher<S> {
|
||||||
let mut forked = false;
|
let mut forked = false;
|
||||||
let mut found_command = false;
|
let mut found_command = false;
|
||||||
let command = parse.reader.string();
|
let command = parse.reader.string();
|
||||||
let original = parse.context.build(&command);
|
let original = parse.context.build(command);
|
||||||
let mut contexts = vec![original];
|
let mut contexts = vec![original];
|
||||||
let mut next: Vec<CommandContext<S>> = vec![];
|
let mut next: Vec<CommandContext<S>> = vec![];
|
||||||
|
|
||||||
while contexts.len() > 0 {
|
while !contexts.is_empty() {
|
||||||
for context in contexts.iter() {
|
for context in contexts.iter() {
|
||||||
let child = &context.child;
|
let child = &context.child;
|
||||||
if let Some(child) = child {
|
if let Some(child) = child {
|
||||||
|
@ -239,3 +237,111 @@ impl<S: Any + Clone> Clone for CommandDispatcher<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::builder::literal_argument_builder::literal;
|
||||||
|
|
||||||
|
struct CommandSource {}
|
||||||
|
|
||||||
|
fn input_with_offset(input: &str, offset: usize) -> StringReader {
|
||||||
|
let mut result: StringReader = input.into();
|
||||||
|
result.cursor = offset;
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Test
|
||||||
|
// public void testCreateAndExecuteCommand() throws Exception {
|
||||||
|
// subject.register(literal("foo").executes(command));
|
||||||
|
|
||||||
|
// assertThat(subject.execute("foo", source), is(42));
|
||||||
|
// verify(command).run(any(CommandContext.class));
|
||||||
|
// }
|
||||||
|
#[test]
|
||||||
|
fn create_and_execute_command() {
|
||||||
|
let mut subject = CommandDispatcher::<Rc<CommandSource>>::new();
|
||||||
|
subject.register(literal("foo").executes(|_| 42));
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
subject
|
||||||
|
.execute("foo".into(), Rc::new(CommandSource {}))
|
||||||
|
.unwrap(),
|
||||||
|
42
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// @Test
|
||||||
|
// public void testCreateAndExecuteOffsetCommand() throws Exception {
|
||||||
|
// subject.register(literal("foo").executes(command));
|
||||||
|
|
||||||
|
// assertThat(subject.execute(inputWithOffset("/foo", 1), source), is(42));
|
||||||
|
// verify(command).run(any(CommandContext.class));
|
||||||
|
// }
|
||||||
|
#[test]
|
||||||
|
fn create_and_execute_offset_command() {
|
||||||
|
let mut subject = CommandDispatcher::<Rc<CommandSource>>::new();
|
||||||
|
subject.register(literal("foo").executes(|_| 42));
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
subject
|
||||||
|
.execute(input_with_offset("/foo", 1), Rc::new(CommandSource {}))
|
||||||
|
.unwrap(),
|
||||||
|
42
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// @Test
|
||||||
|
// public void testCreateAndMergeCommands() throws Exception {
|
||||||
|
// subject.register(literal("base").then(literal("foo").executes(command)));
|
||||||
|
// subject.register(literal("base").then(literal("bar").executes(command)));
|
||||||
|
|
||||||
|
// assertThat(subject.execute("base foo", source), is(42));
|
||||||
|
// assertThat(subject.execute("base bar", source), is(42));
|
||||||
|
// verify(command, times(2)).run(any(CommandContext.class));
|
||||||
|
// }
|
||||||
|
#[test]
|
||||||
|
fn create_and_merge_commands() {
|
||||||
|
let mut subject = CommandDispatcher::<Rc<CommandSource>>::new();
|
||||||
|
subject.register(literal("base").then(literal("foo").executes(|_| 42)));
|
||||||
|
subject.register(literal("base").then(literal("bar").executes(|_| 42)));
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
subject
|
||||||
|
.execute("base foo".into(), Rc::new(CommandSource {}))
|
||||||
|
.unwrap(),
|
||||||
|
42
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
subject
|
||||||
|
.execute("base bar".into(), Rc::new(CommandSource {}))
|
||||||
|
.unwrap(),
|
||||||
|
42
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// @Test
|
||||||
|
// public void testExecuteUnknownCommand() throws Exception {
|
||||||
|
// subject.register(literal("bar"));
|
||||||
|
// subject.register(literal("baz"));
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// subject.execute("foo", source);
|
||||||
|
// fail();
|
||||||
|
// } catch (final CommandSyntaxException ex) {
|
||||||
|
// assertThat(ex.getType(), is(CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand()));
|
||||||
|
// assertThat(ex.getCursor(), is(0));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// #[test]
|
||||||
|
// fn execute_unknown_command() {
|
||||||
|
// let mut subject = CommandDispatcher::<Rc<CommandSource>>::new();
|
||||||
|
// subject.register(literal("bar"));
|
||||||
|
// subject.register(literal("baz"));
|
||||||
|
|
||||||
|
// assert_eq!(
|
||||||
|
// subject
|
||||||
|
// .execute("foo".into(), Rc::new(CommandSource {}))
|
||||||
|
// .err()
|
||||||
|
// .unwrap(),
|
||||||
|
// BuiltInExceptions::DispatcherUnknownCommand.create()
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use std::{cmp, fmt, rc::Rc};
|
use std::{cmp, fmt};
|
||||||
|
|
||||||
use super::builtin_exceptions::BuiltInExceptions;
|
use super::builtin_exceptions::BuiltInExceptions;
|
||||||
use crate::message::Message;
|
use crate::message::Message;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct CommandSyntaxException {
|
pub struct CommandSyntaxException {
|
||||||
type_: BuiltInExceptions,
|
type_: BuiltInExceptions,
|
||||||
message: Message,
|
message: Message,
|
||||||
|
@ -12,7 +12,6 @@ pub struct CommandSyntaxException {
|
||||||
}
|
}
|
||||||
|
|
||||||
const CONTEXT_AMOUNT: usize = 10;
|
const CONTEXT_AMOUNT: usize = 10;
|
||||||
const ENABLE_COMMAND_STACK_TRACES: bool = true;
|
|
||||||
|
|
||||||
impl CommandSyntaxException {
|
impl CommandSyntaxException {
|
||||||
pub fn new(type_: BuiltInExceptions, message: Message, input: &str, cursor: usize) -> Self {
|
pub fn new(type_: BuiltInExceptions, message: Message, input: &str, cursor: usize) -> Self {
|
||||||
|
@ -76,8 +75,8 @@ impl CommandSyntaxException {
|
||||||
&self.type_
|
&self.type_
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn input(&self) -> String {
|
pub fn input(&self) -> &Option<String> {
|
||||||
self.input()
|
&self.input
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cursor(&self) -> Option<usize> {
|
pub fn cursor(&self) -> Option<usize> {
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct Message(String);
|
pub struct Message(String);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{any::Any, marker::PhantomData, rc::Rc};
|
use std::{any::Any, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::CommandContext,
|
context::CommandContext,
|
||||||
|
@ -24,6 +24,7 @@ impl Parser for Integer {
|
||||||
let result = reader.read_int()?;
|
let result = reader.read_int()?;
|
||||||
if let Some(minimum) = self.minimum {
|
if let Some(minimum) = self.minimum {
|
||||||
if result < minimum {
|
if result < minimum {
|
||||||
|
reader.cursor = start;
|
||||||
return Err(BuiltInExceptions::IntegerTooSmall {
|
return Err(BuiltInExceptions::IntegerTooSmall {
|
||||||
found: result,
|
found: result,
|
||||||
min: minimum,
|
min: minimum,
|
||||||
|
@ -33,6 +34,7 @@ impl Parser for Integer {
|
||||||
}
|
}
|
||||||
if let Some(maximum) = self.maximum {
|
if let Some(maximum) = self.maximum {
|
||||||
if result > maximum {
|
if result > maximum {
|
||||||
|
reader.cursor = start;
|
||||||
return Err(BuiltInExceptions::IntegerTooBig {
|
return Err(BuiltInExceptions::IntegerTooBig {
|
||||||
found: result,
|
found: result,
|
||||||
max: maximum,
|
max: maximum,
|
||||||
|
@ -52,5 +54,5 @@ pub fn get_integer<S: Any + Clone>(context: &CommandContext<S>, name: &str) -> O
|
||||||
.argument(name)
|
.argument(name)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.downcast_ref::<i32>()
|
.downcast_ref::<i32>()
|
||||||
.map(|x| *x)
|
.copied()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::exceptions::{
|
use crate::exceptions::{
|
||||||
builtin_exceptions::BuiltInExceptions, command_syntax_exception::CommandSyntaxException,
|
builtin_exceptions::BuiltInExceptions, command_syntax_exception::CommandSyntaxException,
|
||||||
};
|
};
|
||||||
use std::{rc::Rc, str::FromStr};
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct StringReader {
|
pub struct StringReader {
|
||||||
|
@ -79,7 +79,7 @@ impl StringReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_allowed_number(c: char) -> bool {
|
pub fn is_allowed_number(c: char) -> bool {
|
||||||
c >= '0' && c <= '9' || c == '.' || c == '-'
|
('0'..='9').contains(&c) || c == '.' || c == '-'
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_quoted_string_start(c: char) -> bool {
|
pub fn is_quoted_string_start(c: char) -> bool {
|
||||||
|
@ -177,9 +177,9 @@ impl StringReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_allowed_in_unquoted_string(c: char) -> bool {
|
pub fn is_allowed_in_unquoted_string(c: char) -> bool {
|
||||||
c >= '0' && c <= '9'
|
('0'..='9').contains(&c)
|
||||||
|| c >= 'A' && c <= 'Z'
|
|| ('A'..='Z').contains(&c)
|
||||||
|| c >= 'a' && c <= 'z'
|
|| ('a'..='z').contains(&c)
|
||||||
|| c == '_'
|
|| c == '_'
|
||||||
|| c == '-'
|
|| c == '-'
|
||||||
|| c == '.'
|
|| c == '.'
|
||||||
|
@ -232,7 +232,7 @@ impl StringReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Err(BuiltInExceptions::ReaderExpectedEndOfQuote.create_with_context(self));
|
Err(BuiltInExceptions::ReaderExpectedEndOfQuote.create_with_context(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_string(&mut self) -> Result<String, CommandSyntaxException> {
|
pub fn read_string(&mut self) -> Result<String, CommandSyntaxException> {
|
||||||
|
@ -255,12 +255,12 @@ impl StringReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
if value == "true" {
|
if value == "true" {
|
||||||
return Ok(true);
|
Ok(true)
|
||||||
} else if value == "false" {
|
} else if value == "false" {
|
||||||
return Ok(false);
|
Ok(false)
|
||||||
} else {
|
} else {
|
||||||
self.cursor = start;
|
self.cursor = start;
|
||||||
return Err(BuiltInExceptions::ReaderInvalidBool { value }.create_with_context(self));
|
Err(BuiltInExceptions::ReaderInvalidBool { value }.create_with_context(self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,15 +11,7 @@ use crate::{
|
||||||
string_range::StringRange,
|
string_range::StringRange,
|
||||||
string_reader::StringReader,
|
string_reader::StringReader,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{any::Any, cell::RefCell, collections::BTreeMap, fmt::Debug, hash::Hash, ptr, rc::Rc};
|
||||||
any::Any,
|
|
||||||
cell::RefCell,
|
|
||||||
collections::{BTreeMap, HashMap},
|
|
||||||
fmt::Debug,
|
|
||||||
hash::Hash,
|
|
||||||
ptr,
|
|
||||||
rc::Rc,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// An ArgumentBuilder that has been built.
|
/// An ArgumentBuilder that has been built.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -67,7 +59,7 @@ impl<S: Any + Clone> CommandNode<S> {
|
||||||
pub fn get_relevant_nodes(&self, input: &mut StringReader) -> Vec<Rc<RefCell<CommandNode<S>>>> {
|
pub fn get_relevant_nodes(&self, input: &mut StringReader) -> Vec<Rc<RefCell<CommandNode<S>>>> {
|
||||||
let literals = self.literals();
|
let literals = self.literals();
|
||||||
|
|
||||||
if literals.len() > 0 {
|
if !literals.is_empty() {
|
||||||
let cursor = input.cursor();
|
let cursor = input.cursor();
|
||||||
while input.can_read() && input.peek() != ' ' {
|
while input.can_read() && input.peek() != ' ' {
|
||||||
input.skip();
|
input.skip();
|
||||||
|
@ -83,18 +75,10 @@ impl<S: Any + Clone> CommandNode<S> {
|
||||||
if let Some(literal) = literal {
|
if let Some(literal) = literal {
|
||||||
return vec![literal.clone()];
|
return vec![literal.clone()];
|
||||||
} else {
|
} else {
|
||||||
return self
|
return self.arguments().values().cloned().collect();
|
||||||
.arguments()
|
|
||||||
.values()
|
|
||||||
.map(|argument| argument.clone())
|
|
||||||
.collect();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return self
|
self.arguments().values().cloned().collect()
|
||||||
.arguments()
|
|
||||||
.values()
|
|
||||||
.map(|argument| argument.clone())
|
|
||||||
.collect();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +131,7 @@ impl<S: Any + Clone> CommandNode<S> {
|
||||||
.expect("Couldn't get result for some reason");
|
.expect("Couldn't get result for some reason");
|
||||||
let parsed = ParsedArgument {
|
let parsed = ParsedArgument {
|
||||||
range: StringRange::between(start, reader.cursor()),
|
range: StringRange::between(start, reader.cursor()),
|
||||||
result: result,
|
result,
|
||||||
};
|
};
|
||||||
|
|
||||||
context_builder.with_argument(&argument.name, parsed.clone());
|
context_builder.with_argument(&argument.name, parsed.clone());
|
||||||
|
@ -175,7 +159,7 @@ impl<S: Any + Clone> CommandNode<S> {
|
||||||
|
|
||||||
fn parse(&self, reader: &mut StringReader) -> Option<usize> {
|
fn parse(&self, reader: &mut StringReader) -> Option<usize> {
|
||||||
match self.value {
|
match self.value {
|
||||||
ArgumentBuilderType::Argument(ref argument) => {
|
ArgumentBuilderType::Argument(_) => {
|
||||||
panic!("Can't parse argument.")
|
panic!("Can't parse argument.")
|
||||||
}
|
}
|
||||||
ArgumentBuilderType::Literal(ref literal) => {
|
ArgumentBuilderType::Literal(ref literal) => {
|
||||||
|
@ -252,7 +236,9 @@ impl<S: Any + Clone> PartialEq for CommandNode<S> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if let Some(selfexecutes) = &self.command {
|
if let Some(selfexecutes) = &self.command {
|
||||||
|
// idk how to do this better since we can't compare `dyn Fn`s
|
||||||
if let Some(otherexecutes) = &other.command {
|
if let Some(otherexecutes) = &other.command {
|
||||||
|
#[allow(clippy::vtable_address_comparisons)]
|
||||||
if !Rc::ptr_eq(selfexecutes, otherexecutes) {
|
if !Rc::ptr_eq(selfexecutes, otherexecutes) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -260,6 +246,9 @@ impl<S: Any + Clone> PartialEq for CommandNode<S> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if other.command.is_some() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
|
|
Loading…
Add table
Reference in a new issue