use serde::Serialize;
pub const DOC_VERSION: u32 = 1;
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Doc {
Nil,
Src(u32, u32),
Lit(String),
Line,
Soft,
Hard,
Blank,
IfBreak(Box<Doc>, Box<Doc>),
Group(Box<Doc>),
Indent(Box<Doc>),
Concat(Vec<Doc>),
Host {
start: u32,
end: u32,
parse: HostParse,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum HostParse {
Block,
Expr,
}
impl Doc {
pub fn src(start: u32, end: u32) -> Self {
Self::Src(start, end)
}
pub fn lit(s: impl Into<String>) -> Self {
Self::Lit(s.into())
}
pub fn group(inner: Doc) -> Self {
Self::Group(Box::new(inner))
}
pub fn indent(inner: Doc) -> Self {
Self::Indent(Box::new(inner))
}
pub fn if_break(flat: Doc, broken: Doc) -> Self {
Self::IfBreak(Box::new(flat), Box::new(broken))
}
pub fn concat(parts: impl IntoIterator<Item = Doc>) -> Self {
Self::Concat(parts.into_iter().collect())
}
pub fn join(sep: Doc, parts: impl IntoIterator<Item = Doc>) -> Self {
let mut out = Vec::new();
for (i, part) in parts.into_iter().enumerate() {
if i > 0 {
out.push(sep.clone());
}
out.push(part);
}
Self::Concat(out)
}
pub fn host(start: u32, end: u32) -> Self {
Self::Host {
start,
end,
parse: HostParse::Block,
}
}
pub fn host_expr(start: u32, end: u32) -> Self {
Self::Host {
start,
end,
parse: HostParse::Expr,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct Finding {
pub span: (u32, u32),
pub lint: String,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub help: Option<String>,
}
impl Finding {
pub fn new(lint: impl Into<String>, span: (u32, u32), message: impl Into<String>) -> Self {
Self {
span,
lint: lint.into(),
message: message.into(),
help: None,
}
}
pub fn with_help(mut self, help: impl Into<String>) -> Self {
self.help = Some(help.into());
self
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Format {
pub document: Option<Doc>,
pub spans: Vec<(u32, u32)>,
pub comments: Vec<(u32, u32)>,
}
impl Format {
pub fn document(document: Doc) -> Self {
Self {
document: Some(document),
spans: Vec::new(),
comments: Vec::new(),
}
}
pub fn spans(spans: Vec<(u32, u32)>) -> Self {
Self {
document: None,
spans,
comments: Vec::new(),
}
}
pub fn with_comments(mut self, comments: Vec<(u32, u32)>) -> Self {
self.comments = comments;
self
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Lint {
pub findings: Vec<Finding>,
pub luau: Option<String>,
pub comments: Vec<(u32, u32)>,
}