Skip to content

Commit 2588a7d

Browse files
committed
More accurately provide spans to errors in the GodotClass macro
1 parent e27a562 commit 2588a7d

File tree

5 files changed

+162
-68
lines changed

5 files changed

+162
-68
lines changed

godot-macros/src/class/data_models/field.rs

+20-2
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,19 @@
66
*/
77

88
use crate::class::{FieldExport, FieldVar};
9-
use proc_macro2::{Ident, TokenStream};
9+
use proc_macro2::{Ident, Span, TokenStream};
10+
use quote::ToTokens;
1011

1112
pub struct Field {
1213
pub name: Ident,
1314
pub ty: venial::TypeExpr,
14-
pub default_val: Option<TokenStream>,
15+
pub default_val: Option<FieldDefault>,
1516
pub var: Option<FieldVar>,
1617
pub export: Option<FieldExport>,
1718
pub is_onready: bool,
1819
#[cfg(feature = "register-docs")]
1920
pub attributes: Vec<venial::Attribute>,
21+
pub span: Span,
2022
}
2123

2224
impl Field {
@@ -30,6 +32,7 @@ impl Field {
3032
is_onready: false,
3133
#[cfg(feature = "register-docs")]
3234
attributes: field.attributes.clone(),
35+
span: field.span(),
3336
}
3437
}
3538
}
@@ -43,4 +46,19 @@ pub struct Fields {
4346

4447
/// Deprecation warnings.
4548
pub deprecations: Vec<TokenStream>,
49+
50+
/// Errors during macro evaluation that shouldn't abort the execution of the macro.
51+
pub errors: Vec<venial::Error>,
52+
}
53+
54+
#[derive(Clone)]
55+
pub struct FieldDefault {
56+
pub default_val: TokenStream,
57+
pub span: Span,
58+
}
59+
60+
impl ToTokens for FieldDefault {
61+
fn to_tokens(&self, tokens: &mut TokenStream) {
62+
self.default_val.to_tokens(tokens)
63+
}
4664
}

godot-macros/src/class/data_models/field_export.rs

+41-24
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,32 @@
55
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
66
*/
77

8-
use proc_macro2::{Ident, TokenStream};
8+
use proc_macro2::{Ident, Span, TokenStream};
99
use quote::quote;
1010
use std::collections::{HashMap, HashSet};
1111

1212
use crate::util::{KvParser, ListParser};
1313
use crate::ParseResult;
1414

