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

Rename items with a rule #703

Open
wants to merge 4 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 26 additions & 4 deletions docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -566,24 +566,46 @@ item_types = ["enums", "structs", "opaque", "functions"]
#
# [export]
# prefix = "capi_"
# rename_items = "snake_case"
# [export.rename]
# "MyType" = "my_cool_type"
# "MyType" = "my_cool_TYPE"
#
# You get the following results:
#
# renaming_overrides_prefixing = true:
# "MyType" => "my_cool_type"
# "MyType" => "my_cool_TYPE"
#
# renaming_overrides_prefixing = false:
# "MyType => capi_my_cool_type"
#
# default: false
renaming_overrides_prefixing = true

# Table of name conversions to apply to item names (lhs becomes rhs)
# Rename rule to apply to all exported items. This includes constants,
# structs, unions, enums, type aliases, etc. Does not apply to functions as they
# must be matched by a linker.
#
# possible values (that actually do something):
# * "ScreamingSnakeCase": MyType => MY_TYPE
# * "SnakeCase": MyType => my_type,
# * "CamelCase": MyType => myType,
# * "UpperCase": MyType => MYTYPE (not great, who uses this?)
# * "LowerCase": MyType => mytype (not great, who uses this?)
# * "None": apply no renaming
#
# technically possible values (that shouldn't have a purpose here):
# * "GeckoCase": MyType => MyType (only struct members & enum variants get a prefix)
# * "PascalCase": MyType => MyType (no-op for normal Rust PascalCase type names)
# * "QualifiedScreamingSnakeCase" => same as ScreamingSnakeCase in this context
#
# default: "None"
rename_items = "snake_case"

# Table of name conversions to apply to item names (lhs becomes rhs).
# Does not apply to function names as they must be matched by a linker.
[export.rename]
"MyType" = "my_cool_type"
"my_function" = "BetterFunctionName"
"MyOtherType" = "awesome_type"

# Table of things to prepend to the body of any struct, union, or enum that has the
# given name. This can be used to add things like methods which don't change ABI,
Expand Down
10 changes: 9 additions & 1 deletion src/bindgen/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ use crate::bindgen::ir::path::Path;
use crate::bindgen::ir::repr::ReprAlign;
pub use crate::bindgen::rename::RenameRule;

use super::rename::IdentifierType;

pub const VERSION: &str = env!("CARGO_PKG_VERSION");

/// A language type to generate bindings for.
Expand Down Expand Up @@ -317,6 +319,8 @@ pub struct ExportConfig {
pub exclude: Vec<String>,
/// Table of name conversions to apply to item names
pub rename: HashMap<String, String>,
/// A rename rule to apply to all type names
pub rename_items: RenameRule,
/// Table of raw strings to prepend to the body of items.
pub pre_body: HashMap<String, String>,
/// Table of raw strings to append to the body of items.
Expand Down Expand Up @@ -356,13 +360,17 @@ impl ExportConfig {
self.body.get(path.name()).map(|s| s.trim_matches('\n'))
}

pub(crate) fn rename(&self, item_name: &mut String) {
pub(crate) fn rename(&self, item_name: &mut String, ident_type: IdentifierType<'_>) {
if let Some(name) = self.rename.get(item_name) {
*item_name = name.clone();
if self.renaming_overrides_prefixing {
return;
}
}
if let Some(rename_rule) = self.rename_items.not_none() {
let cow = rename_rule.apply(item_name, ident_type);
*item_name = cow.into_owned();
}
if let Some(ref prefix) = self.prefix {
item_name.insert_str(0, prefix);
}
Expand Down
11 changes: 7 additions & 4 deletions src/bindgen/ir/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::bindgen::ir::{
Struct, ToCondition, Type,
};
use crate::bindgen::library::Library;
use crate::bindgen::rename::IdentifierType;
use crate::bindgen::writer::{Source, SourceWriter};
use crate::bindgen::Bindings;

Expand Down Expand Up @@ -121,13 +122,13 @@ impl Literal {
fields,
..
} => {
config.export.rename(export_name);
config.export.rename(export_name, IdentifierType::Constant);
for lit in fields.values_mut() {
lit.rename_for_config(config);
}
}
Literal::Path(ref mut name) => {
config.export.rename(name);
config.export.rename(name, IdentifierType::Constant);
}
Literal::PostfixUnaryOp { ref mut value, .. } => {
value.rename_for_config(config);
Expand Down Expand Up @@ -465,7 +466,9 @@ impl Item for Constant {

fn rename_for_config(&mut self, config: &Config) {
if self.associated_to.is_none() {
config.export.rename(&mut self.export_name);
config
.export
.rename(&mut self.export_name, IdentifierType::Constant);
}
self.value.rename_for_config(config);
self.ty.rename_for_config(config, &GenericParams::default()); // FIXME: should probably propagate something here
Expand Down Expand Up @@ -538,7 +541,7 @@ impl Constant {
Some(s) => Cow::Borrowed(s.export_name()),
None => {
let mut name = self.associated_to.as_ref().unwrap().name().to_owned();
config.export.rename(&mut name);
config.export.rename(&mut name, IdentifierType::Type);
Cow::Owned(name)
}
};
Expand Down
4 changes: 3 additions & 1 deletion src/bindgen/ir/enumeration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,9 @@ impl Item for Enum {
}

fn rename_for_config(&mut self, config: &Config) {
config.export.rename(&mut self.export_name);
config
.export
.rename(&mut self.export_name, IdentifierType::Enum);

if config.language != Language::Cxx && self.tag.is_some() {
// it makes sense to always prefix Tag with type name in C
Expand Down
5 changes: 4 additions & 1 deletion src/bindgen/ir/generic_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::ops::Deref;
use crate::bindgen::config::{Config, Language};
use crate::bindgen::declarationtyperesolver::{DeclarationType, DeclarationTypeResolver};
use crate::bindgen::ir::{Path, Type};
use crate::bindgen::rename::IdentifierType;
use crate::bindgen::utilities::IterHelpers;
use crate::bindgen::writer::{Source, SourceWriter};

Expand Down Expand Up @@ -126,7 +127,9 @@ impl GenericPath {
generic.rename_for_config(config, generic_params);
}
if !generic_params.contains(&self.path) {
config.export.rename(&mut self.export_name);
config
.export
.rename(&mut self.export_name, IdentifierType::Type);
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/bindgen/ir/opaque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::bindgen::ir::{
use crate::bindgen::library::Library;
use crate::bindgen::mangle;
use crate::bindgen::monomorph::Monomorphs;
use crate::bindgen::rename::IdentifierType;
use crate::bindgen::writer::{Source, SourceWriter};

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -91,7 +92,9 @@ impl Item for OpaqueItem {
}

fn rename_for_config(&mut self, config: &Config) {
config.export.rename(&mut self.export_name);
config
.export
.rename(&mut self.export_name, IdentifierType::Type);
}

fn add_dependencies(&self, _: &Library, _: &mut Dependencies) {}
Expand Down
4 changes: 3 additions & 1 deletion src/bindgen/ir/structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,9 @@ impl Item for Struct {
fn rename_for_config(&mut self, config: &Config) {
// Rename the name of the struct
if !(self.has_tag_field && config.language == Language::Cxx) {
config.export.rename(&mut self.export_name);
config
.export
.rename(&mut self.export_name, IdentifierType::Type);
}

// Rename the types used in fields
Expand Down
3 changes: 2 additions & 1 deletion src/bindgen/ir/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{GenericParams, GenericPath, Path};
use crate::bindgen::library::Library;
use crate::bindgen::monomorph::Monomorphs;
use crate::bindgen::rename::IdentifierType;
use crate::bindgen::utilities::IterHelpers;
use crate::bindgen::writer::{Source, SourceWriter};

Expand Down Expand Up @@ -324,7 +325,7 @@ impl ArrayLength {

fn rename_for_config(&mut self, config: &Config) {
if let ArrayLength::Name(ref mut name) = self {
config.export.rename(name);
config.export.rename(name, IdentifierType::Constant);
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/bindgen/ir/typedef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::bindgen::ir::{
use crate::bindgen::library::Library;
use crate::bindgen::mangle;
use crate::bindgen::monomorph::Monomorphs;
use crate::bindgen::rename::IdentifierType;
use crate::bindgen::writer::{Source, SourceWriter};

/// A type alias that is represented as a C typedef
Expand Down Expand Up @@ -134,7 +135,9 @@ impl Item for Typedef {
}

fn rename_for_config(&mut self, config: &Config) {
config.export.rename(&mut self.export_name);
config
.export
.rename(&mut self.export_name, IdentifierType::Type);
self.aliased.rename_for_config(config, &self.generic_params);
}

Expand Down
4 changes: 3 additions & 1 deletion src/bindgen/ir/union.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,9 @@ impl Item for Union {
}

fn rename_for_config(&mut self, config: &Config) {
config.export.rename(&mut self.export_name);
config
.export
.rename(&mut self.export_name, IdentifierType::Type);
for field in &mut self.fields {
field.ty.rename_for_config(config, &self.generic_params);
}
Expand Down
2 changes: 2 additions & 0 deletions src/bindgen/rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub enum IdentifierType<'a> {
FunctionArg,
Type,
Enum,
Constant,
}

impl<'a> IdentifierType<'a> {
Expand All @@ -23,6 +24,7 @@ impl<'a> IdentifierType<'a> {
IdentifierType::FunctionArg => "a",
IdentifierType::Type => "",
IdentifierType::Enum => "",
IdentifierType::Constant => "",
}
}
}
Expand Down
39 changes: 39 additions & 0 deletions tests/expectations/rename_items.both.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

#define capi_constant_abc 10

enum capi_enumeration {
capi_enumeration_x = 0,
capi_enumeration_y = 1,
};
typedef uint8_t capi_enumeration;

typedef struct capi_struct_abc capi_struct_abc;

typedef struct capi_union_ghi capi_union_ghi;

typedef struct capi_struct_def {
int32_t x;
float y;
} capi_struct_def;

typedef union capi_union_jkl {
int32_t x;
float y;
} capi_union_jkl;

typedef struct capi_struct_abc capi_type_alias;

#define capi_constant_expression (intptr_t)(capi_type_alias*)10

extern const int32_t StaticAbc;

void root(const struct capi_struct_abc *a,
struct capi_struct_def b,
struct capi_union_ghi c,
union capi_union_jkl d,
capi_enumeration e,
capi_type_alias f);
53 changes: 53 additions & 0 deletions tests/expectations/rename_items.both.compat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

#define capi_constant_abc 10

enum capi_enumeration
#ifdef __cplusplus
: uint8_t
#endif // __cplusplus
{
capi_enumeration_x = 0,
capi_enumeration_y = 1,
};
#ifndef __cplusplus
typedef uint8_t capi_enumeration;
#endif // __cplusplus

typedef struct capi_struct_abc capi_struct_abc;

typedef struct capi_union_ghi capi_union_ghi;

typedef struct capi_struct_def {
int32_t x;
float y;
} capi_struct_def;

typedef union capi_union_jkl {
int32_t x;
float y;
} capi_union_jkl;

typedef struct capi_struct_abc capi_type_alias;

#define capi_constant_expression (intptr_t)(capi_type_alias*)10

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

extern const int32_t StaticAbc;

void root(const struct capi_struct_abc *a,
struct capi_struct_def b,
struct capi_union_ghi c,
union capi_union_jkl d,
capi_enumeration e,
capi_type_alias f);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
39 changes: 39 additions & 0 deletions tests/expectations/rename_items.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

#define capi_constant_abc 10
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is basically the use case for allowing one rule per item type as well as a default global one. I don't often see lower_snake_case #defines in C, even in a largely lower_snake_case API. This PR already has the infrastructure for that, passing IdentifierType in to ExportConfig::rename, but hasn't implemented it (yet).


enum capi_enumeration {
capi_enumeration_x = 0,
capi_enumeration_y = 1,
};
typedef uint8_t capi_enumeration;

typedef struct capi_struct_abc capi_struct_abc;

typedef struct capi_union_ghi capi_union_ghi;

typedef struct {
int32_t x;
float y;
} capi_struct_def;

typedef union {
int32_t x;
float y;
} capi_union_jkl;

typedef capi_struct_abc capi_type_alias;

#define capi_constant_expression (intptr_t)(capi_type_alias*)10

extern const int32_t StaticAbc;

void root(const capi_struct_abc *a,
capi_struct_def b,
capi_union_ghi c,
capi_union_jkl d,
capi_enumeration e,
capi_type_alias f);