Merge pull request #1683 from RustPython/coolreader18/improve-derive-diagnostics

Improve rustpython-derive diagnostics
This commit is contained in:
Jeong YunWon
2020-01-14 14:34:42 +09:00
committed by GitHub
5 changed files with 53 additions and 36 deletions

1
Cargo.lock generated
View File

@@ -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)",

View File

@@ -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"

View File

@@ -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,
},
);

View File

@@ -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]

View File

@@ -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,
});