Rocket/core/codegen/src/proc_macro_ext.rs

92 lines
2.2 KiB
Rust
Raw Normal View History

use std::ops::RangeBounds;
2019-09-21 20:36:57 +00:00
use devise::Diagnostic;
use proc_macro2::{Span, Literal};
// An experiment.
pub struct Diagnostics(Vec<Diagnostic>);
impl Diagnostics {
pub fn new() -> Self {
Diagnostics(vec![])
}
pub fn push(&mut self, diag: Diagnostic) {
self.0.push(diag);
}
pub fn emit_head(self) -> Diagnostic {
let mut iter = self.0.into_iter();
let mut last = iter.next().expect("Diagnostic::emit_head empty");
for diag in iter {
2019-09-21 20:36:57 +00:00
// FIXME(diag: emit, can there be errors here?)
last.emit_as_item_tokens();
last = diag;
}
last
}
Revamp codegen, fixing inconscpicuous bugs. This commit completely revamps the way that codegen handles route URI "parameters". The changes are largely internal. In summary, codegen code is better organized, better written, and less subject to error. There are three breaking changes: * `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]` becomes `#[route(GET, uri = "..")]`. * the order of execution for path and query guards relative to each-other is now unspecified * URI normalization now normalizes the query part as well. Several error messages were improved. A couple of bugs were fixed: * Prior to this commit, Rocket would optimistically try to parse every segment of a URI as an ident, in case one was needed in the future. A bug in rustc results in codegen "panicking" if the segment couldn't _lex_ as an ident. This panic didn't manifest until far after expansion, unfortunately. This wasn't a problem before as we only allowed ident-like segments (ASCII), but now that we allow any UTF-8, the bug surfaced. This was fixed by never attempting to parse non-idents as idents. * Prior to this commit, it was impossible to generate typed URIs for paths that ignored path parameters via the recently added syntax `<_>`: the macro would panic. This was fixed by, well, handling these ignored parameters. Some minor additions: * Added `RawStr::find()`, expanding its `Pattern`-based API. * Added an internal mechanism to dynamically determine if a `UriPart` is `Path` or `Query`.
2021-03-02 12:01:33 +00:00
pub fn head_err_or<T>(self, ok: T) -> devise::Result<T> {
match self.0.is_empty() {
true => Ok(ok),
false => Err(self.emit_head())
}
}
}
impl From<Diagnostic> for Diagnostics {
fn from(diag: Diagnostic) -> Self {
Diagnostics(vec![diag])
}
}
impl From<Vec<Diagnostic>> for Diagnostics {
fn from(diags: Vec<Diagnostic>) -> Self {
Diagnostics(diags)
}
}
pub struct StringLit(pub String, pub Literal);
2018-11-24 01:15:13 +00:00
impl StringLit {
pub fn new<S: Into<String>>(string: S, span: Span) -> Self {
let string = string.into();
let mut lit = Literal::string(&string);
lit.set_span(span);
StringLit(string, lit)
}
pub fn span(&self) -> Span {
self.1.span()
}
/// Attempt to obtain a subspan, or, failing that, produce the full span.
2019-09-21 20:36:57 +00:00
/// This will create suboptimal diagnostics, but better than failing to
/// build entirely.
pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Span {
self.1.subspan(range).unwrap_or_else(|| self.span())
}
}
Revamp codegen, fixing inconscpicuous bugs. This commit completely revamps the way that codegen handles route URI "parameters". The changes are largely internal. In summary, codegen code is better organized, better written, and less subject to error. There are three breaking changes: * `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]` becomes `#[route(GET, uri = "..")]`. * the order of execution for path and query guards relative to each-other is now unspecified * URI normalization now normalizes the query part as well. Several error messages were improved. A couple of bugs were fixed: * Prior to this commit, Rocket would optimistically try to parse every segment of a URI as an ident, in case one was needed in the future. A bug in rustc results in codegen "panicking" if the segment couldn't _lex_ as an ident. This panic didn't manifest until far after expansion, unfortunately. This wasn't a problem before as we only allowed ident-like segments (ASCII), but now that we allow any UTF-8, the bug surfaced. This was fixed by never attempting to parse non-idents as idents. * Prior to this commit, it was impossible to generate typed URIs for paths that ignored path parameters via the recently added syntax `<_>`: the macro would panic. This was fixed by, well, handling these ignored parameters. Some minor additions: * Added `RawStr::find()`, expanding its `Pattern`-based API. * Added an internal mechanism to dynamically determine if a `UriPart` is `Path` or `Query`.
2021-03-02 12:01:33 +00:00
impl syn::parse::Parse for StringLit {
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
let lit = input.parse::<syn::LitStr>()?;
Ok(StringLit::new(lit.value(), lit.span()))
}
}
Revamp codegen, fixing inconscpicuous bugs. This commit completely revamps the way that codegen handles route URI "parameters". The changes are largely internal. In summary, codegen code is better organized, better written, and less subject to error. There are three breaking changes: * `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]` becomes `#[route(GET, uri = "..")]`. * the order of execution for path and query guards relative to each-other is now unspecified * URI normalization now normalizes the query part as well. Several error messages were improved. A couple of bugs were fixed: * Prior to this commit, Rocket would optimistically try to parse every segment of a URI as an ident, in case one was needed in the future. A bug in rustc results in codegen "panicking" if the segment couldn't _lex_ as an ident. This panic didn't manifest until far after expansion, unfortunately. This wasn't a problem before as we only allowed ident-like segments (ASCII), but now that we allow any UTF-8, the bug surfaced. This was fixed by never attempting to parse non-idents as idents. * Prior to this commit, it was impossible to generate typed URIs for paths that ignored path parameters via the recently added syntax `<_>`: the macro would panic. This was fixed by, well, handling these ignored parameters. Some minor additions: * Added `RawStr::find()`, expanding its `Pattern`-based API. * Added an internal mechanism to dynamically determine if a `UriPart` is `Path` or `Query`.
2021-03-02 12:01:33 +00:00
impl devise::FromMeta for StringLit {
fn from_meta(meta: &devise::MetaItem) -> devise::Result<Self> {
Ok(StringLit::new(String::from_meta(meta)?, meta.value_span()))
}
}
impl std::ops::Deref for StringLit {
type Target = str;
fn deref(&self) -> &str {
&self.0
}
}