diff --git a/src/dmdoc/main.rs b/src/dmdoc/main.rs index 13f8b794..275c8bc5 100644 --- a/src/dmdoc/main.rs +++ b/src/dmdoc/main.rs @@ -248,7 +248,7 @@ fn main() -> Result<(), Box> { type_path: format_type_path(&p.var_type.type_path), }).collect(), decl: match proc.declaration { - Some(ref decl) => if decl.is_verb { "verb" } else { "proc" }, + Some(ref decl) => decl.kind.name(), None => "", }, file: context.file_path(proc_value.location.file), diff --git a/src/dreammaker/ast.rs b/src/dreammaker/ast.rs index 3d85fee6..04a33922 100644 --- a/src/dreammaker/ast.rs +++ b/src/dreammaker/ast.rs @@ -493,6 +493,47 @@ impl From for Follow { } } +/// The proc declaration kind, either `proc` or `verb`. +/// +/// DM requires referinging proc paths to include whether the target is +/// declared as a proc or verb, even though the two modes are functionally +/// identical in many other respects. +#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)] +pub enum ProcDeclKind { + Proc, + Verb, +} + +impl ProcDeclKind { + /// Attempt to convert a string to a declaration kind. + pub fn from_name(name: &str) -> Option { + match name { + "proc" => Some(ProcDeclKind::Proc), + "verb" => Some(ProcDeclKind::Verb), + _ => None, + } + } + + /// Return whether `self` is `ProcDeclKind::Verb`. + pub fn is_verb(self) -> bool { + self == ProcDeclKind::Verb + } + + /// Return the string representation of this declaration kind. + pub fn name(self) -> &'static str { + match self { + ProcDeclKind::Proc => "proc", + ProcDeclKind::Verb => "verb", + } + } +} + +impl fmt::Display for ProcDeclKind { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str(self.name()) + } +} + /// A parameter declaration in the header of a proc. #[derive(Debug, Clone, PartialEq, Default)] pub struct Parameter { diff --git a/src/dreammaker/objtree.rs b/src/dreammaker/objtree.rs index 4af809f5..860255f8 100644 --- a/src/dreammaker/objtree.rs +++ b/src/dreammaker/objtree.rs @@ -9,7 +9,7 @@ use petgraph::visit::EdgeRef; use petgraph::Direction; use linked_hash_map::LinkedHashMap; -use super::ast::{Expression, VarType, VarSuffix, PathOp, Parameter, Statement}; +use super::ast::{Expression, VarType, VarSuffix, PathOp, Parameter, Statement, ProcDeclKind}; use super::constants::{Constant, Pop}; use super::docs::DocCollection; use super::{DMError, Location, Context}; @@ -45,7 +45,7 @@ pub struct TypeVar { #[derive(Debug, Clone)] pub struct ProcDeclaration { pub location: Location, - pub is_verb: bool, + pub kind: ProcDeclKind, } #[derive(Debug, Clone)] @@ -759,25 +759,22 @@ impl ObjectTree { location: Location, parent: NodeIndex, name: &str, - mut declaration: Option, + mut declaration: Option, parameters: Vec, code: Code, ) -> Result<(usize, &mut ProcValue), DMError> { let node = self.graph.node_weight_mut(parent).unwrap(); let proc = node.procs.entry(name.to_owned()).or_insert_with(Default::default); - if let Some(is_verb) = declaration { + if let Some(kind) = declaration { if let Some(ref decl) = proc.declaration { - DMError::new(location, format!("duplicate definition of {}/{}", - if is_verb { "verb" } else { "proc" }, - name, - )) + DMError::new(location, format!("duplicate definition of {}/{}", kind, name)) .add_note(decl.location, "previous definition") .register(context); declaration = None; // suppress the later check } else { proc.declaration = Some(ProcDeclaration { location, - is_verb, + kind, }); } } @@ -855,9 +852,9 @@ impl ObjectTree { code: Code, ) -> Result<(usize, &mut ProcValue), DMError> { let (parent, mut proc_name) = self.get_from_path(location, &mut path, len)?; - let mut is_verb = None; - if is_proc_decl(proc_name) { - is_verb = Some(proc_name == "verb"); + let mut declaration = None; + if let Some(kind) = ProcDeclKind::from_name(proc_name) { + declaration = Some(kind); proc_name = match path.next() { Some(name) => name, None => return Err(DMError::new(location, "proc must have a name")), @@ -872,7 +869,7 @@ impl ObjectTree { )); } - self.register_proc(context, location, parent, proc_name, is_verb, parameters, code) + self.register_proc(context, location, parent, proc_name, declaration, parameters, code) } } diff --git a/src/langserver/completion.rs b/src/langserver/completion.rs index c7ac9ed6..9e0e2be1 100644 --- a/src/langserver/completion.rs +++ b/src/langserver/completion.rs @@ -304,7 +304,7 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> { Some(decl) => decl, None => continue, }; - if proc_decl.is_verb != (decl == "verb") { + if proc_decl.kind.is_verb() != (decl == "verb") { continue; } if contains(name, query) { diff --git a/src/langserver/main.rs b/src/langserver/main.rs index 65311882..c47c3dc1 100644 --- a/src/langserver/main.rs +++ b/src/langserver/main.rs @@ -597,7 +597,7 @@ handle_method_call! { for (proc_name, pv) in ty.procs.iter() { if let Some(decl) = pv.declaration.as_ref() { - if query.matches_proc(&proc_name, decl.is_verb) { + if query.matches_proc(&proc_name, decl.kind) { results.push(SymbolInformation { name: proc_name.clone(), kind: if idx.index() == 0 { @@ -730,7 +730,7 @@ handle_method_call! { infos.push_front(message); if let Some(ref decl) = proc.declaration { let mut declaration = String::new(); - declaration.push_str(if decl.is_verb { "verb" } else { "proc" }); + declaration.push_str(decl.kind.name()); declaration.push_str("/**"); declaration.push_str(last); declaration.push_str("**"); diff --git a/src/langserver/symbol_search.rs b/src/langserver/symbol_search.rs index 9d2e3afc..56fa8184 100644 --- a/src/langserver/symbol_search.rs +++ b/src/langserver/symbol_search.rs @@ -71,7 +71,7 @@ impl Query { } } - pub fn matches_proc(&self, name: &str, _is_verb: bool) -> bool { + pub fn matches_proc(&self, name: &str, _kind: ::dm::ast::ProcDeclKind) -> bool { match *self { Query::Anything(ref q) | Query::Proc(ref q) => starts_with(name, q),