Skip to content

Commit

Permalink
Merge pull request #794 from rust-embedded/idents
Browse files Browse the repository at this point in the history
Custom prefix/case/suffix for identifiers
  • Loading branch information
Emilgardis authored Jan 3, 2024
2 parents 8deac04 + 6e1185f commit 454886e
Show file tree
Hide file tree
Showing 10 changed files with 252 additions and 186 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]

- Custom prefix/case/suffix for identifiers

## [v0.31.3] - 2023-12-25

- Add `svd::Device` validation after parsing by `serde`
Expand Down
39 changes: 15 additions & 24 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ html-escape = "0.2"

[dependencies.svd-parser]
features = ["expand"]
version = "0.14.4"
version = "0.14.5"

[dependencies.svd-rs]
features = ["serde"]
version = "0.14.6"
version = "0.14.7"

[dependencies.syn]
version = "2.0"
Expand Down
85 changes: 83 additions & 2 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use anyhow::{bail, Result};
use std::path::{Path, PathBuf};

#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
#[derive(Clone, PartialEq, Eq, Debug, Default)]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Config {
pub target: Target,
pub atomics: bool,
Expand All @@ -28,6 +27,7 @@ pub struct Config {
pub interrupt_link_section: Option<String>,
pub reexport_core_peripherals: bool,
pub reexport_interrupt: bool,
pub ident_formats: IdentFormats,
}

#[allow(clippy::upper_case_acronyms)]
Expand Down Expand Up @@ -116,3 +116,84 @@ impl SourceType {
.unwrap_or_default()
}
}

#[cfg_attr(
feature = "serde",
derive(serde::Deserialize),
serde(rename_all = "lowercase")
)]
#[derive(Clone, Debug, PartialEq, Eq, Default)]
#[non_exhaustive]
pub enum Case {
#[default]
Constant,
Pascal,
Snake,
}

#[derive(Clone, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
pub struct IdentFormat {
pub case: Option<Case>,
pub prefix: String,
pub suffix: String,
}

