1
1
#pragma once
2
2
3
- #include < binlog/EventStream.hpp>
4
- #include < binlog/PrettyPrinter.hpp>
3
+ #include < binlog/binlog.hpp>
5
4
#include < string>
6
5
#include < vector>
7
6
#include < unordered_map>
10
9
#include < filesystem>
11
10
#include < sstream>
12
11
#include < mutex>
12
+ #include < fmt/format.h>
13
+ #include < fmt/chrono.h>
14
+ #include < nlohmann/json.hpp>
13
15
14
16
namespace codeql {
15
17
16
18
extern const std::string_view programName;
17
19
20
+ struct SwiftDiagnosticsSource ;
21
+
22
+ struct SwiftDiagnosticsSourceWithLocation {
23
+ const SwiftDiagnosticsSource& source;
24
+ std::string_view file;
25
+ unsigned startLine;
26
+ unsigned startColumn;
27
+ unsigned endLine;
28
+ unsigned endColumn;
29
+
30
+ // see SwiftDiagnosticsSource::json
31
+ nlohmann::json json (const std::chrono::system_clock::time_point& timestamp,
32
+ std::string_view message) const ;
33
+
34
+ std::string str () const ;
35
+ };
36
+
18
37
// Models a diagnostic source for Swift, holding static information that goes out into a diagnostic
19
38
// These are internally stored into a map on id's. A specific error log can use binlog's category
20
39
// as id, which will then be used to recover the diagnostic source while dumping.
@@ -29,36 +48,25 @@ struct SwiftDiagnosticsSource {
29
48
30
49
// for the moment, we only output errors, so no need to store the severity
31
50
32
- // registers a diagnostics source for later retrieval with get, if not done yet
33
- template <const SwiftDiagnosticsSource* Source>
34
- static void ensureRegistered () {
35
- static std::once_flag once;
36
- std::call_once (once, registerImpl, Source);
37
- }
38
-
39
- // gets a previously inscribed SwiftDiagnosticsSource for the given id. Will abort if none exists
40
- static const SwiftDiagnosticsSource& get (const std::string& id) { return *map ().at (id); }
41
-
42
- // emit a JSON diagnostics for this source with the given timestamp and message to out
51
+ // create a JSON diagnostics for this source with the given timestamp and message to out
43
52
// A plaintextMessage is used that includes both the message and the action to take. Dots are
44
53
// appended to both. The id is used to construct the source id in the form
45
- // `swift/<prog name>/<id with '-' replacing '_'>`
46
- void emit (std::ostream& out, std::string_view timestamp, std::string_view message) const ;
54
+ // `swift/<prog name>/<id>`
55
+ nlohmann::json json (const std::chrono::system_clock::time_point& timestamp,
56
+ std::string_view message) const ;
57
+
58
+ SwiftDiagnosticsSourceWithLocation withLocation (std::string_view file,
59
+ unsigned startLine = 0 ,
60
+ unsigned startColumn = 0 ,
61
+ unsigned endLine = 0 ,
62
+ unsigned endColumn = 0 ) const {
63
+ return {*this , file, startLine, startColumn, endLine, endColumn};
64
+ }
47
65
48
66
private:
49
- static void registerImpl (const SwiftDiagnosticsSource* source);
50
-
51
67
std::string sourceId () const ;
52
- using Map = std::unordered_map<std::string, const SwiftDiagnosticsSource*>;
53
-
54
- static Map& map () {
55
- static Map ret;
56
- return ret;
57
- }
58
68
};
59
69
60
- // An output modeling binlog's output stream concept that intercepts binlog entries and translates
61
- // them to appropriate diagnostics JSON entries
62
70
class SwiftDiagnosticsDumper {
63
71
public:
64
72
// opens path for writing out JSON entries. Returns whether the operation was successful.
@@ -69,22 +77,65 @@ class SwiftDiagnosticsDumper {
69
77
70
78
void flush () { output.flush (); }
71
79
72
- // write out binlog entries as corresponding JSON diagnostics entries. Expects all entries to have
73
- // a category equal to an id of a previously created SwiftDiagnosticSource.
74
- void write (const char * buffer, std::size_t bufferSize);
80
+ template <typename Source>
81
+ void write (const Source& source,
82
+ const std::chrono::system_clock::time_point& timestamp,
83
+ std::string_view message) {
84
+ if (output) {
85
+ output << source.json (timestamp, message) << ' \n ' ;
86
+ }
87
+ }
88
+
89
+ bool good () const { return output.good (); }
90
+ explicit operator bool () const { return good (); }
75
91
76
92
private:
77
- binlog::EventStream events;
78
93
std::ofstream output;
79
- binlog::PrettyPrinter timestampedMessagePrinter{" %u %m" , " %Y-%m-%dT%H:%M:%S.%NZ" };
80
94
};
81
95
82
- } // namespace codeql
83
-
84
- namespace codeql_diagnostics {
85
- constexpr codeql::SwiftDiagnosticsSource internal_error{
86
- " internal_error" ,
96
+ constexpr codeql::SwiftDiagnosticsSource internalError{
97
+ " internal-error" ,
87
98
" Internal error" ,
88
99
" Contact us about this issue" ,
89
100
};
90
- } // namespace codeql_diagnostics
101
+ } // namespace codeql
102
+
103
+ namespace mserialize {
104
+ // log diagnostic sources using just their id, using binlog/mserialize internal plumbing
105
+ template <>
106
+ struct CustomTag <codeql::SwiftDiagnosticsSource, void > : detail::BuiltinTag<std::string> {
107
+ using T = codeql::SwiftDiagnosticsSource;
108
+ };
109
+
110
+ template <>
111
+ struct CustomSerializer <codeql::SwiftDiagnosticsSource, void > {
112
+ template <typename OutputStream>
113
+ static void serialize (const codeql::SwiftDiagnosticsSource& source, OutputStream& out) {
114
+ mserialize::serialize (source.id , out);
115
+ }
116
+
117
+ static size_t serialized_size (const codeql::SwiftDiagnosticsSource& source) {
118
+ return mserialize::serialized_size (source.id );
119
+ }
120
+ };
121
+
122
+ template <>
123
+ struct CustomTag <codeql::SwiftDiagnosticsSourceWithLocation, void >
124
+ : detail::BuiltinTag<std::string> {
125
+ using T = codeql::SwiftDiagnosticsSourceWithLocation;
126
+ };
127
+
128
+ template <>
129
+ struct CustomSerializer <codeql::SwiftDiagnosticsSourceWithLocation, void > {
130
+ template <typename OutputStream>
131
+ static void serialize (const codeql::SwiftDiagnosticsSourceWithLocation& source,
132
+ OutputStream& out) {
133
+ mserialize::serialize (source.str (), out);
134
+ }
135
+
136
+ static size_t serialized_size (const codeql::SwiftDiagnosticsSourceWithLocation& source) {
137
+ return mserialize::serialized_size (source.str ());
138
+ }
139
+ };
140
+
141
+ } // namespace mserialize
0 commit comments