15+
pub struct FieldExport {
16+
pub export_type: ExportType,
17+
pub span: Span,
18+
}
19+
20+
impl FieldExport {
21+
pub(crate) fn new_from_kv(parser: &mut KvParser) -> ParseResult<Self> {
22+
let span = parser.span();
23+
let export_type = ExportType::new_from_kv(parser)?;
24+
Ok(Self { export_type, span })
25+
}
26+
27+
pub fn to_export_hint(&self) -> Option<TokenStream> {
28+
self.export_type.to_export_hint()
29+
}
30+
}
31+
1532
/// Store info from `#[export]` attribute.
16-
pub enum FieldExport {
33+
pub enum ExportType {
1734
/// ### GDScript annotations
1835
/// - `@export`
1936
///
@@ -121,7 +138,7 @@ pub enum FieldExport {
121138
ColorNoAlpha,
122139
}
123140

124-
impl FieldExport {
141+
impl ExportType {
125142
/// Parse an `#[export(...)]` attribute.
126143
///
127144
/// The translation from GDScript annotations to rust attributes is given by:
@@ -253,10 +270,10 @@ impl FieldExport {
253270
return Ok(Self::ColorNoAlpha);
254271
}
255272

256-
Ok(FieldExport::Default)
273+
Ok(Self::Default)
257274
}
258275

259-
fn new_range_list(mut parser: ListParser) -> ParseResult<FieldExport> {
276+
fn new_range_list(mut parser: ListParser) -> ParseResult<Self> {
260277
const FLAG_OPTIONS: [&str; 7] = [
261278
"or_greater",
262279
"or_less",
@@ -299,7 +316,7 @@ impl FieldExport {
299316

300317
parser.finish()?;
301318

302-
Ok(FieldExport::Range {
319+
Ok(Self::Range {
303320
min,
304321
max,
305322
step,
@@ -374,12 +391,12 @@ macro_rules! quote_export_func {
374391
}
375392
}
376393

377-
impl FieldExport {
394+
impl ExportType {
378395
pub fn to_export_hint(&self) -> Option<TokenStream> {
379396
match self {
380-
FieldExport::Default => None,
397+
Self::Default => None,
381398

382-
FieldExport::Range {
399+
Self::Range {
383400
min,
384401
max,
385402
step,
@@ -416,70 +433,70 @@ impl FieldExport {
416433
})
417434
}
418435

419-
FieldExport::Enum { variants } => {
436+
Self::Enum { variants } => {
420437
let variants = variants.iter().map(ValueWithKey::to_tuple_expression);
421438

422439
quote_export_func! {
423440
export_enum(&[#(#variants),*])
424441
}
425442
}
426443

427-
FieldExport::ExpEasing {
444+
Self::ExpEasing {
428445
attenuation,
429446
positive_only,
430447
} => quote_export_func! {
431448
export_exp_easing(#attenuation, #positive_only)
432449
},
433450

434-
FieldExport::Flags { bits } => {
451+
Self::Flags { bits } => {
435452
let bits = bits.iter().map(ValueWithKey::to_tuple_expression);
436453

437454
quote_export_func! {
438455
export_flags(&[#(#bits),*])
439456
}
440457
}
441458

442-
FieldExport::Layers {
459+
Self::Layers {
443460
dimension: LayerDimension::_2d,
444461
kind: LayerKind::Physics,
445462
} => quote_export_func! { export_flags_2d_physics() },
446463

447-
FieldExport::Layers {
464+
Self::Layers {
448465
dimension: LayerDimension::_2d,
449466
kind: LayerKind::Render,
450467
} => quote_export_func! { export_flags_2d_render() },
451468

452-
FieldExport::Layers {
469+
Self::Layers {
453470
dimension: LayerDimension::_2d,
454471
kind: LayerKind::Navigation,
455472
} => quote_export_func! { export_flags_2d_navigation() },
456473

457-
FieldExport::Layers {
474+
Self::Layers {
458475
dimension: LayerDimension::_3d,
459476
kind: LayerKind::Physics,
460477
} => quote_export_func! { export_flags_3d_physics() },
461478

462-
FieldExport::Layers {
479+
Self::Layers {
463480
dimension: LayerDimension::_3d,
464481
kind: LayerKind::Render,
465482
} => quote_export_func! { export_flags_3d_render() },
466483

467-
FieldExport::Layers {
484+
Self::Layers {
468485
dimension: LayerDimension::_3d,
469486
kind: LayerKind::Navigation,
470487
} => quote_export_func! { export_flags_3d_navigation() },
471488

472-
FieldExport::File {
489+
Self::File {
473490
global: false,
474491
kind: FileKind::Dir,
475492
} => quote_export_func! { export_dir() },
476493

477-
FieldExport::File {
494+
Self::File {
478495
global: true,
479496
kind: FileKind::Dir,
480497
} => quote_export_func! { export_global_dir() },
481498

482-
FieldExport::File {
499+
Self::File {
483500
global,
484501
kind: FileKind::File { filter },
485502
} => {
@@ -488,12 +505,12 @@ impl FieldExport {
488505
quote_export_func! { export_file_inner(#global, #filter) }
489506
}
490507

491-
FieldExport::Multiline => quote_export_func! { export_multiline() },
508+
Self::Multiline => quote_export_func! { export_multiline() },
492509

493-
FieldExport::PlaceholderText { placeholder } => quote_export_func! {
510+
Self::PlaceholderText { placeholder } => quote_export_func! {
494511
export_placeholder(#placeholder)
495512
},
496-
FieldExport::ColorNoAlpha => quote_export_func! { export_color_no_alpha() },
513+
Self::ColorNoAlpha => quote_export_func! { export_color_no_alpha() },
497514
}
498515
}
499516
}

godot-macros/src/class/data_models/field_var.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
66
*/
77

8-
use proc_macro2::{Ident, TokenStream};
8+
use proc_macro2::{Ident, Span, TokenStream};
99
use quote::{format_ident, quote};
1010

1111
use crate::class::{
@@ -16,12 +16,13 @@ use crate::util::KvParser;
1616
use crate::{util, ParseResult};
1717

1818
/// Store info from `#[var]` attribute.
19-
#[derive(Default, Clone, Debug)]
19+
#[derive(Clone, Debug)]
2020
pub struct FieldVar {
2121
pub getter: GetterSetter,
2222
pub setter: GetterSetter,
2323
pub hint: FieldHint,
2424
pub usage_flags: UsageFlags,
25+
pub span: Span,
2526
}
2627

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

@@ -71,10 +73,23 @@ impl FieldVar {
7173
setter,
7274
hint,
7375
usage_flags,
76+
span,
7477
})
7578
}
7679
}
7780

81+
impl Default for FieldVar {
82+
fn default() -> Self {
83+
Self {
84+
getter: Default::default(),
85+
setter: Default::default(),
86+
hint: Default::default(),
87+
usage_flags: Default::default(),
88+
span: Span::call_site(),
89+
}
90+
}
91+
}
92+
7893
#[derive(Default, Clone, Eq, PartialEq, Debug)]
7994
pub enum GetterSetter {
8095
/// Getter/setter should be omitted, field is write/read only.

godot-macros/src/class/data_models/property.rs

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub fn make_property_impl(class_name: &Ident, fields: &Fields) -> TokenStream {
7070
setter,
7171
hint,
7272
mut usage_flags,
73+
..
7374
} = var;
7475

7576
let export_hint;

0 commit comments

Comments
 (0)