1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  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& errorMessageconst Span& spanconst boost::uuids::uuid& moduleId)
 21 {
 22     std::vector<std::std::pair<Spanboost::uuids::uuid>>references;
 23     return Expand(errorMessagespanmoduleIdreferences);
 24 }
 25 
 26 std::string Expand(const std::string& errorMessageconst Span& primarySpanconst boost::uuids::uuid& primaryModuleId
 27     const Span& referenceSpanconst boost::uuids::uuid& referenceModuleId)
 28 {
 29     std::vector<std::std::pair<Spanboost::uuids::uuid>>references(1std::make_pair(referenceSpanreferenceModuleId));
 30     return Expand(errorMessageprimarySpanprimaryModuleIdreferences"Error");
 31 }
 32 
 33 std::string Expand(const std::string& errorMessageconst Span& primarySpanconst boost::uuids::uuid& primaryModuleId
 34     const Span& referenceSpanconst boost::uuids::uuid& referenceModuleIdconst std::string& title)
 35 {
 36     std::vector<std::std::pair<Spanboost::uuids::uuid>>references(1std::make_pair(referenceSpanreferenceModuleId));
 37     return Expand(errorMessageprimarySpanprimaryModuleIdreferencestitle);
 38 }
 39 
 40 std::string Expand(const std::string& errorMessageconst Span& spanconst boost::uuids::uuid& moduleIdconst std::std::vector<std::std::pair<Spanboost::uuids::uuid>>&references)
 41 {
 42     return Expand(errorMessagespanmoduleIdreferences"Error");
 43 }
 44 
 45 std::string Expand(const std::string& errorMessageconst Span& spanconst boost::uuids::uuid& moduleIdconst std::std::vector<std::std::pair<Spanboost::uuids::uuid>>&references
 46     const std::string& title)
 47 {
 48     std::vector<std::std::pair<Spanboost::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<Spanboost::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*moduleconstSpan&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(spanstartColendCol);
 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*moduleconstSpan&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(spanstartColendCol);
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<Spanboost::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(moduledefined);
171     if (ref)
172     {
173         refs->AddItem(std::move(ref));
174     }
175     std::vector<std::std::pair<Spanboost::uuids::uuid>>referenceSpans=references;
176     referenceSpans.erase(std::unique(referenceSpans.begin()referenceSpans.end())referenceSpans.end());
177     for (const std::std::pair<Spanboost::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(modreferenceSpanModuleId.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(moduledefined);
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<Spanboost::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(modspanModuleId.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* immutableModuleconst 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<Spanboost::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<Spanboost::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<Spanboost::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<Spanboost::uuids::uuid>>&references_):
308     Exception(message_defined_definedModuleId_references_)
309 {
310 }
311 
312 } } // namespace cmajor::symbols