diff --git a/mlf-cli/src/generate/mlf.rs b/mlf-cli/src/generate/mlf.rs index f3499b8..786dfcc 100644 --- a/mlf-cli/src/generate/mlf.rs +++ b/mlf-cli/src/generate/mlf.rs @@ -244,9 +244,9 @@ pub fn generate_mlf_from_json(json: &Value) -> Result Result { - let mlf = generate_record(name, def, last_segment, &ctx)?; + let mlf = generate_record(name, def, &ctx)?; output.push_str(&mlf); output.push('\n'); } "query" => { - let mlf = generate_query(name, def, last_segment, &ctx)?; + let mlf = generate_query(name, def, &ctx)?; output.push_str(&mlf); output.push('\n'); } "procedure" => { - let mlf = generate_procedure(name, def, last_segment, &ctx)?; + let mlf = generate_procedure(name, def, &ctx)?; output.push_str(&mlf); output.push('\n'); } "subscription" => { - let mlf = generate_subscription(name, def, last_segment, &ctx)?; + let mlf = generate_subscription(name, def, &ctx)?; output.push_str(&mlf); output.push('\n'); } @@ -286,7 +286,7 @@ pub fn generate_mlf_from_json(json: &Value) -> Result { // All other types (object, string, array, union, etc.) are treated as def type - let mlf = generate_def_type(name, def, last_segment, &ctx)?; + let mlf = generate_def_type(name, def, &ctx)?; output.push_str(&mlf); output.push('\n'); } @@ -301,6 +301,22 @@ pub fn generate_mlf_from_json(json: &Value) -> Result String { } } -fn generate_record(name: &str, def: &Value, last_segment: &str, ctx: &ConversionContext) -> Result { +fn generate_record(name: &str, def: &Value, ctx: &ConversionContext) -> Result { let mut output = String::new(); // Add doc comment if present @@ -351,7 +367,7 @@ fn generate_record(name: &str, def: &Value, last_segment: &str, ctx: &Conversion // Use last segment of NSID for "main" definitions let record_name = if name == "main" { - escape_name(last_segment) + escape_name(&ctx.local_main_name) } else { escape_name(name) }; @@ -399,7 +415,7 @@ fn generate_record(name: &str, def: &Value, last_segment: &str, ctx: &Conversion Ok(output) } -fn generate_query(name: &str, def: &Value, last_segment: &str, ctx: &ConversionContext) -> Result { +fn generate_query(name: &str, def: &Value, ctx: &ConversionContext) -> Result { let mut output = String::new(); // Add doc comment @@ -417,7 +433,7 @@ fn generate_query(name: &str, def: &Value, last_segment: &str, ctx: &ConversionC } let query_name = if name == "main" { - escape_name(last_segment) + escape_name(&ctx.local_main_name) } else { escape_name(name) }; @@ -493,7 +509,7 @@ fn generate_query(name: &str, def: &Value, last_segment: &str, ctx: &ConversionC Ok(output) } -fn generate_procedure(name: &str, def: &Value, last_segment: &str, ctx: &ConversionContext) -> Result { +fn generate_procedure(name: &str, def: &Value, ctx: &ConversionContext) -> Result { let mut output = String::new(); // Add doc comment @@ -511,7 +527,7 @@ fn generate_procedure(name: &str, def: &Value, last_segment: &str, ctx: &Convers } let procedure_name = if name == "main" { - escape_name(last_segment) + escape_name(&ctx.local_main_name) } else { escape_name(name) }; @@ -592,7 +608,7 @@ fn generate_procedure(name: &str, def: &Value, last_segment: &str, ctx: &Convers Ok(output) } -fn generate_subscription(name: &str, def: &Value, last_segment: &str, ctx: &ConversionContext) -> Result { +fn generate_subscription(name: &str, def: &Value, ctx: &ConversionContext) -> Result { let mut output = String::new(); // Add doc comment @@ -610,7 +626,7 @@ fn generate_subscription(name: &str, def: &Value, last_segment: &str, ctx: &Conv } let subscription_name = if name == "main" { - escape_name(last_segment) + escape_name(&ctx.local_main_name) } else { escape_name(name) }; @@ -681,7 +697,7 @@ fn generate_token(name: &str, def: &Value) -> Result { Ok(output) } -fn generate_def_type(name: &str, def: &Value, last_segment: &str, ctx: &ConversionContext) -> Result { +fn generate_def_type(name: &str, def: &Value, ctx: &ConversionContext) -> Result { let mut output = String::new(); // Add doc comment if present @@ -701,7 +717,7 @@ fn generate_def_type(name: &str, def: &Value, last_segment: &str, ctx: &Conversi // Use last segment of NSID for "main" definitions // Keywords are now allowed by the parser, so just escape with backticks let def_name = if name == "main" { - escape_name(last_segment) + escape_name(&ctx.local_main_name) } else { escape_name(name) }; @@ -1098,19 +1114,39 @@ fn render_ref(type_def: &Value, ctx: &ConversionContext) -> Result String { if let Some(stripped) = ref_str.strip_prefix('#') { - stripped.to_string() - } else if let Some((namespace, def_name)) = ref_str.split_once('#') { + return rewrite_local_main(stripped, ctx); + } + if let Some((namespace, def_name)) = ref_str.split_once('#') { if namespace == ctx.current_namespace { - def_name.to_string() - } else { - format!("{}.{}", namespace, def_name) + return rewrite_local_main(def_name, ctx); } + return format!("{}.{}", namespace, def_name); + } + // Bare NSID — implicit main of the named lexicon. If it names the + // current lexicon (rare but possible), rewrite to the local main + // name; otherwise leave as-is. + if ref_str == ctx.current_namespace { + return ctx.local_main_name.clone(); + } + ref_str.to_string() +} + +/// Rewrite a bare def name to account for the lexicon's main-def +/// rename. A def name of `"main"` in a lexicon whose main has been +/// renamed to its namespace's last segment becomes that segment +/// instead; any other name passes through unchanged. +fn rewrite_local_main(def_name: &str, ctx: &ConversionContext) -> String { + if def_name == "main" { + ctx.local_main_name.clone() } else { - // Malformed ref — pass through unchanged rather than inventing a namespace. - ref_str.to_string() + def_name.to_string() } } diff --git a/tests/lexicon_to_mlf/main_renamed_local_ref/expected.mlf b/tests/lexicon_to_mlf/main_renamed_local_ref/expected.mlf new file mode 100644 index 0000000..2875419 --- /dev/null +++ b/tests/lexicon_to_mlf/main_renamed_local_ref/expected.mlf @@ -0,0 +1,9 @@ +@main +def type thing = { + value!: string, +}; + +def type container = { + items!: thing[], +}; + diff --git a/tests/lexicon_to_mlf/main_renamed_local_ref/input.json b/tests/lexicon_to_mlf/main_renamed_local_ref/input.json new file mode 100644 index 0000000..35ce703 --- /dev/null +++ b/tests/lexicon_to_mlf/main_renamed_local_ref/input.json @@ -0,0 +1,23 @@ +{ + "lexicon": 1, + "id": "com.example.thing", + "defs": { + "main": { + "type": "object", + "required": ["value"], + "properties": { + "value": {"type": "string"} + } + }, + "container": { + "type": "object", + "required": ["items"], + "properties": { + "items": { + "type": "array", + "items": {"type": "ref", "ref": "#main"} + } + } + } + } +}