Add support for Rust 2018 edition projects.
Summary: After enabling 2018 edition on my cargo project, the use statements generated in the interface module no longer resolve. Prefixing module paths with `crate::` brings things back into alignment. Unsure if this is how you'd like to approach the issue, but I'm happy to revise the patch based on your feedback. Test Plan: STEPS TO REPRODUCE 1. create a new cargo project based on the template 2. update your toolchain to >= 1.31 3. add `edition = "2018"` to the package section of your Cargo.toml 4. run `cargo build` OBSERVED RESULT Build fails since generated code tries to import crate-local modules as if they are top level crates. EXPECTED RESULT Build completes successfully. Reviewers: vandenoever Differential Revision: https://phabricator.kde.org/D17447master
parent
4acf7e3176
commit
325ffc2a2c
|
@ -16,3 +16,4 @@ serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde-xml-rs = "0.2.1"
|
serde-xml-rs = "0.2.1"
|
||||||
|
toml = "0.4.10"
|
|
@ -1,5 +1,6 @@
|
||||||
use configuration_private::*;
|
use configuration_private::*;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
use toml;
|
||||||
use std::collections::{BTreeMap, BTreeSet};
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
@ -57,11 +58,28 @@ mod json {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum RustEdition {
|
||||||
|
Rust2015,
|
||||||
|
Rust2018,
|
||||||
|
Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::std::convert::From<Option<&str>> for RustEdition {
|
||||||
|
fn from(str: Option<&str>) -> RustEdition {
|
||||||
|
match str {
|
||||||
|
None | Some("2015") => RustEdition::Rust2015,
|
||||||
|
Some("2018") => RustEdition::Rust2018,
|
||||||
|
_ => RustEdition::Unknown,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub config_file: PathBuf,
|
pub config_file: PathBuf,
|
||||||
pub cpp_file: PathBuf,
|
pub cpp_file: PathBuf,
|
||||||
pub objects: BTreeMap<String, Rc<Object>>,
|
pub objects: BTreeMap<String, Rc<Object>>,
|
||||||
pub rust: Rust,
|
pub rust: Rust,
|
||||||
|
pub rust_edition: RustEdition,
|
||||||
pub overwrite_implementation: bool,
|
pub overwrite_implementation: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,11 +465,21 @@ fn post_process(config_file: &Path, json: json::Config) -> Result<Config, Box<Er
|
||||||
for object in &json.objects {
|
for object in &json.objects {
|
||||||
post_process_object(object, &mut objects, &json.objects)?;
|
post_process_object(object, &mut objects, &json.objects)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let rust_edition: RustEdition = {
|
||||||
|
let mut buf = config_file.to_path_buf();
|
||||||
|
buf.pop();
|
||||||
|
buf.push("Cargo.toml");
|
||||||
|
let manifest: toml::Value = fs::read_to_string(&buf)?.parse()?;
|
||||||
|
manifest["package"].get("edition").and_then(|val| val.as_str()).into()
|
||||||
|
};
|
||||||
|
|
||||||
Ok(Config {
|
Ok(Config {
|
||||||
config_file: config_file.into(),
|
config_file: config_file.into(),
|
||||||
cpp_file: json.cpp_file,
|
cpp_file: json.cpp_file,
|
||||||
objects,
|
objects,
|
||||||
rust: json.rust,
|
rust: json.rust,
|
||||||
|
rust_edition,
|
||||||
overwrite_implementation: json.overwrite_implementation,
|
overwrite_implementation: json.overwrite_implementation,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ extern crate regex;
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate serde_xml_rs;
|
extern crate serde_xml_rs;
|
||||||
|
extern crate toml;
|
||||||
|
|
||||||
pub mod build;
|
pub mod build;
|
||||||
pub mod configuration;
|
pub mod configuration;
|
||||||
|
|
19
src/rust.rs
19
src/rust.rs
|
@ -1264,7 +1264,8 @@ use std::sync::Arc;
|
||||||
use std::sync::atomic::{{AtomicPtr, Ordering}};
|
use std::sync::atomic::{{AtomicPtr, Ordering}};
|
||||||
use std::ptr::null;
|
use std::ptr::null;
|
||||||
|
|
||||||
use {}::*;",
|
use {}{}::*;",
|
||||||
|
get_module_prefix(conf),
|
||||||
conf.rust.implementation_module
|
conf.rust.implementation_module
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -1518,8 +1519,9 @@ pub fn write_implementation(conf: &Config) -> Result<()> {
|
||||||
"#![allow(unused_imports)]
|
"#![allow(unused_imports)]
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use {}::*;
|
use {}{}::*;
|
||||||
",
|
",
|
||||||
|
get_module_prefix(conf),
|
||||||
conf.rust.interface_module
|
conf.rust.interface_module
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -1528,3 +1530,16 @@ use {}::*;
|
||||||
}
|
}
|
||||||
write_if_different(file, &r)
|
write_if_different(file, &r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Inspects the rust edition of the target crate to decide how the module
|
||||||
|
/// imports should be written.
|
||||||
|
///
|
||||||
|
/// As of Rust 2018, modules inside the crate should be prefixed with `crate::`.
|
||||||
|
/// Prior to the 2018 edition, crate-local modules could be imported without
|
||||||
|
/// this prefix.
|
||||||
|
fn get_module_prefix(conf: &Config) -> &'static str {
|
||||||
|
match conf.rust_edition {
|
||||||
|
RustEdition::Rust2018 => "crate::",
|
||||||
|
_ => ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue