#pragma once #include #include #include "swift/extractor/trap/TrapLabel.h" #include "swift/extractor/infra/file/TargetFile.h" namespace codeql { // Abstracts a given trap output file, with its own universe of trap labels class TrapDomain { TargetFile out; public: explicit TrapDomain(TargetFile&& out) : out{std::move(out)} {} template void emit(const Entry& e) { out << e << '\n'; } template void debug(const Args&... args) { out << "/* DEBUG:\n"; (out << ... << args); out << "\n*/\n"; } template TrapLabel createLabel() { auto ret = allocateLabel(); assignStar(ret); out << '\n'; return ret; } template TrapLabel createLabel(Args&&... args) { auto ret = allocateLabel(); assignKey(ret, std::forward(args)...); out << '\n'; return ret; } template TrapLabel createLabelWithImplementationId(const std::string_view& implementationId, Args&&... args) { auto ret = allocateLabel(); assignKey(ret, std::forward(args)...); out << " .implementation " << trapQuoted(implementationId) << '\n'; return ret; } private: uint64_t id_{0}; template TrapLabel allocateLabel() { return TrapLabel::unsafeCreateFromExplicitId(id_++); } template void assignStar(TrapLabel label) { out << label << "=*"; } template void assignKey(TrapLabel label, const std::string& key) { // prefix the key with the id to guarantee the same key is not used wrongly with different tags auto prefixed = std::string(Tag::prefix) + '_' + key; out << label << "=@" << trapQuoted(prefixed); } template void assignKey(TrapLabel label, const Args&... keyParts) { std::ostringstream oss; (oss << ... << keyParts); assignKey(label, oss.str()); } }; } // namespace codeql