Added ghost attr to elem macro (#2718)

This commit is contained in:
Sébastien d'Herbais de Thun 2023-11-19 19:23:00 +01:00 committed by GitHub
parent b479be8e9e
commit 9b5b3b2557
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 100 additions and 24 deletions

View File

@ -42,6 +42,7 @@ use crate::text::{
pub struct ParElem { pub struct ParElem {
/// The spacing between lines. /// The spacing between lines.
#[resolve] #[resolve]
#[ghost]
#[default(Em::new(0.65).into())] #[default(Em::new(0.65).into())]
pub leading: Length, pub leading: Length,
@ -54,6 +55,7 @@ pub struct ParElem {
/// Note that the current [alignment]($align) still has an effect on the /// Note that the current [alignment]($align) still has an effect on the
/// placement of the last line except if it ends with a /// placement of the last line except if it ends with a
/// [justified line break]($linebreak.justify). /// [justified line break]($linebreak.justify).
#[ghost]
#[default(false)] #[default(false)]
pub justify: bool, pub justify: bool,
@ -78,6 +80,7 @@ pub struct ParElem {
/// challenging to break in a visually /// challenging to break in a visually
/// pleasing way. /// pleasing way.
/// ``` /// ```
#[ghost]
pub linebreaks: Smart<Linebreaks>, pub linebreaks: Smart<Linebreaks>,
/// The indent the first line of a paragraph should have. /// The indent the first line of a paragraph should have.
@ -90,9 +93,11 @@ pub struct ParElem {
/// the [paragraph spacing]($block.spacing) to the [`leading`] when /// the [paragraph spacing]($block.spacing) to the [`leading`] when
/// using this property (e.g. using /// using this property (e.g. using
/// `[#show par: set block(spacing: 0.65em)]`). /// `[#show par: set block(spacing: 0.65em)]`).
#[ghost]
pub first_line_indent: Length, pub first_line_indent: Length,
/// The indent all but the first line of a paragraph should have. /// The indent all but the first line of a paragraph should have.
#[ghost]
#[resolve] #[resolve]
pub hanging_indent: Length, pub hanging_indent: Length,

View File

@ -98,6 +98,7 @@ pub struct TextElem {
/// ``` /// ```
#[default(FontList(vec![FontFamily::new("Linux Libertine")]))] #[default(FontList(vec![FontFamily::new("Linux Libertine")]))]
#[borrowed] #[borrowed]
#[ghost]
pub font: FontList, pub font: FontList,
/// Whether to allow last resort font fallback when the primary font list /// Whether to allow last resort font fallback when the primary font list
@ -118,6 +119,7 @@ pub struct TextElem {
/// هذا عربي /// هذا عربي
/// ``` /// ```
#[default(true)] #[default(true)]
#[ghost]
pub fallback: bool, pub fallback: bool,
/// The desired font style. /// The desired font style.
@ -137,6 +139,7 @@ pub struct TextElem {
/// #text(font: "Linux Libertine", style: "italic")[Italic] /// #text(font: "Linux Libertine", style: "italic")[Italic]
/// #text(font: "DejaVu Sans", style: "oblique")[Oblique] /// #text(font: "DejaVu Sans", style: "oblique")[Oblique]
/// ``` /// ```
#[ghost]
pub style: FontStyle, pub style: FontStyle,
/// The desired thickness of the font's glyphs. Accepts an integer between /// The desired thickness of the font's glyphs. Accepts an integer between
@ -158,6 +161,7 @@ pub struct TextElem {
/// #text(weight: 500)[Medium] \ /// #text(weight: 500)[Medium] \
/// #text(weight: "bold")[Bold] /// #text(weight: "bold")[Bold]
/// ``` /// ```
#[ghost]
pub weight: FontWeight, pub weight: FontWeight,
/// The desired width of the glyphs. Accepts a ratio between `{50%}` and /// The desired width of the glyphs. Accepts a ratio between `{50%}` and
@ -173,6 +177,7 @@ pub struct TextElem {
/// #text(stretch: 75%)[Condensed] \ /// #text(stretch: 75%)[Condensed] \
/// #text(stretch: 100%)[Normal] /// #text(stretch: 100%)[Normal]
/// ``` /// ```
#[ghost]
pub stretch: FontStretch, pub stretch: FontStretch,
/// The size of the glyphs. This value forms the basis of the `em` unit: /// The size of the glyphs. This value forms the basis of the `em` unit:
@ -188,6 +193,7 @@ pub struct TextElem {
#[parse(args.named_or_find("size")?)] #[parse(args.named_or_find("size")?)]
#[fold] #[fold]
#[default(Abs::pt(11.0))] #[default(Abs::pt(11.0))]
#[ghost]
pub size: TextSize, pub size: TextSize,
/// The glyph fill paint. /// The glyph fill paint.
@ -214,6 +220,7 @@ pub struct TextElem {
paint.map(|paint| paint.v) paint.map(|paint| paint.v)
})] })]
#[default(Color::BLACK.into())] #[default(Color::BLACK.into())]
#[ghost]
pub fill: Paint, pub fill: Paint,
/// The amount of space that should be added between characters. /// The amount of space that should be added between characters.
@ -223,6 +230,7 @@ pub struct TextElem {
/// Distant text. /// Distant text.
/// ``` /// ```
#[resolve] #[resolve]
#[ghost]
pub tracking: Length, pub tracking: Length,
/// The amount of space between words. /// The amount of space between words.
@ -239,6 +247,7 @@ pub struct TextElem {
/// ``` /// ```
#[resolve] #[resolve]
#[default(Rel::one())] #[default(Rel::one())]
#[ghost]
pub spacing: Rel<Length>, pub spacing: Rel<Length>,
/// Whether to automatically insert spacing between CJK and Latin characters. /// Whether to automatically insert spacing between CJK and Latin characters.
@ -250,6 +259,7 @@ pub struct TextElem {
/// #set text(cjk-latin-spacing: none) /// #set text(cjk-latin-spacing: none)
/// 第4章介绍了基本的API。 /// 第4章介绍了基本的API。
/// ``` /// ```
#[ghost]
pub cjk_latin_spacing: Smart<Option<Never>>, pub cjk_latin_spacing: Smart<Option<Never>>,
/// An amount to shift the text baseline by. /// An amount to shift the text baseline by.
@ -259,6 +269,7 @@ pub struct TextElem {
/// word. /// word.
/// ``` /// ```
#[resolve] #[resolve]
#[ghost]
pub baseline: Length, pub baseline: Length,
/// Whether certain glyphs can hang over into the margin in justified text. /// Whether certain glyphs can hang over into the margin in justified text.
@ -278,6 +289,7 @@ pub struct TextElem {
/// results in a clearer paragraph edge. /// results in a clearer paragraph edge.
/// ``` /// ```
#[default(true)] #[default(true)]
#[ghost]
pub overhang: bool, pub overhang: bool,
/// The top end of the conceptual frame around the text used for layout and /// The top end of the conceptual frame around the text used for layout and
@ -294,6 +306,7 @@ pub struct TextElem {
/// #rect(fill: aqua)[Typst] /// #rect(fill: aqua)[Typst]
/// ``` /// ```
#[default(TopEdge::Metric(TopEdgeMetric::CapHeight))] #[default(TopEdge::Metric(TopEdgeMetric::CapHeight))]
#[ghost]
pub top_edge: TopEdge, pub top_edge: TopEdge,
/// The bottom end of the conceptual frame around the text used for layout /// The bottom end of the conceptual frame around the text used for layout
@ -310,6 +323,7 @@ pub struct TextElem {
/// #rect(fill: aqua)[Typst] /// #rect(fill: aqua)[Typst]
/// ``` /// ```
#[default(BottomEdge::Metric(BottomEdgeMetric::Baseline))] #[default(BottomEdge::Metric(BottomEdgeMetric::Baseline))]
#[ghost]
pub bottom_edge: BottomEdge, pub bottom_edge: BottomEdge,
/// An [ISO 639-1/2/3 language code.](https://en.wikipedia.org/wiki/ISO_639) /// An [ISO 639-1/2/3 language code.](https://en.wikipedia.org/wiki/ISO_639)
@ -330,11 +344,13 @@ pub struct TextElem {
/// In diesem Dokument, ... /// In diesem Dokument, ...
/// ``` /// ```
#[default(Lang::ENGLISH)] #[default(Lang::ENGLISH)]
#[ghost]
pub lang: Lang, pub lang: Lang,
/// An [ISO 3166-1 alpha-2 region code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) /// An [ISO 3166-1 alpha-2 region code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)
/// ///
/// This lets the text processing pipeline make more informed choices. /// This lets the text processing pipeline make more informed choices.
#[ghost]
pub region: Option<Region>, pub region: Option<Region>,
/// The OpenType writing script. /// The OpenType writing script.
@ -364,6 +380,7 @@ pub struct TextElem {
/// #set text(lang: "ro", script: "grek") /// #set text(lang: "ro", script: "grek")
/// #scedilla // S with a cedilla /// #scedilla // S with a cedilla
/// ``` /// ```
#[ghost]
pub script: Smart<WritingScript>, pub script: Smart<WritingScript>,
/// The dominant direction for text and inline objects. Possible values are: /// The dominant direction for text and inline objects. Possible values are:
@ -391,6 +408,7 @@ pub struct TextElem {
/// هذا عربي. /// هذا عربي.
/// ``` /// ```
#[resolve] #[resolve]
#[ghost]
pub dir: TextDir, pub dir: TextDir,
/// Whether to hyphenate text to improve line breaking. When `{auto}`, text /// Whether to hyphenate text to improve line breaking. When `{auto}`, text
@ -413,6 +431,7 @@ pub struct TextElem {
/// improve justification. /// improve justification.
/// ``` /// ```
#[resolve] #[resolve]
#[ghost]
pub hyphenate: Hyphenate, pub hyphenate: Hyphenate,
/// Whether to apply kerning. /// Whether to apply kerning.
@ -431,6 +450,7 @@ pub struct TextElem {
/// Totally /// Totally
/// ``` /// ```
#[default(true)] #[default(true)]
#[ghost]
pub kerning: bool, pub kerning: bool,
/// Whether to apply stylistic alternates. /// Whether to apply stylistic alternates.
@ -451,6 +471,7 @@ pub struct TextElem {
/// 0, a, g, ß /// 0, a, g, ß
/// ``` /// ```
#[default(false)] #[default(false)]
#[ghost]
pub alternates: bool, pub alternates: bool,
/// Which stylistic set to apply. Font designers can categorize alternative /// Which stylistic set to apply. Font designers can categorize alternative
@ -458,6 +479,7 @@ pub struct TextElem {
/// you need to consult your font to know which sets are available. When set /// you need to consult your font to know which sets are available. When set
/// to an integer between `{1}` and `{20}`, enables the corresponding /// to an integer between `{1}` and `{20}`, enables the corresponding
/// OpenType font feature from `ss01`, ..., `ss20`. /// OpenType font feature from `ss01`, ..., `ss20`.
#[ghost]
pub stylistic_set: Option<StylisticSet>, pub stylistic_set: Option<StylisticSet>,
/// Whether standard ligatures are active. /// Whether standard ligatures are active.
@ -475,16 +497,19 @@ pub struct TextElem {
/// A fine ligature. /// A fine ligature.
/// ``` /// ```
#[default(true)] #[default(true)]
#[ghost]
pub ligatures: bool, pub ligatures: bool,
/// Whether ligatures that should be used sparingly are active. Setting this /// Whether ligatures that should be used sparingly are active. Setting this
/// to `{true}` enables the OpenType `dlig` font feature. /// to `{true}` enables the OpenType `dlig` font feature.
#[default(false)] #[default(false)]
#[ghost]
pub discretionary_ligatures: bool, pub discretionary_ligatures: bool,
/// Whether historical ligatures are active. Setting this to `{true}` /// Whether historical ligatures are active. Setting this to `{true}`
/// enables the OpenType `hlig` font feature. /// enables the OpenType `hlig` font feature.
#[default(false)] #[default(false)]
#[ghost]
pub historical_ligatures: bool, pub historical_ligatures: bool,
/// Which kind of numbers / figures to select. When set to `{auto}`, the /// Which kind of numbers / figures to select. When set to `{auto}`, the
@ -498,6 +523,7 @@ pub struct TextElem {
/// #set text(number-type: "old-style") /// #set text(number-type: "old-style")
/// Number 9. /// Number 9.
/// ``` /// ```
#[ghost]
pub number_type: Smart<NumberType>, pub number_type: Smart<NumberType>,
/// The width of numbers / figures. When set to `{auto}`, the default /// The width of numbers / figures. When set to `{auto}`, the default
@ -513,6 +539,7 @@ pub struct TextElem {
/// A 12 B 34. \ /// A 12 B 34. \
/// A 56 B 78. /// A 56 B 78.
/// ``` /// ```
#[ghost]
pub number_width: Smart<NumberWidth>, pub number_width: Smart<NumberWidth>,
/// Whether to have a slash through the zero glyph. Setting this to `{true}` /// Whether to have a slash through the zero glyph. Setting this to `{true}`
@ -522,6 +549,7 @@ pub struct TextElem {
/// 0, #text(slashed-zero: true)[0] /// 0, #text(slashed-zero: true)[0]
/// ``` /// ```
#[default(false)] #[default(false)]
#[ghost]
pub slashed_zero: bool, pub slashed_zero: bool,
/// Whether to turn numbers into fractions. Setting this to `{true}` /// Whether to turn numbers into fractions. Setting this to `{true}`
@ -536,6 +564,7 @@ pub struct TextElem {
/// #text(fractions: true)[1/2] /// #text(fractions: true)[1/2]
/// ``` /// ```
#[default(false)] #[default(false)]
#[ghost]
pub fractions: bool, pub fractions: bool,
/// Raw OpenType features to apply. /// Raw OpenType features to apply.
@ -551,6 +580,7 @@ pub struct TextElem {
/// 1/2 /// 1/2
/// ``` /// ```
#[fold] #[fold]
#[ghost]
pub features: FontFeatures, pub features: FontFeatures,
/// Content in which all text is styled according to the other arguments. /// Content in which all text is styled according to the other arguments.
@ -566,26 +596,31 @@ pub struct TextElem {
/// A delta to apply on the font weight. /// A delta to apply on the font weight.
#[internal] #[internal]
#[fold] #[fold]
#[ghost]
pub delta: Delta, pub delta: Delta,
/// Whether the font style should be inverted. /// Whether the font style should be inverted.
#[internal] #[internal]
#[fold] #[fold]
#[default(false)] #[default(false)]
#[ghost]
pub emph: Toggle, pub emph: Toggle,
/// Decorative lines. /// Decorative lines.
#[internal] #[internal]
#[fold] #[fold]
#[ghost]
pub deco: Decoration, pub deco: Decoration,
/// A case transformation that should be applied to the text. /// A case transformation that should be applied to the text.
#[internal] #[internal]
#[ghost]
pub case: Option<Case>, pub case: Option<Case>,
/// Whether small capital glyphs should be used. ("smcp") /// Whether small capital glyphs should be used. ("smcp")
#[internal] #[internal]
#[default(false)] #[default(false)]
#[ghost]
pub smallcaps: bool, pub smallcaps: bool,
} }

View File

@ -3,7 +3,7 @@ use super::*;
/// Expand the `#[elem]` macro. /// Expand the `#[elem]` macro.
pub fn elem(stream: TokenStream, body: syn::ItemStruct) -> Result<TokenStream> { pub fn elem(stream: TokenStream, body: syn::ItemStruct) -> Result<TokenStream> {
let element = parse(stream, &body)?; let element = parse(stream, &body)?;
Ok(create(&element)) create(&element)
} }
/// Details about an element. /// Details about an element.
@ -51,10 +51,20 @@ impl Elem {
/// ///
/// This includes: /// This includes:
/// - Fields that are not external and therefore present in the struct. /// - Fields that are not external and therefore present in the struct.
/// - Fields that are ghost fields.
fn real_fields(&self) -> impl Iterator<Item = &Field> + Clone { fn real_fields(&self) -> impl Iterator<Item = &Field> + Clone {
self.fields.iter().filter(|field| !field.external) self.fields.iter().filter(|field| !field.external)
} }
/// Fields that are present in the struct.
///
/// This includes:
/// - Fields that are not external and therefore present in the struct.
/// - Fields that are not ghost fields.
fn present_fields(&self) -> impl Iterator<Item = &Field> + Clone {
self.real_fields().filter(|field| !field.ghost)
}
/// Fields that are inherent to the element. /// Fields that are inherent to the element.
fn inherent_fields(&self) -> impl Iterator<Item = &Field> + Clone { fn inherent_fields(&self) -> impl Iterator<Item = &Field> + Clone {
self.real_fields().filter(|field| field.inherent()) self.real_fields().filter(|field| field.inherent())
@ -91,7 +101,7 @@ impl Elem {
/// This includes: /// This includes:
/// - Fields that are not synthesized (guarantees equality before and after synthesis). /// - Fields that are not synthesized (guarantees equality before and after synthesis).
fn eq_fields(&self) -> impl Iterator<Item = &Field> + Clone { fn eq_fields(&self) -> impl Iterator<Item = &Field> + Clone {
self.real_fields().filter(|field| !field.synthesized) self.present_fields().filter(|field| !field.synthesized)
} }
/// Fields that are relevant for `Construct` impl. /// Fields that are relevant for `Construct` impl.
@ -125,6 +135,7 @@ struct Field {
external: bool, external: bool,
synthesized: bool, synthesized: bool,
borrowed: bool, borrowed: bool,
ghost: bool,
forced_variant: Option<usize>, forced_variant: Option<usize>,
parse: Option<BlockWithReturn>, parse: Option<BlockWithReturn>,
default: Option<syn::Expr>, default: Option<syn::Expr>,
@ -133,7 +144,7 @@ struct Field {
impl Field { impl Field {
/// Whether the field is present on every instance of the element. /// Whether the field is present on every instance of the element.
fn inherent(&self) -> bool { fn inherent(&self) -> bool {
self.required || self.variadic (self.required || self.variadic) && !self.ghost
} }
/// Whether the field can be used with set rules. /// Whether the field can be used with set rules.
@ -226,6 +237,7 @@ fn parse_field(field: &syn::Field) -> Result<Field> {
synthesized: has_attr(&mut attrs, "synthesized"), synthesized: has_attr(&mut attrs, "synthesized"),
fold: has_attr(&mut attrs, "fold"), fold: has_attr(&mut attrs, "fold"),
resolve: has_attr(&mut attrs, "resolve"), resolve: has_attr(&mut attrs, "resolve"),
ghost: has_attr(&mut attrs, "ghost"),
parse: parse_attr(&mut attrs, "parse")?.flatten(), parse: parse_attr(&mut attrs, "parse")?.flatten(),
default: parse_attr::<syn::Expr>(&mut attrs, "default")?.flatten(), default: parse_attr::<syn::Expr>(&mut attrs, "default")?.flatten(),
vis: field.vis.clone(), vis: field.vis.clone(),
@ -264,20 +276,31 @@ fn parse_field(field: &syn::Field) -> Result<Field> {
} }
/// Produce the element's definition. /// Produce the element's definition.
fn create(element: &Elem) -> TokenStream { fn create(element: &Elem) -> Result<TokenStream> {
let Elem { vis, ident, docs, .. } = element; let Elem { vis, ident, docs, .. } = element;
if element.fields.iter().any(|field| field.ghost)
&& element
.capabilities
.iter()
.all(|capability| capability != "Construct")
{
bail!(ident, "cannot have ghost fields and have `Construct` auto generated");
}
let all = element.real_fields(); let all = element.real_fields();
let present = element.present_fields();
let settable = all.clone().filter(|field| !field.synthesized && field.settable()); let settable = all.clone().filter(|field| !field.synthesized && field.settable());
let fields = all.clone().map(create_field); let fields = present.clone().map(create_field);
let fields_enum = create_fields_enum(element); let fields_enum = create_fields_enum(element);
let new = create_new_func(element); let new = create_new_func(element);
let field_methods = all.clone().map(|field| create_field_method(element, field)); let field_methods = all.clone().map(|field| create_field_method(element, field));
let field_in_methods = let field_in_methods =
settable.clone().map(|field| create_field_in_method(element, field)); settable.clone().map(|field| create_field_in_method(element, field));
let with_field_methods = all.clone().map(create_with_field_method); let with_field_methods = present.clone().map(create_with_field_method);
let push_field_methods = all.clone().map(create_push_field_method); let push_field_methods = present.clone().map(create_push_field_method);
let field_style_methods = let field_style_methods =
settable.clone().map(|field| create_set_field_method(element, field)); settable.clone().map(|field| create_set_field_method(element, field));
@ -300,7 +323,7 @@ fn create(element: &Elem) -> TokenStream {
} }
}); });
quote! { Ok(quote! {
#[doc = #docs] #[doc = #docs]
#[derive(Debug, Clone, Hash)] #[derive(Debug, Clone, Hash)]
#[allow(clippy::derived_hash_with_manual_eq)] #[allow(clippy::derived_hash_with_manual_eq)]
@ -335,7 +358,7 @@ fn create(element: &Elem) -> TokenStream {
::typst::eval::Value::Content(::typst::model::Content::new(self)) ::typst::eval::Value::Content(::typst::model::Content::new(self))
} }
} }
} })
} }
/// Create a field declaration. /// Create a field declaration.
@ -459,12 +482,14 @@ fn create_new_func(element: &Elem) -> TokenStream {
let defaults = element let defaults = element
.fields .fields
.iter() .iter()
.filter(|field| !field.external && !field.inherent() && !field.synthesized) .filter(|field| {
!field.external && !field.inherent() && !field.synthesized && !field.ghost
})
.map(|Field { ident, .. }| quote! { #ident: None }); .map(|Field { ident, .. }| quote! { #ident: None });
let default_synthesized = element let default_synthesized = element
.fields .fields
.iter() .iter()
.filter(|field| !field.external && field.synthesized) .filter(|field| !field.external && field.synthesized && !field.ghost)
.map(|Field { ident, default, .. }| { .map(|Field { ident, default, .. }| {
if let Some(expr) = default { if let Some(expr) = default {
quote! { #ident: #expr } quote! { #ident: #expr }
@ -591,7 +616,14 @@ fn create_field_in_method(element: &Elem, field: &Field) -> TokenStream {
/// Create an accessor methods for a field. /// Create an accessor methods for a field.
fn create_field_method(element: &Elem, field: &Field) -> TokenStream { fn create_field_method(element: &Elem, field: &Field) -> TokenStream {
let Field { vis, docs, ident, output, .. } = field; let Field { vis, docs, ident, output, ghost, .. } = field;
let inherent = if *ghost {
quote! { None }
} else {
quote! { self.#ident.as_ref() }
};
if (field.inherent() && !field.synthesized) if (field.inherent() && !field.synthesized)
|| (field.synthesized && field.default.is_some()) || (field.synthesized && field.default.is_some())
{ {
@ -610,8 +642,7 @@ fn create_field_method(element: &Elem, field: &Field) -> TokenStream {
} }
} }
} else if field.borrowed { } else if field.borrowed {
let access = let access = create_style_chain_access(element, field, inherent);
create_style_chain_access(element, field, quote! { self.#ident.as_ref() });
quote! { quote! {
#[doc = #docs] #[doc = #docs]
@ -620,8 +651,7 @@ fn create_field_method(element: &Elem, field: &Field) -> TokenStream {
} }
} }
} else { } else {
let access = let access = create_style_chain_access(element, field, inherent);
create_style_chain_access(element, field, quote! { self.#ident.as_ref() });
quote! { quote! {
#[doc = #docs] #[doc = #docs]
@ -697,16 +727,22 @@ fn create_native_elem_impl(element: &Elem) -> TokenStream {
let name = &field.enum_ident; let name = &field.enum_ident;
let field_ident = &field.ident; let field_ident = &field.ident;
quote! { if field.ghost {
<#elem as #model::ElementFields>::Fields::#name => Some( quote! {
::typst::eval::IntoValue::into_value(self.#field_ident.clone()) <#elem as #model::ElementFields>::Fields::#name => None,
), }
} else {
quote! {
<#elem as #model::ElementFields>::Fields::#name => Some(
::typst::eval::IntoValue::into_value(self.#field_ident.clone())
),
}
} }
}); });
// Fields that can be set using the `set_field` method. // Fields that can be set using the `set_field` method.
let field_set_matches = element.visible_fields() let field_set_matches = element.visible_fields()
.filter(|field| field.settable() && !field.synthesized).map(|field| { .filter(|field| field.settable() && !field.synthesized && !field.ghost).map(|field| {
let elem = &element.ident; let elem = &element.ident;
let name = &field.enum_ident; let name = &field.enum_ident;
let field_ident = &field.ident; let field_ident = &field.ident;
@ -722,7 +758,7 @@ fn create_native_elem_impl(element: &Elem) -> TokenStream {
// Fields that are inherent. // Fields that are inherent.
let field_inherent_matches = element let field_inherent_matches = element
.visible_fields() .visible_fields()
.filter(|field| field.inherent()) .filter(|field| field.inherent() && !field.ghost)
.map(|field| { .map(|field| {
let elem = &element.ident; let elem = &element.ident;
let name = &field.enum_ident; let name = &field.enum_ident;
@ -739,7 +775,7 @@ fn create_native_elem_impl(element: &Elem) -> TokenStream {
// Fields that cannot be set or are internal create an error. // Fields that cannot be set or are internal create an error.
let field_not_set_matches = element let field_not_set_matches = element
.real_fields() .real_fields()
.filter(|field| field.internal || field.synthesized) .filter(|field| field.internal || field.synthesized || field.ghost)
.map(|field| { .map(|field| {
let elem = &element.ident; let elem = &element.ident;
let ident = &field.enum_ident; let ident = &field.enum_ident;
@ -798,7 +834,7 @@ fn create_native_elem_impl(element: &Elem) -> TokenStream {
// Creation of the fields dictionary for optional fields. // Creation of the fields dictionary for optional fields.
let field_opt_dict = element let field_opt_dict = element
.visible_fields() .visible_fields()
.filter(|field| !field.inherent()) .filter(|field| !field.inherent() && !field.ghost)
.clone() .clone()
.map(|field| { .map(|field| {
let name = &field.name; let name = &field.name;