Fix #418: Use heck for case conversion
All case conversion cases seem to be covered by this crate so this greatly simplifies `rename.rs`.
This commit is contained in:
parent
4beb526516
commit
8139fbf3c7
16
Cargo.lock
generated
16
Cargo.lock
generated
@ -35,6 +35,7 @@ name = "cbindgen"
|
||||
version = "0.14.1"
|
||||
dependencies = [
|
||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -74,6 +75,14 @@ dependencies = [
|
||||
"wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.4"
|
||||
@ -240,6 +249,11 @@ dependencies = [
|
||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.7"
|
||||
@ -287,6 +301,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
|
||||
"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
|
||||
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
|
||||
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
|
||||
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
||||
@ -308,6 +323,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
|
||||
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
"checksum toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "01d1404644c8b12b16bfcffa4322403a91a451584daaaa7c28d3152e6cbc98cf"
|
||||
"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
|
||||
"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
|
||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
||||
|
@ -23,6 +23,7 @@ tempfile = "3.0"
|
||||
toml = "0.5"
|
||||
proc-macro2 = "1"
|
||||
quote = "1"
|
||||
heck = "0.3"
|
||||
|
||||
[dependencies.syn]
|
||||
version = "1.0.3"
|
||||
|
@ -139,10 +139,8 @@ impl EnumVariant {
|
||||
discriminant,
|
||||
body.map(|body| {
|
||||
(
|
||||
RenameRule::SnakeCase.apply_to_pascal_case(
|
||||
&format!("{}", variant.ident),
|
||||
IdentifierType::StructMember,
|
||||
),
|
||||
RenameRule::SnakeCase
|
||||
.apply(&format!("{}", variant.ident), IdentifierType::StructMember),
|
||||
body,
|
||||
)
|
||||
}),
|
||||
@ -452,14 +450,11 @@ impl Item for Enum {
|
||||
.iter()
|
||||
.map(|variant| {
|
||||
EnumVariant::new(
|
||||
r.apply_to_pascal_case(
|
||||
&variant.export_name,
|
||||
IdentifierType::EnumVariant(self),
|
||||
),
|
||||
r.apply(&variant.export_name, IdentifierType::EnumVariant(self)),
|
||||
variant.discriminant,
|
||||
variant.body.as_ref().map(|body| {
|
||||
(
|
||||
r.apply_to_snake_case(&body.0, IdentifierType::StructMember),
|
||||
r.apply(&body.0, IdentifierType::StructMember),
|
||||
body.1.clone(),
|
||||
)
|
||||
}),
|
||||
@ -769,7 +764,7 @@ impl Source for Enum {
|
||||
.rename_args
|
||||
.as_ref()
|
||||
.unwrap_or(&RenameRule::GeckoCase)
|
||||
.apply_to_snake_case(name, IdentifierType::FunctionArg)
|
||||
.apply(name, IdentifierType::FunctionArg)
|
||||
};
|
||||
|
||||
write!(out, "static {} {}(", self.export_name, variant.export_name);
|
||||
@ -901,7 +896,7 @@ impl Source for Enum {
|
||||
}
|
||||
|
||||
let other = if let Some(r) = config.function.rename_args {
|
||||
r.apply_to_snake_case("other", IdentifierType::FunctionArg)
|
||||
r.apply("other", IdentifierType::FunctionArg)
|
||||
} else {
|
||||
String::from("other")
|
||||
};
|
||||
|
@ -159,12 +159,7 @@ impl Function {
|
||||
self.args = self
|
||||
.args
|
||||
.iter()
|
||||
.map(|x| {
|
||||
(
|
||||
r.apply_to_snake_case(&x.0, IdentifierType::FunctionArg),
|
||||
x.1.clone(),
|
||||
)
|
||||
})
|
||||
.map(|x| (r.apply(&x.0, IdentifierType::FunctionArg), x.1.clone()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -310,7 +310,7 @@ impl Item for Struct {
|
||||
}
|
||||
} else if let Some(r) = find_first_some(&field_rules) {
|
||||
for name in names {
|
||||
*name = r.apply_to_snake_case(name, IdentifierType::StructMember);
|
||||
*name = r.apply(name, IdentifierType::StructMember);
|
||||
}
|
||||
} else if self.tuple_struct {
|
||||
// If there is a tag field, skip it
|
||||
@ -489,7 +489,7 @@ impl Source for Struct {
|
||||
.rename_args
|
||||
.as_ref()
|
||||
.unwrap_or(&RenameRule::GeckoCase)
|
||||
.apply_to_snake_case(name, IdentifierType::FunctionArg)
|
||||
.apply(name, IdentifierType::FunctionArg)
|
||||
};
|
||||
write!(out, "{}(", self.export_name());
|
||||
let vec: Vec<_> = self
|
||||
@ -516,7 +516,7 @@ impl Source for Struct {
|
||||
}
|
||||
|
||||
let other = if let Some(r) = config.function.rename_args {
|
||||
r.apply_to_snake_case("other", IdentifierType::FunctionArg)
|
||||
r.apply("other", IdentifierType::FunctionArg)
|
||||
} else {
|
||||
String::from("other")
|
||||
};
|
||||
|
@ -190,7 +190,7 @@ impl Item for Union {
|
||||
.iter()
|
||||
.map(|x| {
|
||||
(
|
||||
r.apply_to_snake_case(&x.0, IdentifierType::StructMember),
|
||||
r.apply(&x.0, IdentifierType::StructMember),
|
||||
x.1.clone(),
|
||||
x.2.clone(),
|
||||
)
|
||||
|
@ -114,6 +114,7 @@ impl<'a> Parser<'a> {
|
||||
// If we have a whitelist, check it
|
||||
if let Some(ref include) = self.config.parse.include {
|
||||
if !include.contains(&pkg_name) {
|
||||
debug!("Excluding crate {}", pkg_name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -124,6 +125,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
fn parse_crate(&mut self, pkg: &PackageRef) -> Result<(), Error> {
|
||||
assert!(self.lib.is_some());
|
||||
debug!("Parsing crate {}", pkg.name);
|
||||
self.parsed_crates.insert(pkg.name.clone());
|
||||
|
||||
// Check if we should use cargo expand for this crate
|
||||
|
@ -51,168 +51,35 @@ pub enum RenameRule {
|
||||
}
|
||||
|
||||
impl RenameRule {
|
||||
/// Applies the rename rule to a string that is formatted in PascalCase.
|
||||
pub fn apply_to_pascal_case(self, text: &str, context: IdentifierType) -> String {
|
||||
/// Applies the rename rule to a string
|
||||
pub fn apply(self, text: &str, context: IdentifierType) -> String {
|
||||
use heck::*;
|
||||
|
||||
if text.is_empty() {
|
||||
return String::new();
|
||||
}
|
||||
|
||||
match self {
|
||||
RenameRule::None => String::from(text),
|
||||
RenameRule::GeckoCase => context.to_str().to_owned() + text,
|
||||
RenameRule::None => text.to_owned(),
|
||||
RenameRule::GeckoCase => context.to_str().to_owned() + &text.to_camel_case(),
|
||||
RenameRule::LowerCase => text.to_lowercase(),
|
||||
RenameRule::UpperCase => text.to_uppercase(),
|
||||
RenameRule::PascalCase => text.to_owned(),
|
||||
RenameRule::CamelCase => text[..1].to_lowercase() + &text[1..],
|
||||
RenameRule::SnakeCase => {
|
||||
// Do not add additional `_` if the string already contains `_` e.g. `__Field`
|
||||
// Do not split consecutive capital letters
|
||||
let mut result = String::new();
|
||||
let mut add_separator = true;
|
||||
let mut prev_uppercase = false;
|
||||
for (i, c) in text.char_indices() {
|
||||
if c == '_' {
|
||||
add_separator = false;
|
||||
prev_uppercase = false;
|
||||
}
|
||||
if c.is_uppercase() {
|
||||
if i != 0 && add_separator && !prev_uppercase {
|
||||
result.push_str("_");
|
||||
} else {
|
||||
add_separator = true;
|
||||
}
|
||||
prev_uppercase = true;
|
||||
} else {
|
||||
prev_uppercase = false;
|
||||
}
|
||||
for x in c.to_lowercase() {
|
||||
result.push(x);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
RenameRule::ScreamingSnakeCase => {
|
||||
// Same as SnakeCase code above, but uses to_uppercase
|
||||
let mut result = String::new();
|
||||
let mut add_separator = true;
|
||||
let mut prev_uppercase = false;
|
||||
for (i, c) in text.char_indices() {
|
||||
if c == '_' {
|
||||
add_separator = false;
|
||||
prev_uppercase = false;
|
||||
}
|
||||
if c.is_uppercase() {
|
||||
if i != 0 && add_separator && !prev_uppercase {
|
||||
result.push_str("_");
|
||||
} else {
|
||||
add_separator = true;
|
||||
}
|
||||
prev_uppercase = true;
|
||||
} else {
|
||||
prev_uppercase = false;
|
||||
}
|
||||
for x in c.to_uppercase() {
|
||||
result.push(x);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
RenameRule::PascalCase => text.to_camel_case(),
|
||||
RenameRule::CamelCase => text.to_mixed_case(),
|
||||
RenameRule::SnakeCase => text.to_snake_case(),
|
||||
RenameRule::ScreamingSnakeCase => text.to_shouty_snake_case(),
|
||||
RenameRule::QualifiedScreamingSnakeCase => {
|
||||
let mut result = String::new();
|
||||
|
||||
if let IdentifierType::EnumVariant(e) = context {
|
||||
if let RenameRule::QualifiedScreamingSnakeCase = self {
|
||||
result.push_str(
|
||||
&RenameRule::ScreamingSnakeCase
|
||||
.apply_to_pascal_case(e.path().name(), IdentifierType::Enum),
|
||||
);
|
||||
result.push_str("_");
|
||||
}
|
||||
result.push_str(
|
||||
&RenameRule::ScreamingSnakeCase
|
||||
.apply(e.path().name(), IdentifierType::Enum),
|
||||
);
|
||||
result.push_str("_");
|
||||
}
|
||||
|
||||
result
|
||||
.push_str(&RenameRule::ScreamingSnakeCase.apply_to_pascal_case(&text, context));
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies the rename rule to a string that is formatted in snake_case.
|
||||
pub fn apply_to_snake_case(self, mut text: &str, context: IdentifierType) -> String {
|
||||
if text.is_empty() {
|
||||
return String::new();
|
||||
}
|
||||
|
||||
match self {
|
||||
RenameRule::None => String::from(text),
|
||||
RenameRule::GeckoCase => {
|
||||
if &text[..1] == "_" {
|
||||
text = &text[1..];
|
||||
}
|
||||
|
||||
context.to_str().to_owned()
|
||||
+ &RenameRule::PascalCase.apply_to_snake_case(text, context)
|
||||
}
|
||||
RenameRule::LowerCase => text.to_lowercase(),
|
||||
RenameRule::UpperCase => text.to_uppercase(),
|
||||
RenameRule::PascalCase => {
|
||||
let mut result = String::new();
|
||||
let mut is_uppercase = true;
|
||||
for c in text.chars() {
|
||||
if c == '_' {
|
||||
is_uppercase = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if is_uppercase {
|
||||
for x in c.to_uppercase() {
|
||||
result.push(x);
|
||||
}
|
||||
is_uppercase = false;
|
||||
} else {
|
||||
result.push(c);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
RenameRule::CamelCase => {
|
||||
// Same as PascalCase code above, but is_uppercase = false to start
|
||||
let mut result = String::new();
|
||||
let mut is_uppercase = false;
|
||||
for c in text.chars() {
|
||||
if c == '_' {
|
||||
is_uppercase = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if is_uppercase {
|
||||
for x in c.to_uppercase() {
|
||||
result.push(x);
|
||||
}
|
||||
is_uppercase = false;
|
||||
} else {
|
||||
result.push(c);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
RenameRule::SnakeCase => text.to_owned(),
|
||||
RenameRule::ScreamingSnakeCase => text.to_owned().to_uppercase(),
|
||||
RenameRule::QualifiedScreamingSnakeCase => {
|
||||
let mut result = String::new();
|
||||
|
||||
if let IdentifierType::EnumVariant(e) = context {
|
||||
if let RenameRule::QualifiedScreamingSnakeCase = self {
|
||||
result.push_str(
|
||||
&RenameRule::ScreamingSnakeCase
|
||||
.apply_to_snake_case(e.path().name(), IdentifierType::Enum),
|
||||
);
|
||||
result.push_str("_");
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
.push_str(&RenameRule::ScreamingSnakeCase.apply_to_snake_case(&text, context));
|
||||
result.push_str(&RenameRule::ScreamingSnakeCase.apply(&text, context));
|
||||
result
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user