@@ -364,4 +364,65 @@ TEST_SUITE(generate) {
364364 EXPECT_NE (partition_prompt_it->prompt .find (" ## Module: `demo.math:detail`" ),
365365 std::string::npos);
366366 }
367+
368+ TEST_CASE (build_module_graph_does_not_create_partition_main_cycle) {
369+ ScopedTempDir temp (" build_module_cycle" );
370+ fs::create_directories (temp.path / " src" );
371+
372+ auto config = make_config (temp.path );
373+
374+ extract::ProjectModel model;
375+ model.uses_modules = true ;
376+
377+ auto main_file = (temp.path / " src" / " math.cppm" ).generic_string ();
378+ auto partition_file = (temp.path / " src" / " math.detail.cppm" ).generic_string ();
379+
380+ auto api_symbol = make_symbol (21 , " add" , " demo::math::add" , " int add(int lhs, int rhs)" , main_file);
381+ auto partition_symbol = make_symbol (22 , " detail" , " demo::math::detail" , " int detail()" , partition_file);
382+
383+ model.symbols .emplace (api_symbol.id , api_symbol);
384+ model.symbols .emplace (partition_symbol.id , partition_symbol);
385+
386+ model.modules .emplace (
387+ main_file,
388+ extract::ModuleUnit{
389+ .name = " demo.math" ,
390+ .is_interface = true ,
391+ .source_file = main_file,
392+ .imports = {" demo.math:detail" },
393+ .symbols = {api_symbol.id },
394+ });
395+ model.modules .emplace (
396+ partition_file,
397+ extract::ModuleUnit{
398+ .name = " demo.math:detail" ,
399+ .is_interface = true ,
400+ .source_file = partition_file,
401+ .imports = {},
402+ .symbols = {partition_symbol.id },
403+ });
404+
405+ auto graph = build_page_graph (config, model);
406+
407+ ASSERT_TRUE (graph.nodes .contains (" demo.math/index.md" ));
408+ ASSERT_TRUE (graph.nodes .contains (" demo.math/detail.md" ));
409+
410+ auto & main_node = graph.nodes .at (" demo.math/index.md" );
411+ auto & partition_node = graph.nodes .at (" demo.math/detail.md" );
412+
413+ EXPECT_EQ (std::count (main_node.depends_on .begin (), main_node.depends_on .end (),
414+ " demo.math/detail.md" ),
415+ 1 );
416+ EXPECT_EQ (std::count (partition_node.depends_on .begin (), partition_node.depends_on .end (),
417+ " demo.math/index.md" ),
418+ 0 );
419+
420+ auto pos_main = std::find (graph.generation_order .begin (), graph.generation_order .end (),
421+ " demo.math/index.md" );
422+ auto pos_partition = std::find (graph.generation_order .begin (), graph.generation_order .end (),
423+ " demo.math/detail.md" );
424+ ASSERT_TRUE (pos_main != graph.generation_order .end ());
425+ ASSERT_TRUE (pos_partition != graph.generation_order .end ());
426+ EXPECT_LT (pos_partition, pos_main);
427+ }
367428};
0 commit comments