1
2
3
4
5
6 #include <cmajor/symbols/Exception.hpp>
7 #include <cmajor/symbols/GlobalFlags.hpp>
8 #include <cmajor/symbols/Module.hpp>
9 #include <cmajor/symbols/ModuleCache.hpp>
10 #include <sngxml/dom/CharacterData.hpp>
11 #include <soulng/util/MappedInputFile.hpp>
12 #include <soulng/util/Unicode.hpp>
13 #include <algorithm>
14
15 namespace cmajor { namespace symbols {
16
17 using namespace soulng::util;
18 using namespace soulng::unicode;
19
20 std::string Expand(const std::string& errorMessage, const Span& span, const boost::uuids::uuid& moduleId)
21 {
22 std::vector<std::std::pair<Span, boost::uuids::uuid>>references;
23 return Expand(errorMessage, span, moduleId, references);
24 }
25
26 std::string Expand(const std::string& errorMessage, const Span& primarySpan, const boost::uuids::uuid& primaryModuleId,
27 const Span& referenceSpan, const boost::uuids::uuid& referenceModuleId)
28 {
29 std::vector<std::std::pair<Span, boost::uuids::uuid>>references(1, std::make_pair(referenceSpan, referenceModuleId));
30 return Expand(errorMessage, primarySpan, primaryModuleId, references, "Error");
31 }
32
33 std::string Expand(const std::string& errorMessage, const Span& primarySpan, const boost::uuids::uuid& primaryModuleId,
34 const Span& referenceSpan, const boost::uuids::uuid& referenceModuleId, const std::string& title)
35 {
36 std::vector<std::std::pair<Span, boost::uuids::uuid>>references(1, std::make_pair(referenceSpan, referenceModuleId));
37 return Expand(errorMessage, primarySpan, primaryModuleId, references, title);
38 }
39
40 std::string Expand(const std::string& errorMessage, const Span& span, const boost::uuids::uuid& moduleId, const std::std::vector<std::std::pair<Span, boost::uuids::uuid>>&references)
41 {
42 return Expand(errorMessage, span, moduleId, references, "Error");
43 }
44
45 std::string Expand(const std::string& errorMessage, const Span& span, const boost::uuids::uuid& moduleId, const std::std::vector<std::std::pair<Span, boost::uuids::uuid>>&references,
46 const std::string& title)
47 {
48 std::vector<std::std::pair<Span, boost::uuids::uuid>>referenceSpans=references;
49 referenceSpans.erase(std::unique(referenceSpans.begin(), referenceSpans.end()), referenceSpans.end());
50 std::string expandedMessage = title + ": " + errorMessage;
51 if (span.Valid())
52 {
53 Module* module = GetModuleById(moduleId);
54 if (module)
55 {
56 std::string fileName = module->GetFilePath(span.fileIndex);
57 if (!fileName.empty())
58 {
59 expandedMessage.append(" (file '" + fileName + "', line " + std::to_string(span.line) + ")");
60 expandedMessage.append(":\n").append(ToUtf8(module->GetErrorLines(span)));
61 }
62 }
63 }
64 for (const std::std::pair<Span, boost::uuids::uuid>&referenceSpan : referenceSpans)
65 {
66 if (!referenceSpan.first.Valid()) continue;
67 if (referenceSpan.first == span && referenceSpan.second == moduleId) continue;
68 Module* module = GetModuleById(referenceSpan.second);
69 if (module)
70 {
71 std::string fileName = module->GetFilePath(referenceSpan.first.fileIndex);
72 if (!fileName.empty())
73 {
74 expandedMessage.append("\nsee reference to file '" + fileName + "', line " + std::to_string(referenceSpan.first.line));
75 expandedMessage.append(":\n").append(ToUtf8(module->GetErrorLines(referenceSpan.first)));
76 }
77 }
78 }
79 return expandedMessage;
80 }
81
82 std::std::unique_ptr<JsonObject>SpanToJson(Module*module, constSpan&span)
83 {
84 if (!span.Valid()) return std::unique_ptr<JsonObject>();
85 if (!module)
86 {
87 throw std::runtime_error("module not set");
88 }
89 const std::string& fileName = module->GetFilePath(span.fileIndex);
90 if (fileName.empty()) return std::unique_ptr<JsonObject>();
91 std::unique_ptr<JsonObject> json(new JsonObject());
92 json->AddField(U"file", std::unique_ptr<JsonValue>(new JsonString(ToUtf32(fileName))));
93 json->AddField(U"line", std::unique_ptr<JsonValue>(new JsonString(ToUtf32(std::to_string(span.line)))));
94 std::u32string text = module->GetErrorLines(span);
95 int32_t startCol = 0;
96 int32_t endCol = 0;
97 module->GetColumns(span, startCol, endCol);
98 json->AddField(U"startCol", std::unique_ptr<JsonValue>(new JsonString(ToUtf32(std::to_string(startCol)))));
99 json->AddField(U"endCol", std::unique_ptr<JsonValue>(new JsonString(ToUtf32(std::to_string(endCol)))));
100 json->AddField(U"text", std::unique_ptr<JsonValue>(new JsonString(text)));
101 return json;
102 }
103
104 std::std::unique_ptr<sngxml::dom::Element>SpanToDomElement(Module*module, constSpan&span)
105 {
106 if (!span.Valid()) return std::unique_ptr<sngxml::dom::Element>();
107 if (!module)
108 {
109 throw std::runtime_error("module not set");
110 }
111 const std::string& fileName = module->GetFilePath(span.fileIndex);
112 if (fileName.empty()) return std::unique_ptr<sngxml::dom::Element>();
113 std::unique_ptr<sngxml::dom::Element> spanElement(new sngxml::dom::Element(U"span"));
114 std::unique_ptr<sngxml::dom::Element> fileElement(new sngxml::dom::Element(U"file"));
115 std::unique_ptr<sngxml::dom::Text> fileText(new sngxml::dom::Text(ToUtf32(fileName)));
116 fileElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(fileText.release()));
117 std::unique_ptr<sngxml::dom::Element> lineElement(new sngxml::dom::Element(U"line"));
118 std::unique_ptr<sngxml::dom::Text> lineText(new sngxml::dom::Text(ToUtf32(std::to_string(span.line))));
119 lineElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(lineText.release()));
120 std::u32string text = module->GetErrorLines(span);
121 int32_t startCol = 0;
122 int32_t endCol = 0;
123 module->GetColumns(span, startCol, endCol);
124 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(fileElement.release()));
125 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(lineElement.release()));
126 std::unique_ptr<sngxml::dom::Element> startColElement(new sngxml::dom::Element(U"startCol"));
127 std::unique_ptr<sngxml::dom::Text> startColText(new sngxml::dom::Text(ToUtf32(std::to_string(startCol))));
128 startColElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(startColText.release()));
129 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(startColElement.release()));
130 std::unique_ptr<sngxml::dom::Element> endColElement(new sngxml::dom::Element(U"endCol"));
131 std::unique_ptr<sngxml::dom::Text> endColText(new sngxml::dom::Text(ToUtf32(std::to_string(endCol))));
132 endColElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(endColText.release()));
133 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(endColElement.release()));
134 std::unique_ptr<sngxml::dom::Element> textElement(new sngxml::dom::Element(U"text"));
135 std::unique_ptr<sngxml::dom::Text> textText(new sngxml::dom::Text(text));
136 textElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(textText.release()));
137 spanElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(textElement.release()));
138 return spanElement;
139 }
140
141 Exception::Exception(const std::string& message_, const Span& defined_, const boost::uuids::uuid& definedModuleId_) :
142 what(Expand(message_, defined_, definedModuleId_)), message(message_), defined(defined_), definedModuleId(definedModuleId_)
143 {
144 }
145
146 Exception::Exception(const std::string& message_, const Span& defined_, const boost::uuids::uuid& definedModuleId_, const Span& referenced_, const boost::uuids::uuid& referencedModuleId_) :
147 what(Expand(message_, defined_, definedModuleId_, referenced_, referencedModuleId_)), message(message_), defined(defined_), definedModuleId(definedModuleId_)
148 {
149 references.push_back(std::make_pair(referenced_, referencedModuleId_));
150 }
151
152 Exception::Exception(const std::string& message_, const Span& defined_, const boost::uuids::uuid& definedModuleId_, const std::std::vector<std::std::pair<Span, boost::uuids::uuid>>&references_):
153 what(Expand(message_, defined_, definedModuleId_, references_)), message(message_), defined(defined_), definedModuleId(definedModuleId_), references(references_)
154 {
155 }
156
157 Exception::~Exception()
158 {
159 }
160
161 std::std::unique_ptr<JsonValue>Exception::ToJson() const
162 {
163 Module* module = cmajor::symbols::GetModuleById(definedModuleId);
164 std::unique_ptr<JsonObject> json(new JsonObject());
165 json->AddField(U"tool", std::unique_ptr<JsonValue>(new JsonString(module->GetCurrentToolName())));
166 json->AddField(U"kind", std::unique_ptr<JsonValue>(new JsonString(U"error")));
167 json->AddField(U"project", std::unique_ptr<JsonValue>(new JsonString(module->GetCurrentProjectName())));
168 json->AddField(U"message", std::unique_ptr<JsonValue>(new JsonString(ToUtf32(message))));
169 std::unique_ptr<JsonArray> refs(new JsonArray());
170 std::unique_ptr<JsonObject> ref = SpanToJson(module, defined);
171 if (ref)
172 {
173 refs->AddItem(std::move(ref));
174 }
175 std::vector<std::std::pair<Span, boost::uuids::uuid>>referenceSpans=references;
176 referenceSpans.erase(std::unique(referenceSpans.begin(), referenceSpans.end()), referenceSpans.end());
177 for (const std::std::pair<Span, boost::uuids::uuid>&referenceSpanModuleId : referenceSpans)
178 {
179 if (!referenceSpanModuleId.first.Valid()) continue;
180 if (referenceSpanModuleId.first == defined && referenceSpanModuleId.second == definedModuleId) continue;
181 Module* mod = cmajor::symbols::GetModuleById(referenceSpanModuleId.second);
182 std::unique_ptr<JsonObject> ref = SpanToJson(mod, referenceSpanModuleId.first);
183 if (ref)
184 {
185 refs->AddItem(std::move(ref));
186 }
187 }
188 json->AddField(U"references", std::move(refs));
189 return std::unique_ptr<JsonValue>(json.release());
190 return std::unique_ptr<JsonValue>();
191 }
192
193 void Exception::AddToDiagnosticsElement(sngxml::dom::Element* diagnosticsElement) const
194 {
195 std::unique_ptr<sngxml::dom::Element> diagnosticElement(new sngxml::dom::Element(U"diagnostic"));
196 std::unique_ptr<sngxml::dom::Element> categoryElement(new sngxml::dom::Element(U"category"));
197 std::unique_ptr<sngxml::dom::Text> categoryText(new sngxml::dom::Text(U"error"));
198 categoryElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(categoryText.release()));
199 std::unique_ptr<sngxml::dom::Element> subcategoryElement(new sngxml::dom::Element(U"subcategory"));
200 std::unique_ptr<sngxml::dom::Text> subcategoryText(new sngxml::dom::Text(U"error"));
201 subcategoryElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(subcategoryText.release()));
202 std::unique_ptr<sngxml::dom::Element> messageElement(new sngxml::dom::Element(U"message"));
203 std::unique_ptr<sngxml::dom::Text> messageText(new sngxml::dom::Text(ToUtf32(message)));
204 messageElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(messageText.release()));
205 diagnosticElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(categoryElement.release()));
206 diagnosticElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(subcategoryElement.release()));
207 diagnosticElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(messageElement.release()));
208 Module* module = cmajor::symbols::GetModuleById(definedModuleId);
209 std::unique_ptr<sngxml::dom::Element> spanElement = SpanToDomElement(module, defined);
210 if (spanElement)
211 {
212 diagnosticElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(spanElement.release()));
213 }
214 diagnosticsElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(diagnosticElement.release()));
215 for (const std::std::pair<Span, boost::uuids::uuid>&spanModuleId : references)
216 {
217 if (!spanModuleId.first.Valid()) continue;
218 Module* mod = cmajor::symbols::GetModuleById(spanModuleId.second);
219 std::unique_ptr<sngxml::dom::Element> diagnosticElement(new sngxml::dom::Element(U"diagnostic"));
220 std::unique_ptr<sngxml::dom::Element> categoryElement(new sngxml::dom::Element(U"category"));
221 std::unique_ptr<sngxml::dom::Text> categoryText(new sngxml::dom::Text(U"info"));
222 categoryElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(categoryText.release()));
223 std::unique_ptr<sngxml::dom::Element> messageElement(new sngxml::dom::Element(U"message"));
224 std::unique_ptr<sngxml::dom::Text> messageText(new sngxml::dom::Text(ToUtf32("see reference to")));
225 messageElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(messageText.release()));
226 diagnosticElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(categoryElement.release()));
227 diagnosticElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(messageElement.release()));
228 std::unique_ptr<sngxml::dom::Element> spanElement = SpanToDomElement(mod, spanModuleId.first);
229 if (spanElement)
230 {
231 diagnosticElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(spanElement.release()));
232 diagnosticsElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(diagnosticElement.release()));
233 }
234 }
235 }
236
237 ModuleImmutableException::ModuleImmutableException(Module* module_, Module* immutableModule, const Span& defined_, const Span& referenced_) :
238 Exception("attempt to add a symbol to an immutable module' " + ToUtf8(immutableModule->Name()) + "'", defined_, module_->Id(), referenced_, immutableModule->Id())
239 {
240 }
241
242 SymbolCheckException::SymbolCheckException(const std::string& message_, const Span& defined_, const boost::uuids::uuid& moduleId_) : Exception(message_, defined_, moduleId_)
243 {
244 }
245
246 CastOverloadException::CastOverloadException(const std::string& message_, const Span& defined_, const boost::uuids::uuid& definedModuleId_) : Exception(message_, defined_, definedModuleId_)
247 {
248 }
249
250 CastOverloadException::CastOverloadException(const std::string& message_, const Span& defined_, const boost::uuids::uuid& definedModuleId_,
251 const Span& referenced_, const boost::uuids::uuid& referencedModuleId_) :
252 Exception(message_, defined_, definedModuleId_, referenced_, referencedModuleId_)
253 {
254 }
255
256 CastOverloadException::CastOverloadException(const std::string& message_, const Span& defined_, const boost::uuids::uuid& definedModuleId_,
257 const std::std::vector<std::std::pair<Span, boost::uuids::uuid>>&references_):Exception(message_, defined_, definedModuleId_, references_)
258 {
259 }
260
261 CannotBindConstToNonconstOverloadException::CannotBindConstToNonconstOverloadException(const std::string& message_, const Span& defined_, const boost::uuids::uuid& definedModuleId_) :
262 Exception(message_, defined_, definedModuleId_)
263 {
264 }
265
266 CannotBindConstToNonconstOverloadException::CannotBindConstToNonconstOverloadException(const std::string& message_, const Span& defined_, const boost::uuids::uuid& definedModuleId_,
267 const Span& referenced_, const boost::uuids::uuid& referencedModuleId_) :
268 Exception(message_, defined_, definedModuleId_, referenced_, referencedModuleId_)
269 {
270 }
271
272 CannotBindConstToNonconstOverloadException::CannotBindConstToNonconstOverloadException(const std::string& message_, const Span& defined_, const boost::uuids::uuid& definedModuleId_,
273 const std::std::vector<std::std::pair<Span, boost::uuids::uuid>>&references_):
274 Exception(message_, defined_, definedModuleId_, references_)
275 {
276 }
277
278 CannotAssignToConstOverloadException::CannotAssignToConstOverloadException(const std::string& message_, const Span& defined_, const boost::uuids::uuid& definedModuleId_) :
279 Exception(message_, defined_, definedModuleId_)
280 {
281 }
282
283 CannotAssignToConstOverloadException::CannotAssignToConstOverloadException(const std::string& message_, const Span& defined_, const boost::uuids::uuid& definedModuleId_,
284 const Span& referenced_, const boost::uuids::uuid& referencedModuleId_) :
285 Exception(message_, defined_, definedModuleId_, referenced_, referencedModuleId_)
286 {
287 }
288
289 CannotAssignToConstOverloadException::CannotAssignToConstOverloadException(const std::string& message_, const Span& defined_, const boost::uuids::uuid& definedModuleId_,
290 const std::std::vector<std::std::pair<Span, boost::uuids::uuid>>&references_):
291 Exception(message_, defined_, definedModuleId_, references_)
292 {
293 }
294
295 NoViableFunctionException::NoViableFunctionException(const std::string& message_, const Span& defined_, const boost::uuids::uuid& definedModuleId_) :
296 Exception(message_, defined_, definedModuleId_)
297 {
298 }
299
300 NoViableFunctionException::NoViableFunctionException(const std::string& message_, const Span& defined_, const boost::uuids::uuid& definedModuleId_,
301 const Span& referenced_, const boost::uuids::uuid& referencedModuleId_) :
302 Exception(message_, defined_, definedModuleId_, referenced_, referencedModuleId_)
303 {
304 }
305
306 NoViableFunctionException::NoViableFunctionException(const std::string& message_, const Span& defined_, const boost::uuids::uuid& definedModuleId_,
307 const std::std::vector<std::std::pair<Span, boost::uuids::uuid>>&references_):
308 Exception(message_, defined_, definedModuleId_, references_)
309 {
310 }
311
312 } }