Implement Render even if parsing failed

This makes error messages much more readable.
This commit is contained in:
René Kijewski 2024-04-18 04:35:44 +02:00 committed by René Kijewski
parent a95fca43ac
commit c48532fb17
4 changed files with 26 additions and 15 deletions

View File

@ -36,7 +36,7 @@ impl Heritage<'_> {
type BlockAncestry<'a> = HashMap<&'a str, Vec<(&'a Context<'a>, &'a BlockDef<'a>)>>;
#[derive(Clone)]
#[derive(Default, Clone)]
pub(crate) struct Context<'a> {
pub(crate) nodes: &'a [Node<'a>],
pub(crate) extends: Option<Rc<Path>>,

View File

@ -332,6 +332,14 @@ impl TemplateArgs {
Ok(args)
}
pub(crate) fn fallback() -> Self {
Self {
source: Some(Source::Source("".to_string())),
ext: Some("txt".to_string()),
..Self::default()
}
}
pub(crate) fn config(&self) -> Result<String, CompileError> {
read_config_file(self.config.as_deref())
}

View File

@ -23,10 +23,26 @@ pub fn derive_template(input: TokenStream) -> TokenStream {
let ast = syn::parse::<syn::DeriveInput>(input).unwrap();
match build_template(&ast) {
Ok(source) => source.parse().unwrap(),
Err(e) => e.into_compile_error(),
Err(e) => {
let mut e = e.into_compile_error();
if let Ok(source) = build_skeleton(&ast) {
let source: TokenStream = source.parse().unwrap();
e.extend(source);
}
e
}
}
}
fn build_skeleton(ast: &syn::DeriveInput) -> Result<String, CompileError> {
let template_args = TemplateArgs::fallback();
let config = Config::new("", None)?;
let input = TemplateInput::new(ast, &config, &template_args)?;
let mut contexts = HashMap::new();
contexts.insert(&input.path, Context::default());
Generator::new(&input, &contexts, None, MapChain::default()).build(&contexts[&input.path])
}
/// Takes a `syn::DeriveInput` and generates source code for it
///
/// Reads the metadata from the `template()` attribute to get the template

View File

@ -6,16 +6,3 @@ error: failed to parse template source at row 1, column 27 near:
| ^^^^^^^^
|
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0599]: no method named `render` found for struct `A` in the current scope
--> tests/ui/filter_block_ws.rs:11:7
|
8 | struct A;
| -------- method `render` not found for this struct
...
11 | A.render().unwrap();
| ^^^^^^ method not found in `A`
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `render`, perhaps you need to implement it:
candidate #1: `Template`