Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More accurately provide spans to errors in the GodotClass macro #920

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions godot-core/src/obj/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,21 @@ impl GodotClass for NoBase {
const INIT_LEVEL: InitLevel = InitLevel::Core; // arbitrary; never read.
}

#[diagnostic::on_unimplemented(
message = "expected base `{Self}` found `{A}`",
label = "expected base `{Self}` found `{A}`"
)]
#[doc(hidden)]
pub trait IsBase<T: GodotClass, A> {
#[doc(hidden)]
fn conv(b: Base<T>) -> A;
}
impl<T: GodotClass> IsBase<T, Base<T>> for Base<T> {
fn conv(b: Base<T>) -> Base<T> {
b
}
}

unsafe impl Bounds for NoBase {
type Memory = bounds::MemManual;
type DynMemory = bounds::MemManual;
Expand Down
22 changes: 20 additions & 2 deletions godot-macros/src/class/data_models/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@
*/

use crate::class::{FieldExport, FieldVar};
use proc_macro2::{Ident, TokenStream};
use proc_macro2::{Ident, Span, TokenStream};
use quote::ToTokens;

pub struct Field {
pub name: Ident,
pub ty: venial::TypeExpr,
pub default_val: Option<TokenStream>,
pub default_val: Option<FieldDefault>,
pub var: Option<FieldVar>,
pub export: Option<FieldExport>,
pub is_onready: bool,
#[cfg(feature = "docs")]
pub attributes: Vec<venial::Attribute>,
pub span: Span,
}

impl Field {
Expand All @@ -30,6 +32,7 @@ impl Field {
is_onready: false,
#[cfg(feature = "docs")]
attributes: field.attributes.clone(),
span: field.span(),
}
}
}
Expand All @@ -43,4 +46,19 @@ pub struct Fields {

/// Deprecation warnings.
pub deprecations: Vec<TokenStream>,

/// Errors during macro evaluation that shouldn't abort the execution of the macro.
pub errors: Vec<venial::Error>,
}

#[derive(Clone)]
pub struct FieldDefault {
pub default_val: TokenStream,
pub span: Span,
}

impl ToTokens for FieldDefault {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.default_val.to_tokens(tokens)
}
}
65 changes: 41 additions & 24 deletions godot-macros/src/class/data_models/field_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,32 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

use proc_macro2::{Ident, TokenStream};
use proc_macro2::{Ident, Span, TokenStream};
use quote::quote;
use std::collections::{HashMap, HashSet};

use crate::util::{KvParser, ListParser};
use crate::ParseResult;

pub struct FieldExport {
pub export_type: ExportType,
pub span: Span,
}

impl FieldExport {
pub(crate) fn new_from_kv(parser: &mut KvParser) -> ParseResult<Self> {
let span = parser.span();
let export_type = ExportType::new_from_kv(parser)?;
Ok(Self { export_type, span })
}

pub fn to_export_hint(&self) -> Option<TokenStream> {
self.export_type.to_export_hint()
}
}

