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/D17447
master
Owen Nelson 2018-12-09 23:30:51 +01:00 committed by Jos van den Oever
parent 4acf7e3176
commit 325ffc2a2c
4 changed files with 47 additions and 2 deletions

View File

@ -16,3 +16,4 @@ serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
serde-xml-rs = "0.2.1"
toml = "0.4.10"

View File

@ -1,5 +1,6 @@
use configuration_private::*;
use serde_json;
use toml;
use std::collections::{BTreeMap, BTreeSet};
use std::error::Error;
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 config_file: PathBuf,
pub cpp_file: PathBuf,
pub objects: BTreeMap<String, Rc<Object>>,
pub rust: Rust,
pub rust_edition: RustEdition,
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 {
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 {
config_file: config_file.into(),
cpp_file: json.cpp_file,
objects,
rust: json.rust,
rust_edition,
overwrite_implementation: json.overwrite_implementation,
})
}

View File

@ -3,6 +3,7 @@ extern crate regex;
extern crate serde_derive;
extern crate serde_json;
extern crate serde_xml_rs;
extern crate toml;
pub mod build;
pub mod configuration;

View File

@ -1264,7 +1264,8 @@ use std::sync::Arc;
use std::sync::atomic::{{AtomicPtr, Ordering}};
use std::ptr::null;
use {}::*;",
use {}{}::*;",
get_module_prefix(conf),
conf.rust.implementation_module
)?;
@ -1518,8 +1519,9 @@ pub fn write_implementation(conf: &Config) -> Result<()> {
"#![allow(unused_imports)]
#![allow(unused_variables)]
#![allow(dead_code)]
use {}::*;
use {}{}::*;
",
get_module_prefix(conf),
conf.rust.interface_module
)?;
@ -1528,3 +1530,16 @@ use {}::*;
}
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::",
_ => ""
}
}