use std::borrow::Borrow;
use std::fmt::{Debug, Display, Error, Formatter};
#[derive(Debug, Clone)]
pub struct ParseResult {
pub event_list: Vec<EventInfo>,
pub comment_lines: Vec<usize>,
pub original_content: Vec<String>,
}
#[derive(Clone)]
pub struct EventInfo {
pub line: usize,
pub event: EventType,
}
impl EventInfo {
pub fn new(line: usize, event: EventType) -> EventInfo {
EventInfo { line, event }
}
}
impl Debug for EventInfo {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
write!(fmt, "{:?}->{:?}", self.line, self.event)
}
}
#[derive(Clone)]
pub enum EventType {
Comment(String),
FileComment(String),
Type(TypeStruct),
InScope,
OutScope,
}
impl Debug for EventType {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
match *self {
EventType::Type(ref t) => write!(fmt, "Type: {:?}", t),
EventType::FileComment(ref t) => write!(fmt, "FileComment: {:?}", t),
EventType::Comment(ref t) => write!(fmt, "Comment: {:?}", t),
EventType::InScope => write!(fmt, "InScope"),
EventType::OutScope => write!(fmt, "OutScope"),
}
}
}
#[derive(Clone, PartialEq)]
pub struct TypeStruct {
pub ty: Type,
pub parent: Option<Box<TypeStruct>>,
pub name: String,
pub args: Vec<String>,
}
impl TypeStruct {
pub fn new(ty: Type, name: &str) -> TypeStruct {
TypeStruct {
ty,
name: name.to_owned(),
args: vec![],
parent: None,
}
}
pub fn empty() -> TypeStruct {
TypeStruct {
ty: Type::Unknown,
name: String::new(),
args: Vec::new(),
parent: None,
}
}
pub fn get_depth(&self, ignore_macros: bool) -> usize {
fn recur(ty: &Option<Box<TypeStruct>>, is_parent: bool, ignore_macros: bool) -> usize {
match *ty {
Some(ref t) => {
if ignore_macros && is_parent && t.ty == Type::Macro {
recur(&t.parent, true, ignore_macros)
} else {
recur(&t.parent, true, ignore_macros) + 1
}
}
_ => 0,
}
}
recur(&self.parent, false, ignore_macros)
}
}
impl Debug for TypeStruct {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
let parent = &self.parent;
match *parent {
Some(ref p) => write!(
f,
"{:?}::{} {}{}",
p,
self.ty,
self.name,
self.args.join(" ")
),
_ => write!(f, "{} {}{}", self.ty, self.name, self.args.join(" ")),
}
}
}
fn show(f: &mut Formatter, t: &TypeStruct, is_parent: bool) -> Result<(), Error> {
if is_parent {
write!(f, "{} {}{}::", t.ty, t.name, t.args.join(" "))
} else {
write!(f, "{} {}{}", t.ty, t.name, t.args.join(" "))
}
}
fn sub_call(f: &mut Formatter, t: &TypeStruct, is_parent: bool) -> Result<(), Error> {
if (t.ty == Type::Macro || t.ty.is_macro_definition()) && is_parent {
match t.parent {
Some(ref p) => sub_call(f, p.borrow(), true),
_ => Ok(()),
}
} else {
match t.parent {
Some(ref p) => {
sub_call(f, p.borrow(), true)?;
show(f, t, is_parent)
}
_ => show(f, t, is_parent),
}
}
}
impl Display for TypeStruct {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
sub_call(f, self, false)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Type {
Struct,
Mod,
Enum,
Fn,
Const,
Static,
Type,
Variant,
Impl,
Use,
MacroDefinition,
Macro,
Trait,
Flags,
Unknown,
}
impl Type {
pub fn is_macro_definition(self) -> bool {
matches!(self, Type::MacroDefinition)
}
}
impl Type {
pub fn from(s: &str) -> Type {
match s {
"struct" => Type::Struct,
"mod" => Type::Mod,
"enum" => Type::Enum,
"fn" => Type::Fn,
"const" => Type::Const,
"static" => Type::Static,
"type" => Type::Type,
"impl" => Type::Impl,
"use" => Type::Use,
"trait" => Type::Trait,
"flags" => Type::Flags,
"macro" => Type::Macro,
"macro_rules" | "macro_rules!" => Type::MacroDefinition,
_ => Type::Variant,
}
}
}
impl Display for Type {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
match *self {
Type::Struct => write!(f, "struct"),
Type::Mod => write!(f, "mod"),
Type::Enum => write!(f, "enum"),
Type::Fn => write!(f, "fn"),
Type::Const => write!(f, "const"),
Type::Static => write!(f, "static"),
Type::Type => write!(f, "type"),
Type::Variant => write!(f, "variant"),
Type::Impl => write!(f, "impl"),
Type::Use => write!(f, "use"),
Type::Trait => write!(f, "trait"),
Type::Macro => write!(f, "macro"),
Type::MacroDefinition => write!(f, "macro"),
Type::Flags => write!(f, "flags"),
_ => write!(f, "?"),
}
}
}