forked from Rust-related/RustPython
Merge pull request #1683 from RustPython/coolreader18/improve-derive-diagnostics
Improve rustpython-derive diagnostics
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1310,6 +1310,7 @@ dependencies = [
|
||||
name = "rustpython-derive"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
||||
@@ -17,3 +17,4 @@ proc-macro2 = "0.4.27"
|
||||
rustpython-compiler = { path = "../compiler", version = "0.1.1" }
|
||||
rustpython-bytecode = { path = "../bytecode", version = "0.1.1" }
|
||||
maplit = "1.0"
|
||||
lazy_static = "1"
|
||||
|
||||
@@ -25,6 +25,12 @@ use std::path::{Path, PathBuf};
|
||||
use syn::parse::{Parse, ParseStream, Result as ParseResult};
|
||||
use syn::{self, parse2, Lit, LitByteStr, LitStr, Meta, Token};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref CARGO_MANIFEST_DIR: PathBuf = PathBuf::from(
|
||||
env::var_os("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR is not present"),
|
||||
);
|
||||
}
|
||||
|
||||
enum CompilationSourceKind {
|
||||
File(PathBuf),
|
||||
SourceCode(String),
|
||||
@@ -37,14 +43,19 @@ struct CompilationSource {
|
||||
}
|
||||
|
||||
impl CompilationSource {
|
||||
fn compile_string(
|
||||
fn compile_string<D: std::fmt::Display, F: FnOnce() -> D>(
|
||||
&self,
|
||||
source: &str,
|
||||
mode: compile::Mode,
|
||||
module_name: String,
|
||||
origin: F,
|
||||
) -> Result<CodeObject, Diagnostic> {
|
||||
compile::compile(source, mode, module_name, 0)
|
||||
.map_err(|err| Diagnostic::spans_error(self.span, format!("Compile error: {}", err)))
|
||||
compile::compile(source, mode, module_name, 0).map_err(|err| {
|
||||
Diagnostic::spans_error(
|
||||
self.span,
|
||||
format!("Python compile error from {}: {}", origin(), err),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn compile(
|
||||
@@ -54,10 +65,7 @@ impl CompilationSource {
|
||||
) -> Result<HashMap<String, FrozenModule>, Diagnostic> {
|
||||
Ok(match &self.kind {
|
||||
CompilationSourceKind::File(rel_path) => {
|
||||
let mut path = PathBuf::from(
|
||||
env::var_os("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR is not present"),
|
||||
);
|
||||
path.push(rel_path);
|
||||
let path = CARGO_MANIFEST_DIR.join(rel_path);
|
||||
let source = fs::read_to_string(&path).map_err(|err| {
|
||||
Diagnostic::spans_error(
|
||||
self.span,
|
||||
@@ -66,7 +74,7 @@ impl CompilationSource {
|
||||
})?;
|
||||
hashmap! {
|
||||
module_name.clone() => FrozenModule {
|
||||
code: self.compile_string(&source, mode, module_name)?,
|
||||
code: self.compile_string(&source, mode, module_name, || rel_path.display())?,
|
||||
package: false,
|
||||
},
|
||||
}
|
||||
@@ -74,17 +82,13 @@ impl CompilationSource {
|
||||
CompilationSourceKind::SourceCode(code) => {
|
||||
hashmap! {
|
||||
module_name.clone() => FrozenModule {
|
||||
code: self.compile_string(code, mode, module_name)?,
|
||||
code: self.compile_string(code, mode, module_name, || "string literal")?,
|
||||
package: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
CompilationSourceKind::Dir(rel_path) => {
|
||||
let mut path = PathBuf::from(
|
||||
env::var_os("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR is not present"),
|
||||
);
|
||||
path.push(rel_path);
|
||||
self.compile_dir(&path, String::new(), mode)?
|
||||
self.compile_dir(&CARGO_MANIFEST_DIR.join(rel_path), String::new(), mode)?
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -132,7 +136,12 @@ impl CompilationSource {
|
||||
code_map.insert(
|
||||
module_name.clone(),
|
||||
FrozenModule {
|
||||
code: self.compile_string(&source, mode, module_name)?,
|
||||
code: self.compile_string(&source, mode, module_name, || {
|
||||
path.strip_prefix(&*CARGO_MANIFEST_DIR)
|
||||
.ok()
|
||||
.unwrap_or(&path)
|
||||
.display()
|
||||
})?,
|
||||
package: is_init,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -20,10 +20,7 @@ use quote::ToTokens;
|
||||
use syn::{parse_macro_input, AttributeArgs, DeriveInput, Item};
|
||||
|
||||
fn result_to_tokens(result: Result<TokenStream2, Diagnostic>) -> TokenStream {
|
||||
match result {
|
||||
Ok(tokens) => tokens.into(),
|
||||
Err(diagnostic) => diagnostic.into_token_stream().into(),
|
||||
}
|
||||
result.unwrap_or_else(ToTokens::into_token_stream).into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(FromArgs, attributes(pyarg))]
|
||||
@@ -54,13 +51,13 @@ pub fn pystruct_sequence(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
}
|
||||
|
||||
fn result_to_tokens_expr(result: Result<TokenStream2, Diagnostic>) -> TokenStream {
|
||||
result_to_tokens(result.map(|out_expr| {
|
||||
quote::quote! {
|
||||
macro_rules! __proc_macro_call {
|
||||
() => {{ #out_expr }};
|
||||
}
|
||||
let tokens2 = result.unwrap_or_else(ToTokens::into_token_stream);
|
||||
let ret = quote::quote! {
|
||||
macro_rules! __proc_macro_call {
|
||||
() => {{ #tokens2 }}
|
||||
}
|
||||
}))
|
||||
};
|
||||
ret.into()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::Diagnostic;
|
||||
use proc_macro2::{Span, TokenStream as TokenStream2};
|
||||
use quote::quote;
|
||||
use quote::{quote, quote_spanned};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use syn::{
|
||||
spanned::Spanned, Attribute, AttributeArgs, Ident, ImplItem, Index, Item, Lit, Meta, MethodSig,
|
||||
@@ -305,23 +305,32 @@ pub fn impl_pyimpl(_attr: AttributeArgs, item: Item) -> Result<TokenStream2, Dia
|
||||
ClassItem::Method {
|
||||
item_ident,
|
||||
py_name,
|
||||
} => Some(quote! {
|
||||
class.set_str_attr(#py_name, ctx.new_method(Self::#item_ident));
|
||||
}),
|
||||
} => {
|
||||
let new_meth = quote_spanned!(item_ident.span()=> .new_method(Self::#item_ident));
|
||||
Some(quote! {
|
||||
class.set_str_attr(#py_name, ctx#new_meth);
|
||||
})
|
||||
}
|
||||
ClassItem::ClassMethod {
|
||||
item_ident,
|
||||
py_name,
|
||||
} => Some(quote! {
|
||||
class.set_str_attr(#py_name, ctx.new_classmethod(Self::#item_ident));
|
||||
}),
|
||||
} => {
|
||||
let new_meth = quote_spanned!(item_ident.span()=> .new_classmethod(Self::#item_ident));
|
||||
Some(quote! {
|
||||
class.set_str_attr(#py_name, ctx#new_meth);
|
||||
})
|
||||
}
|
||||
ClassItem::Slot {
|
||||
slot_ident,
|
||||
item_ident,
|
||||
} => Some(quote! {
|
||||
class.slots.borrow_mut().#slot_ident = Some(
|
||||
} => {
|
||||
let into_func = quote_spanned! {item_ident.span()=>
|
||||
::rustpython_vm::function::IntoPyNativeFunc::into_func(Self::#item_ident)
|
||||
);
|
||||
}),
|
||||
};
|
||||
Some(quote! {
|
||||
(*class.slots.borrow_mut()).#slot_ident = Some(#into_func);
|
||||
})
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user