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