Skip to content

Commit c8c9636

Browse files
committed
Merge remote-tracking branch 'origin/31-pb-attribute-vocabulary' into staging
2 parents ba848d5 + d52a096 commit c8c9636

47 files changed

Lines changed: 2611 additions & 213 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/consumer_bson.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ class BsonTemplateCallback : public clang::ast_matchers::MatchFinder::MatchCallb
248248

249249
static bool is_chrono_time_point_(const clang::QualType& qt) {
250250
std::string name = qt.getAsString();
251-
return name.find("std::chrono::time_point") == 0 || name.find("time_point<") != std::string::npos;
251+
return name.find("std::chrono::") != std::string::npos && name.find("time_point") != std::string::npos;
252252
}
253253

254254
// ── type name for emitted code ──

src/consumer_pb.hpp

Lines changed: 239 additions & 54 deletions
Large diffs are not rendered by default.

src/consumer_proto.hpp

Lines changed: 799 additions & 0 deletions
Large diffs are not rendered by default.

src/h5_attr_translator.hpp

Lines changed: 40 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,9 @@ inline bool is_h5_attr_name(llvm::StringRef name) {
4040
|| name == "serialize_full";
4141
}
4242

43-
inline bool is_rlp_attr_name(llvm::StringRef name) {
44-
return name == "name" || name == "ignore" || name == "doc"
45-
|| name == "alias" || name == "required" || name == "timestamp";
46-
}
47-
4843
inline bool is_json_attr_name(llvm::StringRef name) {
4944
return name == "name" || name == "ignore" || name == "doc"
50-
|| name == "alias" || name == "version" || name == "name_all"
51-
|| name == "required" || name == "format" || name == "pattern"
52-
|| name == "min" || name == "max" || name == "tool_format";
45+
|| name == "alias" || name == "required" || name == "type";
5346
}
5447