impl IdentFormat {
pub fn case(mut self, case: Case) -> Self {
self.case = Some(case);
self
}
pub fn constant_case(mut self) -> Self {
self.case = Some(Case::Constant);
self
}
pub fn pascal_case(mut self) -> Self {
self.case = Some(Case::Pascal);
self
}
pub fn scake_case(mut self) -> Self {
self.case = Some(Case::Pascal);
self
}
pub fn prefix(mut self, prefix: &str) -> Self {
self.prefix = prefix.into();
self
}
pub fn suffix(mut self, suffix: &str) -> Self {
self.suffix = suffix.into();
self
}
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
pub struct IdentFormats {
pub field_reader: IdentFormat,
pub field_writer: IdentFormat,
pub enum_name: IdentFormat,
pub enum_write_name: IdentFormat,
pub enum_value: IdentFormat,
pub interrupt: IdentFormat,
pub cluster: IdentFormat,
pub register: IdentFormat,
pub register_spec: IdentFormat,
pub peripheral: IdentFormat,
}

impl Default for IdentFormats {
fn default() -> Self {
Self {
field_reader: IdentFormat::default().constant_case().suffix("_R"),
field_writer: IdentFormat::default().constant_case().suffix("_W"),
enum_name: IdentFormat::default().constant_case().suffix("_A"),
enum_write_name: IdentFormat::default().constant_case().suffix("_AW"),
enum_value: IdentFormat::default().constant_case(),
interrupt: IdentFormat::default().constant_case(),
cluster: IdentFormat::default().constant_case(),
register: IdentFormat::default().constant_case(),
register_spec: IdentFormat::default().constant_case().suffix("_SPEC"),
peripheral: IdentFormat::default().constant_case(),
}
}
}
53 changes: 20 additions & 33 deletions src/generate/device.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
use crate::svd::{array::names, Device, Peripheral};
use proc_macro2::{Ident, Span, TokenStream};
use proc_macro2::{Span, TokenStream};
use quote::{quote, ToTokens};

use log::debug;
use std::borrow::Cow;
use std::fs::File;
use std::io::Write;
use std::path::Path;

use crate::config::{Config, Target};
use crate::util::{self, ToSanitizedCase};
use crate::util::{self, ident, ToSanitizedCase};
use anyhow::{Context, Result};

use crate::generate::{interrupt, peripheral};
Expand Down Expand Up @@ -231,48 +230,36 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
feature_attribute.extend(quote! { #[cfg(feature = #feature_name)] })
};

let span = Span::call_site();
match p {
Peripheral::Single(_p) => {
let p_name = util::name_of(p, config.ignore_groups);
let p_snake = p_name.to_sanitized_snake_case();
let p = p_name.to_sanitized_constant_case();
let id = Ident::new(&p, Span::call_site());
let p_ty = ident(&p_name, &config.ident_formats.peripheral, span);
if config.feature_peripheral {
feature_attribute.extend(quote! { #[cfg(feature = #p_snake)] })
};
fields.extend(quote! {
#[doc = #p]
#[doc = #p_name]
#feature_attribute
pub #id: #id,
pub #p_ty: #p_ty,
});
exprs.extend(quote!(#feature_attribute #id: #id { _marker: PhantomData },));
exprs.extend(quote!(#feature_attribute #p_ty: #p_ty { _marker: PhantomData },));
}
Peripheral::Array(_p, dim_element) => {
let p_names: Vec<Cow<str>> = names(p, dim_element).map(|n| n.into()).collect();
let p = p_names.iter().map(|p| p.to_sanitized_constant_case());
let ids_f = p.clone().map(|p| Ident::new(&p, Span::call_site()));
let ids_e = ids_f.clone();
let feature_attribute = p_names
.iter()
.map(|p_name| {
let p_snake = p_name.to_sanitized_snake_case();
let mut feature_attribute = feature_attribute.clone();
if config.feature_peripheral {
feature_attribute.extend(quote! { #[cfg(feature = #p_snake)] })
};
feature_attribute
})
.collect::<Vec<_>>();
fields.extend(quote! {
#(
#[doc = #p]
Peripheral::Array(p, dim_element) => {
for p_name in names(p, dim_element) {
let p_snake = p_name.to_sanitized_snake_case();
let p_ty = ident(&p_name, &config.ident_formats.peripheral, span);
if config.feature_peripheral {
feature_attribute.extend(quote! { #[cfg(feature = #p_snake)] })
};
fields.extend(quote! {
#[doc = #p_name]
#feature_attribute
pub #ids_f: #ids_f,
)*
});
exprs.extend(
quote!(#(#feature_attribute #ids_e: #ids_e { _marker: PhantomData },)*),
);
pub #p_ty: #p_ty,
});
exprs.extend(quote!(#feature_attribute #p_ty: #p_ty { _marker: PhantomData },));
}
}
}
}
Expand Down
15 changes: 8 additions & 7 deletions src/generate/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::svd::Peripheral;
use proc_macro2::{Span, TokenStream};
use quote::quote;

use crate::util::{self, ToSanitizedCase};
use crate::util::{self, ident, ToSanitizedCase};
use crate::{Config, Target};
use anyhow::Result;

Expand Down Expand Up @@ -46,14 +46,15 @@ pub fn render(
// Current position in the vector table
let mut pos = 0;
let mut mod_items = TokenStream::new();
let span = Span::call_site();
for interrupt in &interrupts {
while pos < interrupt.0.value {
elements.extend(quote!(Vector { _reserved: 0 },));
pos += 1;
}
pos += 1;

let name_constant_case = interrupt.0.name.to_constant_case_ident(Span::call_site());
let i_ty = ident(&interrupt.0.name, &config.ident_formats.interrupt, span);
let description = format!(
"{} - {}",
interrupt.0.value,
Expand Down Expand Up @@ -89,25 +90,25 @@ pub fn render(
variants.extend(quote! {
#[doc = #description]
#feature_attribute
#name_constant_case = #value,
#i_ty = #value,
});

from_arms.extend(quote! {
#feature_attribute
#value => Ok(Interrupt::#name_constant_case),
#value => Ok(Interrupt::#i_ty),
});

if feature_attribute_flag {
elements.extend(quote! {
#not_feature_attribute
Vector { _reserved: 0 },
#feature_attribute
Vector { _handler: #name_constant_case },
Vector { _handler: #i_ty },
});
} else {
elements.extend(quote!(Vector { _handler: #name_constant_case },));
elements.extend(quote!(Vector { _handler: #i_ty },));
}
names.push(name_constant_case);
names.push(i_ty);
names_cfg_attr.push(feature_attribute);
}

Expand Down
Loading

0 comments on commit 454886e

Please sign in to comment.