Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/rust_nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ jobs:
- uses: actions/checkout@v4
- run: rustup update nightly && rustup default nightly
- run: rustup component add rustfmt
- run: rustup component add clippy
- name: Check fmt
run: cargo fmt -- --check
- name: Clippy
run: cargo clippy -- -Dwarnings
- name: Test
run: cargo test
4 changes: 2 additions & 2 deletions java-spaghetti-gen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ categories = ["development-tools::ffi"]
license = "MIT OR Apache-2.0"

[dependencies]
cafebabe = "0.8.0"
cafebabe = "0.9.0"
clap = { version = "4", features = ["derive"] }
bitflags = "2.8.0"
serde = "1.0.197"
serde_derive = "1.0.197"
toml = "0.8.10"
zip = "2.2.2"
zip = "4.1.0"
quote = "1.0.40"
proc-macro2 = "1.0.95"
anyhow = "1.0.98"
Expand Down
2 changes: 1 addition & 1 deletion java-spaghetti-gen/src/config/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ fn expand_vars(string: String) -> String {
if let Ok(replacement) = std::env::var(segment) {
buf.push_str(&replacement[..]);
} else {
println!("cargo:rerun-if-env-changed={}", segment);
println!("cargo:rerun-if-env-changed={segment}");
buf.push('%');
buf.push_str(segment);
buf.push('%');
Expand Down
9 changes: 5 additions & 4 deletions java-spaghetti-gen/src/emit_rust/class_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ use super::fields::RustTypeFlavor;
use super::methods::Method;
use crate::emit_rust::Context;
use crate::emit_rust::fields::emit_rust_type;
use crate::parser_util::{Id, emit_field_descriptor};
use crate::parser_util::Id;

impl Class {
#[allow(clippy::vec_init_then_push)]
pub(crate) fn write_proxy(&self, context: &Context, methods: &[Method]) -> anyhow::Result<TokenStream> {
let mut emit_reject_reasons = Vec::new();

Expand Down Expand Up @@ -204,11 +205,11 @@ fn mangle_native_method(path: &str, name: &str, args: &[FieldDescriptor]) -> Str
let mut res = String::new();
res.push_str("Java_");
res.push_str(&mangle_native(path));
res.push_str("_");
res.push('_');
res.push_str(&mangle_native(name));
res.push_str("__");
for d in args {
res.push_str(&mangle_native(&emit_field_descriptor(d)));
res.push_str(&mangle_native(&d.to_string()));
}

res
Expand All @@ -219,7 +220,7 @@ fn mangle_native(s: &str) -> String {
for c in s.chars() {
match c {
'0'..='9' | 'a'..='z' | 'A'..='Z' => res.push(c),
'/' => res.push_str("_"),
'/' => res.push('_'),
'_' => res.push_str("_1"),
';' => res.push_str("_2"),
'[' => res.push_str("_3"),
Expand Down
6 changes: 3 additions & 3 deletions java-spaghetti-gen/src/emit_rust/classes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ impl Class {
};

let docs = match KnownDocsUrl::from_class(context, self.java.path()) {
Some(url) => format!("{} {} {}", visibility, keyword, url),
None => format!("{} {} {}", visibility, keyword, self.java.path().as_str()),
Some(url) => format!("{visibility} {keyword} {url}"),
None => format!("{visibility} {keyword} {}", self.java.path().as_str()),
};

let rust_name = format_ident!("{}", &self.rust.struct_name);
Expand Down Expand Up @@ -235,7 +235,7 @@ impl Class {

out.extend(quote!(impl #rust_name { #contents }));

if context.proxy_included(&self.java.path().as_str()) {
if context.proxy_included(self.java.path().as_str()) {
out.extend(self.write_proxy(context, &methods)?);
}

Expand Down
20 changes: 10 additions & 10 deletions java-spaghetti-gen/src/emit_rust/fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use super::cstring;
use super::known_docs_url::KnownDocsUrl;
use crate::emit_rust::Context;
use crate::identifiers::{FieldMangling, IdentifierManglingError};
use crate::parser_util::{ClassName, IdBuf, IterableId, JavaClass, JavaField, emit_field_descriptor};
use crate::parser_util::{Id, JavaClass, JavaField};

pub struct Field<'a> {
pub class: &'a JavaClass,
Expand Down Expand Up @@ -120,10 +120,10 @@ impl<'a> Field<'a> {
match self.rust_names.as_ref().map_err(|e| anyhow!("bad mangling: {e}"))? {
FieldMangling::ConstValue(constant, value) => {
let constant = format_ident!("{}", constant);
let value = emit_constant(&value, descriptor);
let value = emit_constant(value, descriptor);
let ty = if descriptor.dimensions == 0
&& let FieldType::Object(cls) = &descriptor.field_type
&& ClassName::from(cls).is_string_class()
&& Id::from(cls).is_string_class()
{
quote!(&'static str)
} else {
Expand Down Expand Up @@ -154,7 +154,7 @@ impl<'a> Field<'a> {
};

let java_name = cstring(self.java.name());
let descriptor = cstring(&emit_field_descriptor(self.java.descriptor()));
let descriptor = cstring(&self.java.descriptor().to_string());

let get_docs = format!("**get** {docs}");
let set_docs = format!("**set** {docs}");
Expand Down Expand Up @@ -208,14 +208,14 @@ pub fn emit_constant(constant: &LiteralConstant<'_>, descriptor: &FieldDescripto
let value = *value as i16;
quote!(#value)
}
_ => panic!("invalid constant for char {:?}", constant),
_ => panic!("invalid constant for char {constant:?}"),
};
}
if descriptor.field_type == FieldType::Boolean && descriptor.dimensions == 0 {
return match constant {
LiteralConstant::Integer(0) => quote!(false),
LiteralConstant::Integer(1) => quote!(true),
_ => panic!("invalid constant for boolean {:?}", constant),
_ => panic!("invalid constant for boolean {constant:?}"),
};
}

Expand Down Expand Up @@ -287,11 +287,11 @@ pub fn emit_rust_type(
FieldType::Float => quote!(f32),
FieldType::Double => quote!(f64),
FieldType::Object(class_name) => {
let class = IdBuf::from(class_name);
let class = Id::from(class_name);
if !context.all_classes.contains_key(class.as_str()) {
reject_reasons.push("ERROR: missing class for field/argument type");
}
if let Ok(path) = context.java_to_rust_path(class.as_id(), mod_) {
if let Ok(path) = context.java_to_rust_path(class, mod_) {
flavorify(path, flavor)
} else {
reject_reasons.push("ERROR: Failed to resolve JNI path to Rust path for class type");
Expand All @@ -313,13 +313,13 @@ pub fn emit_rust_type(
FieldType::Float => quote!(::java_spaghetti::FloatArray),
FieldType::Double => quote!(::java_spaghetti::DoubleArray),
FieldType::Object(class_name) => {
let class = IdBuf::from(class_name);
let class = Id::from(class_name);

if !context.all_classes.contains_key(class.as_str()) {
reject_reasons.push("ERROR: missing class for field type");
}

let path = match context.java_to_rust_path(class.as_id(), mod_) {
let path = match context.java_to_rust_path(class, mod_) {
Ok(path) => path,
Err(_) => {
reject_reasons.push("ERROR: Failed to resolve JNI path to Rust path for class type");
Expand Down
4 changes: 2 additions & 2 deletions java-spaghetti-gen/src/emit_rust/known_docs_url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use cafebabe::descriptors::{FieldDescriptor, FieldType};

use super::methods::Method;
use crate::emit_rust::Context;
use crate::parser_util::{Id, IdBuf};
use crate::parser_util::Id;

pub(crate) struct KnownDocsUrl {
pub(crate) label: String,
Expand Down Expand Up @@ -149,7 +149,7 @@ impl KnownDocsUrl {
FieldType::Float => "float",
FieldType::Double => "double",
FieldType::Object(ref class_name) => {
let class = IdBuf::from(class_name);
let class = Id::from(class_name);
obj_arg = class
.as_str()
.replace('/', pattern.argument_namespace_separator.as_str())
Expand Down
8 changes: 4 additions & 4 deletions java-spaghetti-gen/src/emit_rust/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::fields::{RustTypeFlavor, emit_fragment_type, emit_rust_type};
use super::known_docs_url::KnownDocsUrl;
use crate::emit_rust::Context;
use crate::identifiers::MethodManglingStyle;
use crate::parser_util::{JavaClass, JavaMethod, emit_method_descriptor};
use crate::parser_util::{JavaClass, JavaMethod};

pub struct Method<'a> {
pub class: &'a JavaClass,
Expand Down Expand Up @@ -48,7 +48,7 @@ impl<'a> Method<'a> {
"{}\x1f{}\x1f{}",
self.class.path().as_str(),
self.java.name(),
emit_method_descriptor(self.java.descriptor())
self.java.descriptor()
);

let ignored = context.config.ignore_class_methods.contains(&java_class_method)
Expand Down Expand Up @@ -147,7 +147,7 @@ impl<'a> Method<'a> {

let docs = match KnownDocsUrl::from_method(context, self) {
Some(url) => format!("{url}"),
None => format!("{}", self.java.name()),
None => self.java.name().to_string(),
};

let throwable = context.throwable_rust_path(mod_);
Expand All @@ -162,7 +162,7 @@ impl<'a> Method<'a> {
};

let java_name = cstring(self.java.name());
let descriptor = cstring(&emit_method_descriptor(self.java.descriptor()));
let descriptor = cstring(&self.java.descriptor().to_string());
let method_name = format_ident!("{method_name}");

let call = if self.java.is_constructor() {
Expand Down
2 changes: 1 addition & 1 deletion java-spaghetti-gen/src/emit_rust/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl<'a> Context<'a> {
pub fn java_to_rust_path(&self, java_class: parser_util::Id, mod_: &str) -> Result<TokenStream, Box<dyn Error>> {
let m = Class::mod_for(self, java_class)?;
let s = Class::name_for(self, java_class)?;
let fqn = format!("{}::{}", m, s);
let fqn = format!("{m}::{s}");

// Calculate relative path from B to A.
let b: Vec<&str> = mod_.split("::").collect();
Expand Down
8 changes: 4 additions & 4 deletions java-spaghetti-gen/src/emit_rust/modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ impl Module {
for (name, module) in self.modules.iter() {
writeln!(out)?;

writeln!(out, "pub mod {} {{", name)?;
writeln!(out, "pub mod {name} {{")?;
module.write(context, out)?;
writeln!(out, "}}")?;
}

for (_, class) in self.classes.iter() {
let res = class.write(context)?;
out.write(dumb_format(res).as_bytes())?;
out.write_all(dumb_format(res).as_bytes())?;
}

Ok(())
Expand Down Expand Up @@ -61,7 +61,7 @@ struct DumbFormatter {

impl DumbFormatter {
fn newline(&mut self) {
self.f.push_str("\n");
self.f.push('\n');
for _ in 0..self.indent {
self.f.push_str(" ");
}
Expand All @@ -71,7 +71,7 @@ impl DumbFormatter {

fn pre_write(&mut self) {
if self.space && !self.after_newline {
self.f.push_str(" ");
self.f.push(' ');
}
self.space = false;
self.after_newline = false;
Expand Down
20 changes: 4 additions & 16 deletions java-spaghetti-gen/src/identifiers/method_mangling_style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use cafebabe::descriptors::{FieldType, MethodDescriptor};
use serde_derive::Deserialize;

use super::rust_identifier::{IdentifierManglingError, javaify_identifier, rustify_identifier};
use crate::parser_util::{ClassName, IdPart};
use crate::parser_util::{Id, IdPart};

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "snake_case")]
Expand Down Expand Up @@ -75,7 +75,7 @@ pub enum MethodManglingStyle {
fn method_mangling_style_mangle_test() {
use std::borrow::Cow;

use cafebabe::descriptors::{FieldDescriptor, ReturnDescriptor, UnqualifiedSegment};
use cafebabe::descriptors::{ClassName, FieldDescriptor, ReturnDescriptor};

let desc_no_arg_ret_v = MethodDescriptor {
parameters: Vec::new(),
Expand All @@ -93,19 +93,7 @@ fn method_mangling_style_mangle_test() {
let desc_arg_obj_ret_v = MethodDescriptor {
parameters: vec![FieldDescriptor {
dimensions: 0,
field_type: FieldType::Object(cafebabe::descriptors::ClassName {
segments: vec![
UnqualifiedSegment {
name: Cow::Borrowed("java"),
},
UnqualifiedSegment {
name: Cow::Borrowed("lang"),
},
UnqualifiedSegment {
name: Cow::Borrowed("Object"),
},
],
}),
field_type: FieldType::Object(ClassName::try_from(Cow::Borrowed("java/lang/Object")).unwrap()),
}],
return_type: ReturnDescriptor::Void,
};
Expand Down Expand Up @@ -245,7 +233,7 @@ impl MethodManglingStyle {
FieldType::Float => buffer.push_str("_float"),
FieldType::Double => buffer.push_str("_double"),
FieldType::Object(class_name) => {
let class = ClassName::from(class_name);
let class = Id::from(class_name);

if long_sig {
for component in class.iter() {
Expand Down
4 changes: 2 additions & 2 deletions java-spaghetti-gen/src/parser_util/class.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use std::borrow::Cow;
use std::marker::PhantomPinned;
use std::pin::Pin;

pub use cafebabe::ClassAccessFlags;
use cafebabe::attributes::AttributeData;
use cafebabe::descriptors::ClassName;

use super::Id;

Expand Down Expand Up @@ -79,7 +79,7 @@ impl JavaClass {
self.get().super_class.as_ref().map(|class| Id(class))
}

pub fn interfaces(&self) -> std::slice::Iter<'_, Cow<'_, str>> {
pub fn interfaces(&self) -> std::slice::Iter<'_, ClassName<'_>> {
self.get().interfaces.iter()
}

Expand Down
32 changes: 1 addition & 31 deletions java-spaghetti-gen/src/parser_util/field.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
use std::fmt::Write;

use cafebabe::FieldAccessFlags;
use cafebabe::attributes::AttributeData;
use cafebabe::constant_pool::LiteralConstant;
use cafebabe::descriptors::{FieldDescriptor, FieldType};

use super::ClassName;
use cafebabe::descriptors::FieldDescriptor;

#[derive(Clone, Copy, Debug)]
pub struct JavaField<'a> {
Expand Down Expand Up @@ -96,29 +92,3 @@ impl<'a> JavaField<'a> {
&self.java.descriptor
}
}

pub fn emit_field_descriptor(descriptor: &FieldDescriptor) -> String {
let mut res = String::new();
for _ in 0..descriptor.dimensions {
res.push('[');
}
if let FieldType::Object(class_name) = &descriptor.field_type {
res.push('L');
write!(&mut res, "{}", ClassName::from(class_name)).unwrap();
res.push(';');
} else {
let ch = match descriptor.field_type {
FieldType::Boolean => 'Z',
FieldType::Byte => 'B',
FieldType::Char => 'C',
FieldType::Short => 'S',
FieldType::Integer => 'I',
FieldType::Long => 'J',
FieldType::Float => 'F',
FieldType::Double => 'D',
_ => unreachable!(),
};
res.push(ch)
}
res
}
Loading