feat(config): refactor id field and introduce deduplication on legacy loader
This commit is contained in:
parent
d1776c9fea
commit
459e414a09
|
@ -22,8 +22,8 @@ use regex::Regex;
|
||||||
use std::{collections::HashMap, path::Path};
|
use std::{collections::HashMap, path::Path};
|
||||||
|
|
||||||
use self::config::LegacyConfig;
|
use self::config::LegacyConfig;
|
||||||
use crate::config::store::DefaultConfigStore;
|
|
||||||
use crate::matches::group::loader::yaml::parse::{YAMLMatch, YAMLVariable};
|
use crate::matches::group::loader::yaml::parse::{YAMLMatch, YAMLVariable};
|
||||||
|
use crate::{config::store::DefaultConfigStore, counter::StructId};
|
||||||
use crate::{
|
use crate::{
|
||||||
config::Config,
|
config::Config,
|
||||||
config::{AppProperties, ConfigStore},
|
config::{AppProperties, ConfigStore},
|
||||||
|
@ -43,13 +43,28 @@ pub fn load(
|
||||||
) -> Result<(Box<dyn ConfigStore>, Box<dyn MatchStore>)> {
|
) -> Result<(Box<dyn ConfigStore>, Box<dyn MatchStore>)> {
|
||||||
let config_set = config::LegacyConfigSet::load(base_dir, package_dir)?;
|
let config_set = config::LegacyConfigSet::load(base_dir, package_dir)?;
|
||||||
|
|
||||||
let (default_config, default_match_group) = split_config(config_set.default);
|
let mut match_deduplicate_map = HashMap::new();
|
||||||
|
let mut var_deduplicate_map = HashMap::new();
|
||||||
|
|
||||||
|
let (default_config, mut default_match_group) = split_config(config_set.default);
|
||||||
|
deduplicate_ids(
|
||||||
|
&mut default_match_group,
|
||||||
|
&mut match_deduplicate_map,
|
||||||
|
&mut var_deduplicate_map,
|
||||||
|
);
|
||||||
|
|
||||||
let mut match_groups = HashMap::new();
|
let mut match_groups = HashMap::new();
|
||||||
match_groups.insert("default".to_string(), default_match_group);
|
match_groups.insert("default".to_string(), default_match_group);
|
||||||
|
|
||||||
let mut custom_configs: Vec<Box<dyn Config>> = Vec::new();
|
let mut custom_configs: Vec<Box<dyn Config>> = Vec::new();
|
||||||
for custom in config_set.specific {
|
for custom in config_set.specific {
|
||||||
let (custom_config, custom_match_group) = split_config(custom);
|
let (custom_config, mut custom_match_group) = split_config(custom);
|
||||||
|
deduplicate_ids(
|
||||||
|
&mut custom_match_group,
|
||||||
|
&mut match_deduplicate_map,
|
||||||
|
&mut var_deduplicate_map,
|
||||||
|
);
|
||||||
|
|
||||||
match_groups.insert(custom_config.name.clone(), custom_match_group);
|
match_groups.insert(custom_config.name.clone(), custom_match_group);
|
||||||
custom_configs.push(Box::new(custom_config));
|
custom_configs.push(Box::new(custom_config));
|
||||||
}
|
}
|
||||||
|
@ -90,6 +105,34 @@ fn split_config(config: LegacyConfig) -> (LegacyInteropConfig, LegacyMatchGroup)
|
||||||
(config, match_group)
|
(config, match_group)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Due to the way the legacy configs are loaded (matches are copied multiple times in the various configs)
|
||||||
|
/// we need to deduplicate the ids of those matches (and global vars).
|
||||||
|
fn deduplicate_ids(
|
||||||
|
match_group: &mut LegacyMatchGroup,
|
||||||
|
match_map: &mut HashMap<Match, StructId>,
|
||||||
|
var_map: &mut HashMap<Variable, StructId>,
|
||||||
|
) {
|
||||||
|
for m in match_group.matches.iter_mut() {
|
||||||
|
let mut m_without_id = m.clone();
|
||||||
|
m_without_id.id = 0;
|
||||||
|
if let Some(id) = match_map.get(&m_without_id) {
|
||||||
|
m.id = *id;
|
||||||
|
} else {
|
||||||
|
match_map.insert(m_without_id, m.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for v in match_group.global_vars.iter_mut() {
|
||||||
|
let mut v_without_id = v.clone();
|
||||||
|
v_without_id.id = 0;
|
||||||
|
if let Some(id) = var_map.get(&v_without_id) {
|
||||||
|
v.id = *id;
|
||||||
|
} else {
|
||||||
|
var_map.insert(v_without_id, v.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct LegacyInteropConfig {
|
struct LegacyInteropConfig {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
match_paths: Vec<String>,
|
match_paths: Vec<String>,
|
||||||
|
@ -352,6 +395,75 @@ mod tests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn load_legacy_deduplicates_ids_correctly() {
|
||||||
|
use_test_directory(|base, user, packages| {
|
||||||
|
std::fs::write(
|
||||||
|
base.join("default.yml"),
|
||||||
|
r#"
|
||||||
|
backend: Clipboard
|
||||||
|
|
||||||
|
global_vars:
|
||||||
|
- name: var1
|
||||||
|
type: test
|
||||||
|
|
||||||
|
matches:
|
||||||
|
- trigger: "hello"
|
||||||
|
replace: "world"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
std::fs::write(
|
||||||
|
user.join("specific.yml"),
|
||||||
|
r#"
|
||||||
|
name: specific
|
||||||
|
filter_title: "Google"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let (config_store, match_store) = load(base, packages).unwrap();
|
||||||
|
|
||||||
|
let default_config = config_store.default();
|
||||||
|
let active_config = config_store.active(&AppProperties {
|
||||||
|
title: Some("Google"),
|
||||||
|
class: None,
|
||||||
|
exec: None,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
match_store
|
||||||
|
.query(default_config.match_paths())
|
||||||
|
.matches
|
||||||
|
.first()
|
||||||
|
.unwrap()
|
||||||
|
.id,
|
||||||
|
match_store
|
||||||
|
.query(active_config.match_paths())
|
||||||
|
.matches
|
||||||
|
.first()
|
||||||
|
.unwrap()
|
||||||
|
.id,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
match_store
|
||||||
|
.query(default_config.match_paths())
|
||||||
|
.global_vars
|
||||||
|
.first()
|
||||||
|
.unwrap()
|
||||||
|
.id,
|
||||||
|
match_store
|
||||||
|
.query(active_config.match_paths())
|
||||||
|
.global_vars
|
||||||
|
.first()
|
||||||
|
.unwrap()
|
||||||
|
.id,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn load_legacy_with_packages() {
|
fn load_legacy_with_packages() {
|
||||||
use_test_directory(|base, _, packages| {
|
use_test_directory(|base, _, packages| {
|
||||||
|
|
|
@ -17,10 +17,10 @@
|
||||||
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::matches::{
|
use crate::{counter::next_id, matches::{
|
||||||
group::{path::resolve_imports, MatchGroup},
|
group::{path::resolve_imports, MatchGroup},
|
||||||
Match, Variable,
|
Match, Variable,
|
||||||
};
|
}};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use parse::YAMLMatchGroup;
|
use parse::YAMLMatchGroup;
|
||||||
|
@ -138,7 +138,7 @@ impl TryFrom<YAMLMatch> for Match {
|
||||||
cause,
|
cause,
|
||||||
effect,
|
effect,
|
||||||
label: None,
|
label: None,
|
||||||
..Default::default()
|
id: next_id(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ impl TryFrom<YAMLVariable> for Variable {
|
||||||
name: yaml_var.name,
|
name: yaml_var.name,
|
||||||
var_type: yaml_var.var_type,
|
var_type: yaml_var.var_type,
|
||||||
params: yaml_var.params,
|
params: yaml_var.params,
|
||||||
..Default::default()
|
id: next_id(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,14 @@ mod tests {
|
||||||
|
|
||||||
fn create_match(yaml: &str) -> Result<Match> {
|
fn create_match(yaml: &str) -> Result<Match> {
|
||||||
let yaml_match: YAMLMatch = serde_yaml::from_str(yaml)?;
|
let yaml_match: YAMLMatch = serde_yaml::from_str(yaml)?;
|
||||||
let m: Match = yaml_match.try_into()?;
|
let mut m: Match = yaml_match.try_into()?;
|
||||||
|
|
||||||
|
// Reset the IDs to correctly compare them
|
||||||
|
m.id = 0;
|
||||||
|
if let MatchEffect::Text(e) = &mut m.effect {
|
||||||
|
e.vars.iter_mut().for_each(|v| v.id = 0);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(m)
|
Ok(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,7 +436,10 @@ mod tests {
|
||||||
std::fs::write(&sub_file, "").unwrap();
|
std::fs::write(&sub_file, "").unwrap();
|
||||||
|
|
||||||
let importer = YAMLImporter::new();
|
let importer = YAMLImporter::new();
|
||||||
let group = importer.load_group(&base_file).unwrap();
|
let mut group = importer.load_group(&base_file).unwrap();
|
||||||
|
// Reset the ids to compare them correctly
|
||||||
|
group.matches.iter_mut().for_each(|mut m| m.id = 0);
|
||||||
|
group.global_vars.iter_mut().for_each(|mut v| v.id = 0);
|
||||||
|
|
||||||
let vars = vec![Variable {
|
let vars = vec![Variable {
|
||||||
name: "var1".to_string(),
|
name: "var1".to_string(),
|
||||||
|
|
|
@ -19,21 +19,20 @@
|
||||||
|
|
||||||
use serde_yaml::Mapping;
|
use serde_yaml::Mapping;
|
||||||
|
|
||||||
use crate::counter::{next_id, StructId};
|
use crate::counter::{StructId};
|
||||||
|
|
||||||
pub(crate) mod group;
|
pub(crate) mod group;
|
||||||
pub mod store;
|
pub mod store;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct Match {
|
pub struct Match {
|
||||||
cause: MatchCause,
|
pub id: StructId,
|
||||||
effect: MatchEffect,
|
|
||||||
|
pub cause: MatchCause,
|
||||||
|
pub effect: MatchEffect,
|
||||||
|
|
||||||
// Metadata
|
// Metadata
|
||||||
label: Option<String>,
|
pub label: Option<String>,
|
||||||
|
|
||||||
// Internals
|
|
||||||
_id: StructId,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Match {
|
impl Default for Match {
|
||||||
|
@ -42,20 +41,14 @@ impl Default for Match {
|
||||||
cause: MatchCause::None,
|
cause: MatchCause::None,
|
||||||
effect: MatchEffect::None,
|
effect: MatchEffect::None,
|
||||||
label: None,
|
label: None,
|
||||||
_id: next_id(),
|
id: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Match {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.cause == other.cause && self.effect == other.effect && self.label == other.label
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Causes
|
// Causes
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
|
||||||
pub enum MatchCause {
|
pub enum MatchCause {
|
||||||
None,
|
None,
|
||||||
Trigger(TriggerCause),
|
Trigger(TriggerCause),
|
||||||
|
@ -63,7 +56,7 @@ pub enum MatchCause {
|
||||||
// TODO: shortcut
|
// TODO: shortcut
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct TriggerCause {
|
pub struct TriggerCause {
|
||||||
pub triggers: Vec<String>,
|
pub triggers: Vec<String>,
|
||||||
|
|
||||||
|
@ -86,7 +79,7 @@ impl Default for TriggerCause {
|
||||||
|
|
||||||
// Effects
|
// Effects
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum MatchEffect {
|
pub enum MatchEffect {
|
||||||
None,
|
None,
|
||||||
Text(TextEffect),
|
Text(TextEffect),
|
||||||
|
@ -94,7 +87,7 @@ pub enum MatchEffect {
|
||||||
// TODO: rich text
|
// TODO: rich text
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct TextEffect {
|
pub struct TextEffect {
|
||||||
pub replace: String,
|
pub replace: String,
|
||||||
pub vars: Vec<Variable>,
|
pub vars: Vec<Variable>,
|
||||||
|
@ -109,29 +102,21 @@ impl Default for TextEffect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct Variable {
|
pub struct Variable {
|
||||||
|
pub id: StructId,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub var_type: String,
|
pub var_type: String,
|
||||||
pub params: Mapping,
|
pub params: Mapping,
|
||||||
|
|
||||||
// Internals
|
|
||||||
_id: StructId,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Variable {
|
impl Default for Variable {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
id: 0,
|
||||||
name: String::new(),
|
name: String::new(),
|
||||||
var_type: String::new(),
|
var_type: String::new(),
|
||||||
params: Mapping::new(),
|
params: Mapping::new(),
|
||||||
_id: next_id(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Variable {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.name == other.name && self.var_type == other.var_type && self.params == other.params
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -42,9 +42,7 @@ impl DefaultMatchStore {
|
||||||
// top-level ones.
|
// top-level ones.
|
||||||
load_match_groups_recursively(&mut groups, paths);
|
load_match_groups_recursively(&mut groups, paths);
|
||||||
|
|
||||||
Self {
|
Self { groups }
|
||||||
groups,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,16 +115,16 @@ fn query_matches_for_paths<'a>(
|
||||||
);
|
);
|
||||||
|
|
||||||
for m in group.matches.iter() {
|
for m in group.matches.iter() {
|
||||||
if !visited_matches.contains(&m._id) {
|
if !visited_matches.contains(&m.id) {
|
||||||
matches.push(m);
|
matches.push(m);
|
||||||
visited_matches.insert(m._id);
|
visited_matches.insert(m.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for var in group.global_vars.iter() {
|
for var in group.global_vars.iter() {
|
||||||
if !visited_global_vars.contains(&var._id) {
|
if !visited_global_vars.contains(&var.id) {
|
||||||
global_vars.push(var);
|
global_vars.push(var);
|
||||||
visited_global_vars.insert(var._id);
|
visited_global_vars.insert(var.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,16 +230,27 @@ mod tests {
|
||||||
.get(&base_file.to_string_lossy().to_string())
|
.get(&base_file.to_string_lossy().to_string())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.matches;
|
.matches;
|
||||||
assert_eq!(base_group, &create_matches(&[("hello", "world")]));
|
let base_group: Vec<Match> = base_group.iter().map(|m| {
|
||||||
|
let mut copy = m.clone();
|
||||||
|
copy.id = 0;
|
||||||
|
copy
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
assert_eq!(base_group, create_matches(&[("hello", "world")]));
|
||||||
|
|
||||||
let another_group = &match_store
|
let another_group = &match_store
|
||||||
.groups
|
.groups
|
||||||
.get(&another_file.to_string_lossy().to_string())
|
.get(&another_file.to_string_lossy().to_string())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.matches;
|
.matches;
|
||||||
|
let another_group: Vec<Match> = another_group.iter().map(|m| {
|
||||||
|
let mut copy = m.clone();
|
||||||
|
copy.id = 0;
|
||||||
|
copy
|
||||||
|
}).collect();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
another_group,
|
another_group,
|
||||||
&create_matches(&[("hello", "world2"), ("foo", "bar")])
|
create_matches(&[("hello", "world2"), ("foo", "bar")])
|
||||||
);
|
);
|
||||||
|
|
||||||
let sub_group = &match_store
|
let sub_group = &match_store
|
||||||
|
@ -249,7 +258,12 @@ mod tests {
|
||||||
.get(&sub_file.to_string_lossy().to_string())
|
.get(&sub_file.to_string_lossy().to_string())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.matches;
|
.matches;
|
||||||
assert_eq!(sub_group, &create_matches(&[("hello", "world3")]));
|
let sub_group: Vec<Match> = sub_group.iter().map(|m| {
|
||||||
|
let mut copy = m.clone();
|
||||||
|
copy.id = 0;
|
||||||
|
copy
|
||||||
|
}).collect();
|
||||||
|
assert_eq!(sub_group, create_matches(&[("hello", "world3")]));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,6 +387,7 @@ mod tests {
|
||||||
.matches
|
.matches
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
|
.map(|mut m| { m.id = 0; m })
|
||||||
.collect::<Vec<Match>>(),
|
.collect::<Vec<Match>>(),
|
||||||
create_matches(&[
|
create_matches(&[
|
||||||
("hello", "world3"),
|
("hello", "world3"),
|
||||||
|
@ -387,6 +402,7 @@ mod tests {
|
||||||
.global_vars
|
.global_vars
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
|
.map(|mut v| { v.id = 0; v })
|
||||||
.collect::<Vec<Variable>>(),
|
.collect::<Vec<Variable>>(),
|
||||||
create_vars(&["var2", "var1"])
|
create_vars(&["var2", "var1"])
|
||||||
);
|
);
|
||||||
|
@ -460,6 +476,7 @@ mod tests {
|
||||||
.matches
|
.matches
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
|
.map(|mut m| { m.id = 0; m })
|
||||||
.collect::<Vec<Match>>(),
|
.collect::<Vec<Match>>(),
|
||||||
create_matches(&[
|
create_matches(&[
|
||||||
("hello", "world3"),
|
("hello", "world3"),
|
||||||
|
@ -474,6 +491,7 @@ mod tests {
|
||||||
.global_vars
|
.global_vars
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
|
.map(|mut v| { v.id = 0; v})
|
||||||
.collect::<Vec<Variable>>(),
|
.collect::<Vec<Variable>>(),
|
||||||
create_vars(&["var2", "var1"])
|
create_vars(&["var2", "var1"])
|
||||||
);
|
);
|
||||||
|
@ -532,7 +550,10 @@ mod tests {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let match_store = DefaultMatchStore::new(&[base_file.to_string_lossy().to_string(), sub_file.to_string_lossy().to_string()]);
|
let match_store = DefaultMatchStore::new(&[
|
||||||
|
base_file.to_string_lossy().to_string(),
|
||||||
|
sub_file.to_string_lossy().to_string(),
|
||||||
|
]);
|
||||||
|
|
||||||
let match_set = match_store.query(&[
|
let match_set = match_store.query(&[
|
||||||
base_file.to_string_lossy().to_string(),
|
base_file.to_string_lossy().to_string(),
|
||||||
|
@ -544,6 +565,7 @@ mod tests {
|
||||||
.matches
|
.matches
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
|
.map(|mut m| { m.id = 0; m })
|
||||||
.collect::<Vec<Match>>(),
|
.collect::<Vec<Match>>(),
|
||||||
create_matches(&[
|
create_matches(&[
|
||||||
("hello", "world2"),
|
("hello", "world2"),
|
||||||
|
@ -558,6 +580,7 @@ mod tests {
|
||||||
.global_vars
|
.global_vars
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
|
.map(|mut v| { v.id = 0; v })
|
||||||
.collect::<Vec<Variable>>(),
|
.collect::<Vec<Variable>>(),
|
||||||
create_vars(&["var1", "var2"])
|
create_vars(&["var1", "var2"])
|
||||||
);
|
);
|
||||||
|
@ -631,6 +654,7 @@ mod tests {
|
||||||
.matches
|
.matches
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
|
.map(|mut m| { m.id = 0; m })
|
||||||
.collect::<Vec<Match>>(),
|
.collect::<Vec<Match>>(),
|
||||||
create_matches(&[
|
create_matches(&[
|
||||||
("hello", "world3"), // This appears only once, though it appears 2 times
|
("hello", "world3"), // This appears only once, though it appears 2 times
|
||||||
|
@ -645,6 +669,7 @@ mod tests {
|
||||||
.global_vars
|
.global_vars
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
|
.map(|mut v| { v.id = 0; v })
|
||||||
.collect::<Vec<Variable>>(),
|
.collect::<Vec<Variable>>(),
|
||||||
create_vars(&["var2", "var1"])
|
create_vars(&["var2", "var1"])
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user