Skip to content

Commit

Permalink
feat: override union and insert config
Browse files Browse the repository at this point in the history
Signed-off-by: peefy <[email protected]>
  • Loading branch information
Peefy committed Jul 30, 2024
1 parent 8547843 commit f390704
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 21 deletions.
153 changes: 135 additions & 18 deletions kclvm/query/src/override.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,85 @@ fn apply_import_paths_on_module(m: &mut ast::Module, import_paths: &[String]) ->
Ok(())
}

macro_rules! override_top_level_stmt {
($self:expr, $stmt: expr) => {
let item = $stmt.value.clone();
let mut value = $self.clone_override_value();
// Use position information that needs to override the expression.
value.set_pos(item.pos());
match &$self.operation {
ast::ConfigEntryOperation::Union => {
if let ast::Expr::Config(insert_config_expr) = &value.node {
match &mut $stmt.value.node {
ast::Expr::Schema(schema_expr) => {
if let ast::Expr::Config(config_expr) = &mut schema_expr.config.node {
for item in &insert_config_expr.items {
let parts = get_key_parts(&item.node.key);
// Deal double star and config if expr
if parts.is_empty() {
config_expr.items.push(item.clone());
$self.has_override = true;
} else {
if replace_config_with_path_parts(
config_expr,
&parts,
&$self.action,
&item.node.operation,
&Some(item.node.value.clone()),
) {
$self.has_override = true;
}
}
}
}
}
ast::Expr::Config(config_expr) => {
for item in &insert_config_expr.items {
let parts = get_key_parts(&item.node.key);
// Deal double star and config if expr
if parts.is_empty() {
config_expr.items.push(item.clone());
$self.has_override = true;
} else {
if replace_config_with_path_parts(
config_expr,
&parts,
&$self.action,
&item.node.operation,
&Some(item.node.value.clone()),
) {
$self.has_override = true;
}
}
}
}
_ => {}
}
} else {
// Override the node value.
$stmt.value = value;
$self.has_override = true;
}
}
ast::ConfigEntryOperation::Insert => {
if let ast::Expr::List(insert_list_expr) = &value.node {
if let ast::Expr::List(list_expr) = &mut $stmt.value.node {
for value in &insert_list_expr.elts {
list_expr.elts.push(value.clone());
}
$self.has_override = true;
}
}
}
ast::ConfigEntryOperation::Override => {
// Override the node value.
$stmt.value = value;
$self.has_override = true;
}
}
};
}

/// OverrideTransformer is used to walk AST and transform it with the override values.
struct OverrideTransformer {
pub target_id: String,
Expand Down Expand Up @@ -326,18 +405,18 @@ impl<'ctx> MutSelfMutWalker<'ctx> for OverrideTransformer {
let target = assign_stmt.targets.get(0).unwrap().node.clone();
let target = get_target_path(&target);
if target == self.target_id {
let item = assign_stmt.value.clone();

let mut value = self.clone_override_value();
// Use position information that needs to override the expression.
value.set_pos(item.pos());
// Override the node value.
assign_stmt.value = value;
self.has_override = true;
override_top_level_stmt!(self, assign_stmt);
}
}
}
if let ast::Stmt::Unification(unification_stmt) = &mut stmt.node {
} else if let ast::Stmt::AugAssign(aug_assign_stmt) = &mut stmt.node {
if self.field_paths.len() == 0 {
let target = aug_assign_stmt.target.node.clone();
let target = get_target_path(&target);
if target == self.target_id {
override_top_level_stmt!(self, aug_assign_stmt);
}
}
} else if let ast::Stmt::Unification(unification_stmt) = &mut stmt.node {
let target = match unification_stmt.target.node.names.get(0) {
Some(name) => name,
None => bug!(
Expand All @@ -347,17 +426,55 @@ impl<'ctx> MutSelfMutWalker<'ctx> for OverrideTransformer {
};
if target.node == self.target_id {
let item = unification_stmt.value.clone();

let mut value = self.clone_override_value();
// Use position information that needs to override the expression.
value.set_pos(item.pos());

// Unification is only support to override the schema expression.
if let ast::Expr::Schema(schema_expr) = value.node {
if self.field_paths.len() == 0 {
self.has_override = true;
unification_stmt.value =
Box::new(ast::Node::dummy_node(schema_expr));
match &self.operation {
ast::ConfigEntryOperation::Union => {
if let ast::Expr::Config(insert_config_expr) = &value.node {
if let ast::Expr::Config(config_expr) =
&mut unification_stmt.value.node.config.node
{
for item in &insert_config_expr.items {
let parts = get_key_parts(&item.node.key);
// Deal double star and config if expr
if parts.is_empty() {
config_expr.items.push(item.clone());
self.has_override = true;
} else {
if replace_config_with_path_parts(
config_expr,
&parts,
&self.action,
&item.node.operation,
&Some(item.node.value.clone()),
) {
self.has_override = true;
}
}
}
}
} else {
// Unification is only support to override the schema expression.
if let ast::Expr::Schema(schema_expr) = value.node {
if self.field_paths.len() == 0 {
unification_stmt.value =
Box::new(ast::Node::dummy_node(schema_expr));
self.has_override = true;
}
}
}
}
ast::ConfigEntryOperation::Insert
| ast::ConfigEntryOperation::Override => {
// Unification is only support to override the schema expression.
if let ast::Expr::Schema(schema_expr) = value.node {
if self.field_paths.len() == 0 {
unification_stmt.value =
Box::new(ast::Node::dummy_node(schema_expr));
self.has_override = true;
}
}
}
}
}
Expand Down
13 changes: 10 additions & 3 deletions kclvm/query/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,18 @@ fn test_override_file_config() {
"appConfigurationUnification.overQuota=False".to_string(),
"appConfigurationUnification.resource.cpu-".to_string(),
"appConfigurationUnification.svc=s.Service {}".to_string(),
"config.x:1".to_string(),
"appConfigurationUnification:{name=\"name\"}".to_string(),
"config.x:{a:1}".to_string(),
"config.x:{b:2}".to_string(),
"config.x:{b:3}".to_string(),
"config.x:{c.d:4}".to_string(),
"config.y=1".to_string(),
"config.z+=[1,2,3]".to_string(),
"config.z+=[4,5,6]".to_string(),
"var1:1".to_string(),
"var2=1".to_string(),
"var3+=[1,2,3]".to_string(),
"var3+=[4,5,6]".to_string(),
"var4:AppConfiguration {image:'image'}".to_string(),
];
let import_paths = vec!["service as s".to_string()];
Expand Down Expand Up @@ -187,11 +193,12 @@ appConfigurationUnification: AppConfiguration {
mainContainer: Main {name: "override_name"}
overQuota: False
svc = s.Service {}
name = "name"
}
config = {x: 1, y = 1, z += [1, 2, 3]}
config = {x: {a: 1, b: 3, c: {d: 4}}, y = 1, z += [1, 2, 3, 4, 5, 6]}
var1 = 1
var2 = 1
var3 += [1, 2, 3]
var3 += [1, 2, 3, 4, 5, 6]
var4: AppConfiguration {image: 'image'}
"#
);
Expand Down

0 comments on commit f390704

Please sign in to comment.