Lightweight 0.20260303.0
Loading...
Searching...
No Matches
SplitFileWriter.hpp
1// SPDX-License-Identifier: Apache-2.0
2
3#pragma once
4
5#include "../Api.hpp"
6
7#include <cstddef>
8#include <filesystem>
9#include <string>
10#include <string_view>
11#include <vector>
12
13namespace Lightweight::CodeGen
14{
15
16/// @brief A pre-rendered text block plus its line count, ready to be packed into
17/// one or more output files by `EmitChunked`.
18///
19/// The block is treated as opaque — `EmitChunked` never splits a block in two.
20/// Callers compute `lineCount` once and reuse the same value across multiple
21/// passes, since counting newlines on every visit would be wasteful for large
22/// migrations.
24{
25 /// Pre-rendered text of the block. Treated as opaque by `EmitChunked` —
26 /// never split across files.
27 std::string content;
28
29 /// Number of newlines in `content`, computed once by the caller and reused
30 /// across packing passes.
31 std::size_t lineCount = 0;
32};
33
34/// @brief Greedy bin-packing of `blocks` across files of at most `maxLinesPerFile`
35/// lines.
36///
37/// One block always lands wholly in one chunk — even when its line count exceeds
38/// the budget — because builder DSL chains cannot be broken across translation
39/// units. The returned outer vector has no empty inner vectors. When
40/// `maxLinesPerFile == 0`, every block lands in a single chunk.
41[[nodiscard]] LIGHTWEIGHT_API std::vector<std::vector<CodeBlock>> GroupBlocksByLineBudget(
42 std::vector<CodeBlock> const& blocks, std::size_t maxLinesPerFile);
43
44/// @brief Result of an `EmitChunked` call.
46{
47 /// All files actually written, in apply order. Either `[outputPath]` (single
48 /// file) or `[<stem>_part01.<ext>, <stem>_part02.<ext>, ...]`.
49 std::vector<std::filesystem::path> writtenFiles;
50};
51
52/// @brief Writes one or more output files, splitting `blocks` across `<stem>_partNN.<ext>`
53/// siblings when their combined line count exceeds `maxLinesPerFile`. When the
54/// total fits, a single `outputPath` is written and split is skipped.
55///
56/// `fileHeader` and `fileFooter` are emitted at the top/bottom of every produced
57/// file (so all chunks remain self-contained translation units when used for
58/// `.cpp` outputs). Pass empty strings to skip them.
59///
60/// @return `WriteResult` listing the paths actually written.
61/// @throws `std::runtime_error` if any output file cannot be opened.
62[[nodiscard]] LIGHTWEIGHT_API WriteResult EmitChunked(std::filesystem::path const& outputPath,
63 std::vector<CodeBlock> const& blocks,
64 std::size_t maxLinesPerFile,
65 std::string_view fileHeader = {},
66 std::string_view fileFooter = {});
67
68/// @brief Writes a `CMakeLists.txt` and a `Plugin.cpp` next to the generated
69/// migration sources so the output directory becomes a drop-in plugin.
70///
71/// Mirrors the layout of `src/tools/LupMigrationsPlugin/` so consumers can
72/// `add_subdirectory()` the generated dir and pick up a self-registering plugin
73/// without further glue.
74LIGHTWEIGHT_API void EmitPluginCmake(std::filesystem::path const& outputDir,
75 std::string_view pluginName,
76 std::string_view sourceGlob = "lup_*.cpp");
77
78} // namespace Lightweight::CodeGen
A pre-rendered text block plus its line count, ready to be packed into one or more output files by Em...
Result of an EmitChunked call.
std::vector< std::filesystem::path > writtenFiles