/// Store info from `#[export]` attribute.
pub enum FieldExport {
pub enum ExportType {
/// ### GDScript annotations
/// - `@export`
///
Expand Down Expand Up @@ -121,7 +138,7 @@ pub enum FieldExport {
ColorNoAlpha,
}

impl FieldExport {
impl ExportType {
/// Parse an `#[export(...)]` attribute.
///
/// The translation from GDScript annotations to rust attributes is given by:
Expand Down Expand Up @@ -253,10 +270,10 @@ impl FieldExport {
return Ok(Self::ColorNoAlpha);
}

Ok(FieldExport::Default)
Ok(Self::Default)
}

fn new_range_list(mut parser: ListParser) -> ParseResult<FieldExport> {
fn new_range_list(mut parser: ListParser) -> ParseResult<Self> {
const FLAG_OPTIONS: [&str; 7] = [
"or_greater",
"or_less",
Expand Down Expand Up @@ -299,7 +316,7 @@ impl FieldExport {

parser.finish()?;

Ok(FieldExport::Range {
Ok(Self::Range {
min,
max,
step,
Expand Down Expand Up @@ -374,12 +391,12 @@ macro_rules! quote_export_func {
}
}

impl FieldExport {
impl ExportType {
pub fn to_export_hint(&self) -> Option<TokenStream> {
match self {
FieldExport::Default => None,
Self::Default => None,

FieldExport::Range {
Self::Range {
min,
max,
step,
Expand Down Expand Up @@ -416,70 +433,70 @@ impl FieldExport {
})
}

FieldExport::Enum { variants } => {
Self::Enum { variants } => {
let variants = variants.iter().map(ValueWithKey::to_tuple_expression);

quote_export_func! {
export_enum(&[#(#variants),*])
}
}

FieldExport::ExpEasing {
Self::ExpEasing {
attenuation,
positive_only,
} => quote_export_func! {
export_exp_easing(#attenuation, #positive_only)
},

FieldExport::Flags { bits } => {
Self::Flags { bits } => {
let bits = bits.iter().map(ValueWithKey::to_tuple_expression);

quote_export_func! {
export_flags(&[#(#bits),*])
}
}

FieldExport::Layers {
Self::Layers {
dimension: LayerDimension::_2d,
kind: LayerKind::Physics,
} => quote_export_func! { export_flags_2d_physics() },

FieldExport::Layers {
Self::Layers {
dimension: LayerDimension::_2d,
kind: LayerKind::Render,
} => quote_export_func! { export_flags_2d_render() },

FieldExport::Layers {
Self::Layers {
dimension: LayerDimension::_2d,
kind: LayerKind::Navigation,
} => quote_export_func! { export_flags_2d_navigation() },

FieldExport::Layers {
Self::Layers {
dimension: LayerDimension::_3d,
kind: LayerKind::Physics,
} => quote_export_func! { export_flags_3d_physics() },

FieldExport::Layers {
Self::Layers {
dimension: LayerDimension::_3d,
kind: LayerKind::Render,
} => quote_export_func! { export_flags_3d_render() },

FieldExport::Layers {
Self::Layers {
dimension: LayerDimension::_3d,
kind: LayerKind::Navigation,
} => quote_export_func! { export_flags_3d_navigation() },

FieldExport::File {
Self::File {
global: false,
kind: FileKind::Dir,
} => quote_export_func! { export_dir() },

FieldExport::File {
Self::File {
global: true,
kind: FileKind::Dir,
} => quote_export_func! { export_global_dir() },

FieldExport::File {
Self::File {
global,
kind: FileKind::File { filter },
} => {
Expand All @@ -488,12 +505,12 @@ impl FieldExport {
quote_export_func! { export_file_inner(#global, #filter) }
}

FieldExport::Multiline => quote_export_func! { export_multiline() },
Self::Multiline => quote_export_func! { export_multiline() },

FieldExport::PlaceholderText { placeholder } => quote_export_func! {
Self::PlaceholderText { placeholder } => quote_export_func! {
export_placeholder(#placeholder)
},
FieldExport::ColorNoAlpha => quote_export_func! { export_color_no_alpha() },
Self::ColorNoAlpha => quote_export_func! { export_color_no_alpha() },
}
}
}
Expand Down
19 changes: 17 additions & 2 deletions godot-macros/src/class/data_models/field_var.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

use proc_macro2::{Ident, TokenStream};
use proc_macro2::{Ident, Span, TokenStream};
use quote::{format_ident, quote};

use crate::class::{
Expand All @@ -16,12 +16,13 @@ use crate::util::KvParser;
use crate::{util, ParseResult};

/// Store info from `#[var]` attribute.
#[derive(Default, Clone, Debug)]
#[derive(Clone, Debug)]
pub struct FieldVar {
pub getter: GetterSetter,
pub setter: GetterSetter,
pub hint: FieldHint,
pub usage_flags: UsageFlags,
pub span: Span,
}

impl FieldVar {
Expand All @@ -34,6 +35,7 @@ impl FieldVar {
/// - `hint_string = expr`
/// - `usage_flags =
pub(crate) fn new_from_kv(parser: &mut KvParser) -> ParseResult<Self> {
let span = parser.span();
let mut getter = GetterSetter::parse(parser, "get")?;
let mut setter = GetterSetter::parse(parser, "set")?;

Expand Down Expand Up @@ -71,10 +73,23 @@ impl FieldVar {
setter,
hint,
usage_flags,
span,
})
}
}

impl Default for FieldVar {
fn default() -> Self {
Self {
getter: Default::default(),
setter: Default::default(),
hint: Default::default(),
usage_flags: Default::default(),
span: Span::call_site(),
}
}
}

#[derive(Default, Clone, Eq, PartialEq, Debug)]
pub enum GetterSetter {
/// Getter/setter should be omitted, field is write/read only.
Expand Down
1 change: 1 addition & 0 deletions godot-macros/src/class/data_models/property.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ pub fn make_property_impl(class_name: &Ident, fields: &Fields) -> TokenStream {
setter,
hint,
mut usage_flags,
..
} = var;

let export_hint;
Expand Down
Loading
Loading