1pub mod args;
2pub mod config;
3pub mod driver;
4pub mod parser;
5mod rename;
6mod serde;
7mod topsort;
8mod type_parser;
9mod visitors;
10pub mod writer;
11
12use std::{
13 fmt::{self, Display, Write},
14 io,
15 path::PathBuf,
16};
17
18use indent_write::fmt::IndentWriter;
19use proc_macro2::LineColumn;
20use syn::spanned::Spanned;
21use thiserror::Error;
22use typeshare_model::prelude::{CrateName, TypeName};
23
24pub use typeshare_model::prelude::FilesMode;
26
27#[derive(Debug, Error)]
28pub struct FileParseErrors {
29 pub path: PathBuf,
30 pub crate_name: Option<CrateName>,
31 pub kind: FileErrorKind,
32}
33
34impl FileParseErrors {
35 pub fn new(path: PathBuf, crate_name: Option<CrateName>, kind: FileErrorKind) -> Self {
36 Self {
37 path,
38 crate_name,
39 kind,
40 }
41 }
42}
43
44impl Display for FileParseErrors {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 write!(
47 f,
48 "in {path}, {error}",
49 path = self.path.display(),
50 error = self.kind
51 )
52 }
53}
54
55#[derive(Debug)]
56pub enum FileErrorKind {
57 UnknownCrate,
58 ParseErrors(ParseErrorSet),
59 ReadError(io::Error),
60}
61
62impl Display for FileErrorKind {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 match self {
65 FileErrorKind::UnknownCrate => f.write_str("unknown crate in mutli-file mode"),
66 FileErrorKind::ParseErrors(parse_error_set) => parse_error_set.fmt(f),
67 FileErrorKind::ReadError(error) => write!(f, "i/o error: {error}"),
68 }
69 }
70}
71#[derive(Debug)]
73pub struct ParseErrorSet {
74 errors: Vec<ParseError>,
75}
76
77impl ParseErrorSet {
78 pub fn collect(errors: impl IntoIterator<Item = ParseError>) -> Result<(), Self> {
79 let mut errors = errors.into_iter().peekable();
80
81 match errors.peek() {
82 Some(_) => Err(Self {
83 errors: errors.collect(),
84 }),
85 None => Ok(()),
86 }
87 }
88}
89
90impl From<ParseError> for ParseErrorSet {
91 fn from(error: ParseError) -> Self {
92 Self {
93 errors: Vec::from([error]),
94 }
95 }
96}
97
98impl Display for ParseErrorSet {
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 match self.errors.as_slice() {
101 [] => Ok(()),
102 [error] => write!(f, "{error}"),
103 errors => {
104 writeln!(f, "multiple errors:")?;
105 let mut f = IndentWriter::new(" ", f);
106 errors.iter().try_for_each(|error| write!(f, "{error}"))
107 }
108 }
109 }
110}
111
112#[derive(Debug, Error)]
113#[error("at {}:{}..{}:{}: {kind}",
114 .start.line,
115 .start.column,
116 .end.line,
117 .end.column,
118)]
119pub struct ParseError {
120 start: LineColumn,
121 end: LineColumn,
122 kind: ParseErrorKind,
123}
124
125impl ParseError {
126 pub fn new(span: &impl Spanned, kind: ParseErrorKind) -> Self {
127 let span = span.span();
128 Self {
129 start: span.start(),
130 end: span.end(),
131 kind,
132 }
133 }
134}
135
136#[derive(Debug, Error)]
138#[allow(missing_docs)]
139pub enum ParseErrorKind {
140 #[error("{0}")]
141 SynError(#[from] syn::Error),
142 #[error("failed to parse a rust type: {0}")]
143 RustTypeParseError(#[from] RustTypeParseError),
144 #[error("unsupported language encountered: {0}")]
145 UnsupportedLanguage(String),
146 #[error("unsupported type encountered: {0}")]
147 UnsupportedType(String),
148 #[error("tuple structs with more than one field are currently unsupported")]
149 ComplexTupleStruct,
150 #[error("multiple unnamed associated types are not currently supported")]
151 MultipleUnnamedAssociatedTypes,
152 #[error("the serde tag attribute is not supported for non-algebraic enums: {enum_ident}")]
153 SerdeTagNotAllowed { enum_ident: TypeName },
154 #[error("the serde content attribute is not supported for non-algebraic enums: {enum_ident}")]
155 SerdeContentNotAllowed { enum_ident: TypeName },
156 #[error("serde tag attribute needs to be specified for algebraic enum {enum_ident}. e.g. #[serde(tag = \"type\", content = \"content\")]")]
157 SerdeTagRequired { enum_ident: TypeName },
158 #[error("serde content attribute needs to be specified for algebraic enum {enum_ident}. e.g. #[serde(tag = \"type\", content = \"content\")]")]
159 SerdeContentRequired { enum_ident: TypeName },
160 #[error("the serde flatten attribute is not currently supported")]
161 SerdeFlattenNotAllowed,
162}
163
164#[derive(Debug, Error)]
165#[allow(missing_docs)]
166pub enum RustTypeParseError {
167 #[error("{0:?}")]
168 UnsupportedType(Vec<String>),
169 #[error("Unexpected token when parsing type: `{0}`. This is an internal error, please ping a typeshare developer to resolve this problem.")]
170 UnexpectedToken(String),
171 #[error("Tuples are not allowed in typeshare types")]
172 UnexpectedParameterizedTuple,
173 #[error("Could not parse numeric literal")]
174 NumericLiteral(syn::parse::Error),
175}