From fceb5f4b3c3aee5ba323c2a14cfba549293f0f4b Mon Sep 17 00:00:00 2001 From: bbb651 Date: Fri, 7 Feb 2025 18:48:26 +0200 Subject: [PATCH] wayland-scanner: Support `deprecated-since` --- wayland-client/src/lib.rs | 2 +- wayland-protocols/src/protocol_macro.rs | 2 +- wayland-scanner/src/client_gen.rs | 2 +- wayland-scanner/src/common.rs | 56 +++++++++++++++++++++---- wayland-scanner/src/parse.rs | 3 ++ wayland-scanner/src/protocol.rs | 20 ++++++++- wayland-scanner/src/server_gen.rs | 2 +- 7 files changed, 72 insertions(+), 15 deletions(-) diff --git a/wayland-client/src/lib.rs b/wayland-client/src/lib.rs index 9500c953ff6..294c7a5e2b2 100644 --- a/wayland-client/src/lib.rs +++ b/wayland-client/src/lib.rs @@ -211,7 +211,7 @@ use std::{ /// /// This module is automatically generated from the `wayland.xml` protocol specification, /// and contains the interface definitions for the core Wayland protocol. -#[allow(missing_docs)] +#[allow(missing_docs, deprecated)] pub mod protocol { use self::__interfaces::*; use crate as wayland_client; diff --git a/wayland-protocols/src/protocol_macro.rs b/wayland-protocols/src/protocol_macro.rs index 1f2ce94c81b..a27c2db9e83 100644 --- a/wayland-protocols/src/protocol_macro.rs +++ b/wayland-protocols/src/protocol_macro.rs @@ -9,7 +9,7 @@ macro_rules! wayland_protocol( mod generated { #![allow(dead_code,non_camel_case_types,unused_unsafe,unused_variables)] #![allow(non_upper_case_globals,non_snake_case,unused_imports)] - #![allow(missing_docs, clippy::all)] + #![allow(missing_docs, clippy::all, deprecated)] #[cfg(feature = "client")] pub mod client { diff --git a/wayland-scanner/src/client_gen.rs b/wayland-scanner/src/client_gen.rs index b116f55879b..9ca6b1ab599 100644 --- a/wayland-scanner/src/client_gen.rs +++ b/wayland-scanner/src/client_gen.rs @@ -18,7 +18,7 @@ fn generate_objects_for(interface: &Interface) -> TokenStream { let iface_name = Ident::new(&snake_to_camel(&interface.name), Span::call_site()); let iface_const_name = format_ident!("{}_INTERFACE", interface.name.to_ascii_uppercase()); - let enums = crate::common::generate_enums_for(interface); + let enums = crate::common::generate_enums_for(interface, Side::Client); let sinces = crate::common::gen_msg_constants(&interface.requests, &interface.events); let requests = crate::common::gen_message_enum( diff --git a/wayland-scanner/src/common.rs b/wayland-scanner/src/common.rs index f2e07b3b5e5..998cb6af38d 100644 --- a/wayland-scanner/src/common.rs +++ b/wayland-scanner/src/common.rs @@ -6,26 +6,40 @@ use quote::{format_ident, quote, ToTokens}; use crate::{protocol::*, util::*, Side}; -pub(crate) fn generate_enums_for(interface: &Interface) -> TokenStream { - interface.enums.iter().map(ToTokens::into_token_stream).collect() +pub(crate) fn generate_enums_for(interface: &Interface, side: Side) -> TokenStream { + interface.enums.iter().map(|enu| EnumSide(enu, side)).map(ToTokens::into_token_stream).collect() } -impl ToTokens for Enum { +struct EnumSide<'a>(&'a Enum, Side); + +impl ToTokens for EnumSide<'_> { fn to_tokens(&self, tokens: &mut TokenStream) { + let EnumSide(enu, side) = *self; + let enum_decl; let enum_impl; - let doc_attr = self.description.as_ref().map(description_to_doc_attr); - let ident = Ident::new(&snake_to_camel(&self.name), Span::call_site()); + let doc_attr = enu.description.as_ref().map(description_to_doc_attr); + let ident = Ident::new(&snake_to_camel(&enu.name), Span::call_site()); - if self.bitfield { - let entries = self.entries.iter().map(|entry| { + if enu.bitfield { + let entries = enu.entries.iter().map(|entry| { let doc_attr = entry .description .as_ref() .map(description_to_doc_attr) .or_else(|| entry.summary.as_ref().map(|s| to_doc_attr(s))); + // Deprecations are only for the client side since servers need to be backwards compatible + let deprecated_attr = (side == Side::Client) + .then(|| { + entry.deprecated_since.map(|since| { + let note = format!("Deprecated since version {since} of the interface"); + quote! { #[deprecated = #note] } + }) + }) + .flatten(); + let prefix = if entry.name.chars().next().unwrap().is_numeric() { "_" } else { "" }; let ident = format_ident!("{}{}", prefix, snake_to_camel(&entry.name)); @@ -33,6 +47,7 @@ impl ToTokens for Enum { quote! { #doc_attr + #deprecated_attr const #ident = #value; } }); @@ -60,13 +75,23 @@ impl ToTokens for Enum { } }; } else { - let variants = self.entries.iter().map(|entry| { + let variants = enu.entries.iter().map(|entry| { let doc_attr = entry .description .as_ref() .map(description_to_doc_attr) .or_else(|| entry.summary.as_ref().map(|s| to_doc_attr(s))); + // Deprecations are only for the client side since servers need to be backwards compatible + let deprecated_attr = (side == Side::Client) + .then(|| { + entry.deprecated_since.map(|since| { + let note = format!("Deprecated since version {since} of the interface"); + quote! { #[deprecated = #note] } + }) + }) + .flatten(); + let prefix = if entry.name.chars().next().unwrap().is_numeric() { "_" } else { "" }; let variant = format_ident!("{}{}", prefix, snake_to_camel(&entry.name)); @@ -74,6 +99,7 @@ impl ToTokens for Enum { quote! { #doc_attr + #deprecated_attr #variant = #value } }); @@ -88,7 +114,7 @@ impl ToTokens for Enum { } }; - let match_arms = self.entries.iter().map(|entry| { + let match_arms = enu.entries.iter().map(|entry| { let value = Literal::u32_unsuffixed(entry.value); let prefix = if entry.name.chars().next().unwrap().is_numeric() { "_" } else { "" }; @@ -181,6 +207,17 @@ pub(crate) fn gen_message_enum( } let doc_attr = to_doc_attr(&docs); + + // Deprecations are only for the client side since servers need to be backwards compatible + let deprecated_attr = (side == Side::Client) + .then(|| { + msg.deprecated_since.map(|since| { + let note = format!("Deprecated since version {since} of the interface"); + quote! { #[deprecated = #note] } + }) + }) + .flatten(); + let msg_name = Ident::new(&snake_to_camel(&msg.name), Span::call_site()); let msg_variant_decl = if msg.args.is_empty() { @@ -277,6 +314,7 @@ pub(crate) fn gen_message_enum( quote! { #doc_attr + #deprecated_attr #msg_variant_decl } }) diff --git a/wayland-scanner/src/parse.rs b/wayland-scanner/src/parse.rs index 55611fbfa31..ac9bcb80d97 100644 --- a/wayland-scanner/src/parse.rs +++ b/wayland-scanner/src/parse.rs @@ -198,6 +198,7 @@ fn parse_request(reader: &mut Reader, attrs: Attributes) -> Messa b"name" => request.name = decode_utf8_or_panic(attr.value.into_owned()), b"type" => request.typ = Some(parse_type(&attr.value)), b"since" => request.since = parse_or_panic(&attr.value), + b"deprecated-since" => request.deprecated_since = Some(parse_or_panic(&attr.value)), _ => {} } } @@ -258,6 +259,7 @@ fn parse_event(reader: &mut Reader, attrs: Attributes) -> Message b"name" => event.name = decode_utf8_or_panic(attr.value.into_owned()), b"type" => event.typ = Some(parse_type(&attr.value)), b"since" => event.since = parse_or_panic(&attr.value), + b"deprecated-since" => event.deprecated_since = Some(parse_or_panic(&attr.value)), _ => {} } } @@ -355,6 +357,7 @@ fn parse_entry(reader: &mut Reader, attrs: Attributes) -> Entry { }; } b"since" => entry.since = parse_or_panic(&attr.value), + b"deprecated-since" => entry.deprecated_since = Some(parse_or_panic(&attr.value)), b"summary" => { entry.summary = Some( String::from_utf8_lossy(&attr.value) diff --git a/wayland-scanner/src/protocol.rs b/wayland-scanner/src/protocol.rs index 47fbac91ec3..6188ea4ca81 100644 --- a/wayland-scanner/src/protocol.rs +++ b/wayland-scanner/src/protocol.rs @@ -43,13 +43,21 @@ pub struct Message { pub name: String, pub typ: Option, pub since: u32, + pub deprecated_since: Option, pub description: Option<(String, String)>, pub args: Vec, } impl Message { pub fn new() -> Message { - Message { name: String::new(), typ: None, since: 1, description: None, args: Vec::new() } + Message { + name: String::new(), + typ: None, + since: 1, + deprecated_since: None, + description: None, + args: Vec::new(), + } } pub fn all_null(&self) -> bool { @@ -110,13 +118,21 @@ pub struct Entry { pub name: String, pub value: u32, pub since: u16, + pub deprecated_since: Option, pub description: Option<(String, String)>, pub summary: Option, } impl Entry { pub fn new() -> Entry { - Entry { name: String::new(), value: 0, since: 1, description: None, summary: None } + Entry { + name: String::new(), + value: 0, + since: 1, + deprecated_since: None, + description: None, + summary: None, + } } } diff --git a/wayland-scanner/src/server_gen.rs b/wayland-scanner/src/server_gen.rs index af13af35e52..afd61cd241a 100644 --- a/wayland-scanner/src/server_gen.rs +++ b/wayland-scanner/src/server_gen.rs @@ -23,7 +23,7 @@ fn generate_objects_for(interface: &Interface) -> TokenStream { let iface_name = Ident::new(&snake_to_camel(&interface.name), Span::call_site()); let iface_const_name = format_ident!("{}_INTERFACE", interface.name.to_ascii_uppercase()); - let enums = crate::common::generate_enums_for(interface); + let enums = crate::common::generate_enums_for(interface, Side::Server); let msg_constants = crate::common::gen_msg_constants(&interface.requests, &interface.events); let requests = crate::common::gen_message_enum(