5548
inline bool is_msgpack_attr_name(llvm::StringRef name) {
@@ -75,6 +68,11 @@ inline bool is_avro_attr_name(llvm::StringRef name) {
7568
|| name == "uuid" || name == "date" || name == "time";
7669
}
7770

71+
inline bool is_rlp_attr_name(llvm::StringRef name) {
72+
return name == "name" || name == "ignore" || name == "doc"
73+
|| name == "alias" || name == "required" || name == "timestamp";
74+
}
75+
7876
// Skip whitespace and comments at position `i` in `src`. Returns the new
7977
// position. Comments are emitted to `out` verbatim.
8078
inline std::size_t skip_ws(llvm::StringRef src, std::size_t i, std::string& out) {
@@ -173,58 +171,45 @@ inline std::vector<llvm::StringRef> split_attrs(llvm::StringRef block) {
173171
return out;
174172
}
175173

176-
// Rewrite one attribute spec. If it starts with `h5::<recognized-name>`,
177-
// convert to `clang::annotate("h5::<name>", <args>)`. Otherwise leave verbatim.
174+
// Rewrite one attribute spec. If it starts with a recognized namespace,
175+
// convert to `clang::annotate("ns::<name>", <args>)`. Otherwise leave verbatim.
178176
inline std::string rewrite_one_attr(llvm::StringRef spec) {
179177
std::size_t start = 0;
180178
while (start < spec.size() && std::isspace(static_cast<unsigned char>(spec[start]))) ++start;
181179
llvm::StringRef leading = spec.substr(0, start);
182180
llvm::StringRef body = spec.substr(start);
183181

184-
bool is_h5 = body.starts_with("h5::");
185-
bool is_rlp = body.starts_with("rlp::");
186-
if (!is_h5 && !is_rlp) return spec.str();
187-
llvm::StringRef ns = is_h5 ? "h5::" : "rlp::";
188-
bool is_h5 = body.starts_with("h5::");
189-
bool is_json = body.starts_with("json::");
190-
if (!is_h5 && !is_json) return spec.str();
191-
llvm::StringRef ns = is_h5 ? "h5::" : "json::";
192-
bool is_h5 = body.starts_with("h5::");
182+
bool is_h5 = body.starts_with("h5::");
183+
bool is_json = body.starts_with("json::");
193184
bool is_msgpack = body.starts_with("msgpack::");
194-
if (!is_h5 && !is_msgpack) return spec.str();
195-
llvm::StringRef ns = is_h5 ? "h5::" : "msgpack::";
196-
if (!body.starts_with(ns)) return spec.str();
197-
bool is_h5 = body.starts_with("h5::");
198-
bool is_cbor = body.starts_with("cbor::");
199-
if (!is_h5 && !is_cbor) return spec.str();
200-
llvm::StringRef ns = is_h5 ? "h5::" : "cbor::";
201-
bool is_h5 = body.starts_with("h5::");
202-
bool is_bson = body.starts_with("bson::");
203-
if (!is_h5 && !is_bson) return spec.str();
204-
llvm::StringRef ns = is_h5 ? "h5::" : "bson::";
205-
bool is_h5 = body.starts_with("h5::");
206-
bool is_avro = body.starts_with("avro::");
207-
if (!is_h5 && !is_avro) return spec.str();
208-
llvm::StringRef ns = is_h5 ? "h5::" : "avro::";
185+
bool is_cbor = body.starts_with("cbor::");
186+
bool is_bson = body.starts_with("bson::");
187+
bool is_avro = body.starts_with("avro::");
188+
bool is_rlp = body.starts_with("rlp::");
189+
if (!is_h5 && !is_json && !is_msgpack && !is_cbor && !is_bson && !is_avro && !is_rlp) return spec.str();
190+
191+
llvm::StringRef ns;
192+
if (is_h5) ns = "h5::";
193+
else if (is_json) ns = "json::";
194+
else if (is_msgpack) ns = "msgpack::";
195+
else if (is_cbor) ns = "cbor::";
196+
else if (is_bson) ns = "bson::";
197+
else if (is_avro) ns = "avro::";
198+
else ns = "rlp::";
209199

210200
body = body.drop_front(ns.size());
211201
std::size_t i = 0;
212202
while (i < body.size()
213203
&& (std::isalnum(static_cast<unsigned char>(body[i])) || body[i] == '_')) ++i;
214204
if (i == 0) return spec.str();
215205
llvm::StringRef name = body.substr(0, i);
216-
if (is_h5 && !is_h5_attr_name(name)) return spec.str();
217-
if (is_rlp && !is_rlp_attr_name(name)) return spec.str();
218-
if (is_h5 && !is_h5_attr_name(name)) return spec.str();
219-
if (is_json && !is_json_attr_name(name)) return spec.str();
220-
if (is_h5 && !is_h5_attr_name(name)) return spec.str();
206+
if (is_h5 && !is_h5_attr_name(name)) return spec.str();
207+
if (is_json && !is_json_attr_name(name)) return spec.str();
221208
if (is_msgpack && !is_msgpack_attr_name(name)) return spec.str();
222-
if (is_h5 && !is_h5_attr_name(name)) return spec.str();
223-
if (is_cbor && !is_cbor_attr_name(name)) return spec.str();
224-
if (is_h5 && !is_h5_attr_name(name)) return spec.str();
225-
if (is_bson && !is_bson_attr_name(name)) return spec.str();
226-
if (is_h5 && !is_h5_attr_name(name)) return spec.str();
227-
if (is_avro && !is_avro_attr_name(name)) return spec.str();
209+
if (is_cbor && !is_cbor_attr_name(name)) return spec.str();
210+
if (is_bson && !is_bson_attr_name(name)) return spec.str();
211+
if (is_avro && !is_avro_attr_name(name)) return spec.str();
212+
if (is_rlp && !is_rlp_attr_name(name)) return spec.str();
228213

229214
while (i < body.size() && std::isspace(static_cast<unsigned char>(body[i]))) ++i;
230215

@@ -294,12 +279,9 @@ inline std::string rewrite(llvm::StringRef src) {
294279
continue;
295280
}
296281
llvm::StringRef block = src.substr(i + 2, close - i - 2);
297-
if (block.contains("h5::") || block.contains("rlp::")) {
298-
if (block.contains("h5::") || block.contains("json::")) {
299-
if (block.contains("h5::") || block.contains("msgpack::")) {
300-
if (block.contains("h5::") || block.contains("cbor::")) {
301-
if (block.contains("h5::") || block.contains("bson::")) {
302-
if (block.contains("h5::") || block.contains("avro::")) {
282+
if (block.contains("h5::") || block.contains("json::") || block.contains("msgpack::")
283+
|| block.contains("cbor::") || block.contains("bson::") || block.contains("avro::")
284+
|| block.contains("rlp::")) {
303285
auto attrs = split_attrs(block);
304286
out.append("[[");
305287
for (std::size_t k = 0; k < attrs.size(); ++k) {
@@ -332,12 +314,13 @@ inline void install_virtual_files(clang::tooling::ClangTool& Tool,
332314
for (const auto& p : paths) {
333315
std::string content = read_file(p);
334316
if (content.empty()) continue;
335-
if (content.find("h5::") == std::string::npos && content.find("rlp::") == std::string::npos) continue;
336-
if (content.find("h5::") == std::string::npos && content.find("json::") == std::string::npos) continue;
337-
if (content.find("h5::") == std::string::npos && content.find("msgpack::") == std::string::npos) continue;
338-
if (content.find("h5::") == std::string::npos && content.find("cbor::") == std::string::npos) continue;
339-
if (content.find("h5::") == std::string::npos && content.find("bson::") == std::string::npos) continue;
340-
if (content.find("h5::") == std::string::npos && content.find("avro::") == std::string::npos) continue;
317+
if (content.find("h5::") == std::string::npos
318+
&& content.find("json::") == std::string::npos
319+
&& content.find("msgpack::") == std::string::npos
320+
&& content.find("cbor::") == std::string::npos
321+
&& content.find("bson::") == std::string::npos
322+
&& content.find("avro::") == std::string::npos
323+
&& content.find("rlp::") == std::string::npos) continue;
341324
storage.push_back(rewrite(content));
342325
Tool.mapVirtualFile(p, storage.back());
343326
}

src/h5cpp.cpp

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,17 @@
1818
#include "producer_h5.hpp"
1919
#include "producer_sql.hpp"
2020
#include "consumer.hpp"
21-
#include "consumer_rlp.hpp"
21+
#include "consumer_json.hpp"
22+
#include "consumer_msgpack.hpp"
23+
#include "consumer_cbor.hpp"
2224
#include "consumer_bson.hpp"
2325
#include "consumer_avro.hpp"
26+
#include "consumer_rlp.hpp"
2427
#include "producer_pb.hpp"
2528
#include "consumer_pb.hpp"
29+
#include "consumer_proto.hpp"
30+
#include "pb_attr_translator.hpp"
2631
#include "h5_attr_translator.hpp"
27-
#include "consumer_json.hpp"
28-
#include "consumer_msgpack.hpp"
29-
#include "consumer_cbor.hpp"
3032

3133
clang::ast_matchers::StatementMatcher h5templateMatcher = clang::ast_matchers::callExpr( clang::ast_matchers::allOf(
3234
clang::ast_matchers::hasDescendant( clang::ast_matchers::declRefExpr( clang::ast_matchers::to( clang::ast_matchers::varDecl().bind("variableDecl") ) ) ),
@@ -52,8 +54,6 @@ clang::ast_matchers::StatementMatcher h5templateMatcher = clang::ast_matchers::c
5254
)) )))
5355
));
5456

55-
enum class OutputFormat { hdf5, protobuf, json, msgpack, cbor, bson, avro, rlp,
56-
sql_postgres, sql_mysql, sql_lite3 };
5757
// pbTemplateMatcher: same shape as h5templateMatcher, but triggers on the
5858
// pb.hpp public surface. Covers pb::encode, pb::decode, and pb::encode_into.
5959
clang::ast_matchers::StatementMatcher pbTemplateMatcher = clang::ast_matchers::callExpr( clang::ast_matchers::allOf(
@@ -71,7 +71,8 @@ clang::ast_matchers::StatementMatcher pbTemplateMatcher = clang::ast_matchers::c
7171
)) )))
7272
));
7373

74-
enum class OutputFormat { hdf5, protobuf, json, msgpack, cbor, bson, avro, rlp };
74+
enum class OutputFormat { hdf5, protobuf, json, msgpack, cbor, bson, avro, rlp,
75+
sql_postgres, sql_mysql, sql_lite3 };
7576

7677
static llvm::cl::OptionCategory MyToolCategory("h5cpp options");
7778
static llvm::cl::extrahelp CommonHelp(clang::tooling::CommonOptionsParser::HelpMessage);
@@ -103,6 +104,11 @@ static llvm::cl::opt<OutputFormat> Format(llvm::cl::desc("Output format:"),
103104
llvm::cl::init(OutputFormat::hdf5),
104105
llvm::cl::cat(MyToolCategory));
105106

107+
static llvm::cl::opt<std::string> ProtoOutputFile("proto-out",
108+
llvm::cl::desc("Phase 3: .proto schema output (used with --protobuf)"),
109+
llvm::cl::value_desc("file"),
110+
llvm::cl::cat(MyToolCategory));
111+
106112
static llvm::cl::opt<bool> CheckMode("check",
107113
llvm::cl::desc("Verify that the existing generated file is up to date (exit 1 if stale)"),
108114
llvm::cl::cat(MyToolCategory),
@@ -128,6 +134,12 @@ int main(int argc, const char **argv) {
128134
h5_attr_translator::install_virtual_files(
129135
Tool, OptionsParser.getSourcePathList(), _h5_attr_storage);
130136

137+
// Issue #31: rewrite [[pb::xxx(...)]] → [[clang::annotate("pb::xxx", ...)]]
138+
// for each source path before Clang sees it.
139+
std::vector<std::string> _pb_attr_storage;
140+
pb_attr_translator::install_virtual_files(
141+
Tool, OptionsParser.getSourcePathList(), _pb_attr_storage);
142+
131143
std::string work_path = OutputFile;
132144
if (CheckMode) {
133145
work_path = OutputFile + ".h5cpp-check";
@@ -145,64 +157,52 @@ int main(int argc, const char **argv) {
145157
}
146158
case OutputFormat::protobuf: {
147159
PbTemplateCallback<PbProducer> callback(work_path);
148-
clang::ast_matchers::MatchFinder Finder;
149160
Finder.addMatcher(pbTemplateMatcher, &callback);
161+
std::optional<ProtoTemplateCallback> proto_cb;
162+
if (!ProtoOutputFile.empty()) {
163+
proto_cb.emplace(ProtoOutputFile);
164+
Finder.addMatcher(pbTemplateMatcher, &*proto_cb);
165+
}
150166
rc = Tool.run(clang::tooling::newFrontendActionFactory(&Finder).get());
151167
if (rc == 0 && callback.error()) rc = 1;
152168
break;
169+
}
153170
case OutputFormat::json: {
154171
JsonTemplateCallback callback(work_path);
155172
Finder.addMatcher(h5templateMatcher, &callback);
156173
rc = Tool.run(clang::tooling::newFrontendActionFactory(&Finder).get());
157-
}
158-
case OutputFormat::json:
159-
llvm::errs() << "h5cpp-compiler: --format json not yet implemented\n";
160-
rc = 1;
161174
break;
162175
}
163-
case OutputFormat::msgpack:
164-
llvm::errs() << "h5cpp-compiler: --format msgpack not yet implemented\n";
165-
rc = 1;
166176
case OutputFormat::msgpack: {
167177
MsgpackTemplateCallback callback(work_path);
168178
Finder.addMatcher(h5templateMatcher, &callback);
169179
rc = Tool.run(clang::tooling::newFrontendActionFactory(&Finder).get());
170180
break;
171181
}
172-
llvm::errs() << "h5cpp-compiler: --format cbor not yet implemented\n";
173-
rc = 1;
174182
case OutputFormat::cbor: {
175183
CborTemplateCallback callback(work_path);
176184
Finder.addMatcher(h5templateMatcher, &callback);
177185
rc = Tool.run(clang::tooling::newFrontendActionFactory(&Finder).get());
178186
break;
179187
}
180-
case OutputFormat::bson:
181-
llvm::errs() << "h5cpp-compiler: --format bson not yet implemented\n";
182-
rc = 1;
183188
case OutputFormat::bson: {
184189
BsonTemplateCallback callback(work_path);
185190
Finder.addMatcher(h5templateMatcher, &callback);
186191
rc = Tool.run(clang::tooling::newFrontendActionFactory(&Finder).get());
187192
break;
188193
}
189-
case OutputFormat::avro:
190-
llvm::errs() << "h5cpp-compiler: --format avro not yet implemented\n";
191-
rc = 1;
192194
case OutputFormat::avro: {
193195
AvroTemplateCallback callback(work_path);
194196
Finder.addMatcher(h5templateMatcher, &callback);
195197
rc = Tool.run(clang::tooling::newFrontendActionFactory(&Finder).get());
196198
break;
199+
}
197200
case OutputFormat::rlp: {
198201
RlpTemplateCallback callback(work_path);
199202
Finder.addMatcher(h5templateMatcher, &callback);
200203
rc = Tool.run(clang::tooling::newFrontendActionFactory(&Finder).get());
201-
}
202-
case OutputFormat::rlp:
203-
llvm::errs() << "h5cpp-compiler: --format rlp not yet implemented\n";
204-
rc = 1;
205204
break;
205+
}
206206
case OutputFormat::sql_postgres: {
207207
H5TemplateCallback<SqlProducer<SqlDialect::postgres>> callback(work_path);
208208
Finder.addMatcher(h5templateMatcher, &callback);
@@ -221,7 +221,6 @@ int main(int argc, const char **argv) {
221221
rc = Tool.run(clang::tooling::newFrontendActionFactory(&Finder).get());
222222
break;
223223
}
224-
}
225224
}
226225
}
227226

0 commit comments

Comments
 (0)